Create WebViewDatabaseClassic from WebViewDatabase.
WebViewDatabase has a getInstance() method, so similarly
to WebStorage, WebIconDatabase etc we refactor it into a
proxy class, and move the current implementation into
WebViewDatabaseClassic.
Also clean up some JavaDoc in touched files.
Bug: 6234236
Change-Id: I71cbd8f78e60f396e96e8546073ad634797cce15
diff --git a/core/java/android/webkit/BrowserFrame.java b/core/java/android/webkit/BrowserFrame.java
index 7b6b54c..c169de4 100644
--- a/core/java/android/webkit/BrowserFrame.java
+++ b/core/java/android/webkit/BrowserFrame.java
@@ -72,7 +72,7 @@
private final CallbackProxy mCallbackProxy;
private final WebSettingsClassic mSettings;
private final Context mContext;
- private final WebViewDatabase mDatabase;
+ private final WebViewDatabaseClassic mDatabase;
private final WebViewCore mWebViewCore;
/* package */ boolean mLoadInitFromJava;
private int mLoadType;
@@ -241,7 +241,7 @@
mSettings = settings;
mContext = context;
mCallbackProxy = proxy;
- mDatabase = WebViewDatabase.getInstance(appContext);
+ mDatabase = WebViewDatabaseClassic.getInstance(appContext);
mWebViewCore = w;
mSearchBox = new SearchBoxImpl(mWebViewCore, mCallbackProxy);
@@ -496,8 +496,8 @@
if (item != null) {
WebAddress uri = new WebAddress(item.getUrl());
String schemePlusHost = uri.getScheme() + uri.getHost();
- String[] up =
- mDatabase.getUsernamePassword(schemePlusHost);
+ String[] up = mDatabase.getUsernamePassword(
+ schemePlusHost);
if (up != null && up[0] != null) {
setUsernamePassword(up[0], up[1]);
}
@@ -809,8 +809,7 @@
// non-null username implies that user has
// chosen to save password, so update the
// recorded password
- mDatabase.setUsernamePassword(
- schemePlusHost, username, password);
+ mDatabase.setUsernamePassword(schemePlusHost, username, password);
}
} else {
// CallbackProxy will handle creating the resume
diff --git a/core/java/android/webkit/WebViewClassic.java b/core/java/android/webkit/WebViewClassic.java
index 05b3e64..06057e4 100644
--- a/core/java/android/webkit/WebViewClassic.java
+++ b/core/java/android/webkit/WebViewClassic.java
@@ -701,7 +701,7 @@
// A final CallbackProxy shared by WebViewCore and BrowserFrame.
private CallbackProxy mCallbackProxy;
- private WebViewDatabase mDatabase;
+ private WebViewDatabaseClassic mDatabase;
// SSL certificate for the main top-level page (if secure)
private SslCertificate mCertificate;
@@ -1230,7 +1230,7 @@
mViewManager = new ViewManager(this);
L10nUtils.setApplicationContext(context.getApplicationContext());
mWebViewCore = new WebViewCore(context, this, mCallbackProxy, javaScriptInterfaces);
- mDatabase = WebViewDatabase.getInstance(context);
+ mDatabase = WebViewDatabaseClassic.getInstance(context);
mScroller = new OverScroller(context, null, 0, 0, false); //TODO Use OverScroller's flywheel
mZoomManager = new ZoomManager(this, mCallbackProxy);
@@ -1294,6 +1294,11 @@
public WebStorage getWebStorage() {
return WebStorageClassic.getInstance();
}
+
+ @Override
+ public WebViewDatabase getWebViewDatabase(Context context) {
+ return WebViewDatabaseClassic.getInstance(context);
+ }
}
private void onHandleUiEvent(MotionEvent event, int eventType, int flags) {
@@ -7191,8 +7196,7 @@
break;
}
case NEVER_REMEMBER_PASSWORD: {
- mDatabase.setUsernamePassword(
- msg.getData().getString("host"), null, null);
+ mDatabase.setUsernamePassword(msg.getData().getString("host"), null, null);
((Message) msg.obj).sendToTarget();
break;
}
diff --git a/core/java/android/webkit/WebViewDatabase.java b/core/java/android/webkit/WebViewDatabase.java
index 6c35f19..9d10d67 100644
--- a/core/java/android/webkit/WebViewDatabase.java
+++ b/core/java/android/webkit/WebViewDatabase.java
@@ -16,611 +16,79 @@
package android.webkit;
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Set;
-import java.util.Map.Entry;
-
-import android.content.ContentValues;
import android.content.Context;
-import android.database.Cursor;
-import android.database.DatabaseUtils;
-import android.database.sqlite.SQLiteDatabase;
-import android.database.sqlite.SQLiteException;
-import android.database.sqlite.SQLiteStatement;
-import android.util.Log;
+/**
+ * This class allows developers to determine whether any WebView used in the
+ * application has stored any of the following types of browsing data and
+ * to clear any such stored data for all WebViews in the application.
+ * <ul>
+ * <li>Username/password pairs entered into web forms</li>
+ * <li>HTTP authentication username/password pairs</li>
+ * <li>Data entered into text fields (e.g. for autocomplete suggestions)</li>
+ * </ul>
+ */
public class WebViewDatabase {
- private static final String DATABASE_FILE = "webview.db";
- private static final String CACHE_DATABASE_FILE = "webviewCache.db";
-
- // log tag
+ // TODO: deprecate/hide this.
protected static final String LOGTAG = "webviewdatabase";
- private static final int DATABASE_VERSION = 11;
- // 2 -> 3 Modified Cache table to allow cache of redirects
- // 3 -> 4 Added Oma-Downloads table
- // 4 -> 5 Modified Cache table to support persistent contentLength
- // 5 -> 4 Removed Oma-Downoads table
- // 5 -> 6 Add INDEX for cache table
- // 6 -> 7 Change cache localPath from int to String
- // 7 -> 8 Move cache to its own db
- // 8 -> 9 Store both scheme and host when storing passwords
- // 9 -> 10 Update httpauth table UNIQUE
- // 10 -> 11 Drop cookies and cache now managed by the chromium stack,
- // and update the form data table to use the new format
- // implemented for b/5265606.
-
- private static WebViewDatabase mInstance = null;
-
- private static SQLiteDatabase mDatabase = null;
-
- // synchronize locks
- private final Object mPasswordLock = new Object();
- private final Object mFormLock = new Object();
- private final Object mHttpAuthLock = new Object();
-
- private static final String mTableNames[] = {
- "password", "formurl", "formdata", "httpauth"
- };
-
- // Table ids (they are index to mTableNames)
- private static final int TABLE_PASSWORD_ID = 0;
- private static final int TABLE_FORMURL_ID = 1;
- private static final int TABLE_FORMDATA_ID = 2;
- private static final int TABLE_HTTPAUTH_ID = 3;
-
- // column id strings for "_id" which can be used by any table
- private static final String ID_COL = "_id";
-
- private static final String[] ID_PROJECTION = new String[] {
- "_id"
- };
-
- // column id strings for "password" table
- private static final String PASSWORD_HOST_COL = "host";
- private static final String PASSWORD_USERNAME_COL = "username";
- private static final String PASSWORD_PASSWORD_COL = "password";
-
- // column id strings for "formurl" table
- private static final String FORMURL_URL_COL = "url";
-
- // column id strings for "formdata" table
- private static final String FORMDATA_URLID_COL = "urlid";
- private static final String FORMDATA_NAME_COL = "name";
- private static final String FORMDATA_VALUE_COL = "value";
-
- // column id strings for "httpauth" table
- private static final String HTTPAUTH_HOST_COL = "host";
- private static final String HTTPAUTH_REALM_COL = "realm";
- private static final String HTTPAUTH_USERNAME_COL = "username";
- private static final String HTTPAUTH_PASSWORD_COL = "password";
-
- // Initially true until the background thread completes.
- private boolean mInitialized = false;
-
- private WebViewDatabase(final Context context) {
- new Thread() {
- @Override
- public void run() {
- init(context);
- }
- }.start();
-
- // Singleton only, use getInstance()
+ /**
+ * @hide Only for use by WebViewProvider implementations.
+ */
+ protected WebViewDatabase() {
}
public static synchronized WebViewDatabase getInstance(Context context) {
- if (mInstance == null) {
- mInstance = new WebViewDatabase(context);
- }
- return mInstance;
- }
-
- private synchronized void init(Context context) {
- if (mInitialized) {
- return;
- }
-
- initDatabase(context);
- // Before using the Chromium HTTP stack, we stored the WebKit cache in
- // our own DB. Clean up the DB file if it's still around.
- context.deleteDatabase(CACHE_DATABASE_FILE);
-
- // Thread done, notify.
- mInitialized = true;
- notify();
- }
-
- private void initDatabase(Context context) {
- try {
- mDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0, null);
- } catch (SQLiteException e) {
- // try again by deleting the old db and create a new one
- if (context.deleteDatabase(DATABASE_FILE)) {
- mDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0,
- null);
- }
- }
-
- // mDatabase should not be null,
- // the only case is RequestAPI test has problem to create db
- if (mDatabase == null) {
- mInitialized = true;
- notify();
- return;
- }
-
- if (mDatabase.getVersion() != DATABASE_VERSION) {
- mDatabase.beginTransactionNonExclusive();
- try {
- upgradeDatabase();
- mDatabase.setTransactionSuccessful();
- } finally {
- mDatabase.endTransaction();
- }
- }
- }
-
- private static void upgradeDatabase() {
- upgradeDatabaseToV10();
- upgradeDatabaseFromV10ToV11();
- // Add future database upgrade functions here, one version at a
- // time.
- mDatabase.setVersion(DATABASE_VERSION);
- }
-
- private static void upgradeDatabaseFromV10ToV11() {
- int oldVersion = mDatabase.getVersion();
-
- if (oldVersion >= 11) {
- // Nothing to do.
- return;
- }
-
- // Clear out old java stack cookies - this data is now stored in
- // a separate database managed by the Chrome stack.
- mDatabase.execSQL("DROP TABLE IF EXISTS cookies");
-
- // Likewise for the old cache table.
- mDatabase.execSQL("DROP TABLE IF EXISTS cache");
-
- // Update form autocomplete URLs to match new ICS formatting.
- Cursor c = mDatabase.query(mTableNames[TABLE_FORMURL_ID], null, null,
- null, null, null, null);
- while (c.moveToNext()) {
- String urlId = Long.toString(c.getLong(c.getColumnIndex(ID_COL)));
- String url = c.getString(c.getColumnIndex(FORMURL_URL_COL));
- ContentValues cv = new ContentValues(1);
- cv.put(FORMURL_URL_COL, WebTextView.urlForAutoCompleteData(url));
- mDatabase.update(mTableNames[TABLE_FORMURL_ID], cv, ID_COL + "=?",
- new String[] { urlId });
- }
- c.close();
- }
-
- private static void upgradeDatabaseToV10() {
- int oldVersion = mDatabase.getVersion();
-
- if (oldVersion >= 10) {
- // Nothing to do.
- return;
- }
-
- if (oldVersion != 0) {
- Log.i(LOGTAG, "Upgrading database from version "
- + oldVersion + " to "
- + DATABASE_VERSION + ", which will destroy old data");
- }
-
- if (9 == oldVersion) {
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_HTTPAUTH_ID]);
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
- + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
- + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
- + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
- + ") ON CONFLICT REPLACE);");
- return;
- }
-
- mDatabase.execSQL("DROP TABLE IF EXISTS cookies");
- mDatabase.execSQL("DROP TABLE IF EXISTS cache");
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_FORMURL_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_FORMDATA_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_HTTPAUTH_ID]);
- mDatabase.execSQL("DROP TABLE IF EXISTS "
- + mTableNames[TABLE_PASSWORD_ID]);
-
- // formurl
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMURL_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, " + FORMURL_URL_COL
- + " TEXT" + ");");
-
- // formdata
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMDATA_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + FORMDATA_URLID_COL + " INTEGER, " + FORMDATA_NAME_COL
- + " TEXT, " + FORMDATA_VALUE_COL + " TEXT," + " UNIQUE ("
- + FORMDATA_URLID_COL + ", " + FORMDATA_NAME_COL + ", "
- + FORMDATA_VALUE_COL + ") ON CONFLICT IGNORE);");
-
- // httpauth
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
- + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
- + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
- + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
- + ") ON CONFLICT REPLACE);");
- // passwords
- mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_PASSWORD_ID]
- + " (" + ID_COL + " INTEGER PRIMARY KEY, "
- + PASSWORD_HOST_COL + " TEXT, " + PASSWORD_USERNAME_COL
- + " TEXT, " + PASSWORD_PASSWORD_COL + " TEXT," + " UNIQUE ("
- + PASSWORD_HOST_COL + ", " + PASSWORD_USERNAME_COL
- + ") ON CONFLICT REPLACE);");
- }
-
- // Wait for the background initialization thread to complete and check the
- // database creation status.
- private boolean checkInitialized() {
- synchronized (this) {
- while (!mInitialized) {
- try {
- wait();
- } catch (InterruptedException e) {
- Log.e(LOGTAG, "Caught exception while checking " +
- "initialization");
- Log.e(LOGTAG, Log.getStackTraceString(e));
- }
- }
- }
- return mDatabase != null;
- }
-
- private boolean hasEntries(int tableId) {
- if (!checkInitialized()) {
- return false;
- }
-
- Cursor cursor = null;
- boolean ret = false;
- try {
- cursor = mDatabase.query(mTableNames[tableId], ID_PROJECTION,
- null, null, null, null, null);
- ret = cursor.moveToFirst() == true;
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "hasEntries", e);
- } finally {
- if (cursor != null) cursor.close();
- }
- return ret;
- }
-
- //
- // password functions
- //
-
- /**
- * Set password. Tuple (PASSWORD_HOST_COL, PASSWORD_USERNAME_COL) is unique.
- *
- * @param schemePlusHost The scheme and host for the password
- * @param username The username for the password. If it is null, it means
- * password can't be saved.
- * @param password The password
- */
- void setUsernamePassword(String schemePlusHost, String username,
- String password) {
- if (schemePlusHost == null || !checkInitialized()) {
- return;
- }
-
- synchronized (mPasswordLock) {
- final ContentValues c = new ContentValues();
- c.put(PASSWORD_HOST_COL, schemePlusHost);
- c.put(PASSWORD_USERNAME_COL, username);
- c.put(PASSWORD_PASSWORD_COL, password);
- mDatabase.insert(mTableNames[TABLE_PASSWORD_ID], PASSWORD_HOST_COL,
- c);
- }
+ return WebViewFactory.getProvider().getWebViewDatabase(context);
}
/**
- * Retrieve the username and password for a given host
+ * Gets whether there are any username/password combinations
+ * from web pages saved.
*
- * @param schemePlusHost The scheme and host which passwords applies to
- * @return String[] if found, String[0] is username, which can be null and
- * String[1] is password. Return null if it can't find anything.
- */
- String[] getUsernamePassword(String schemePlusHost) {
- if (schemePlusHost == null || !checkInitialized()) {
- return null;
- }
-
- final String[] columns = new String[] {
- PASSWORD_USERNAME_COL, PASSWORD_PASSWORD_COL
- };
- final String selection = "(" + PASSWORD_HOST_COL + " == ?)";
- synchronized (mPasswordLock) {
- String[] ret = null;
- Cursor cursor = null;
- try {
- cursor = mDatabase.query(mTableNames[TABLE_PASSWORD_ID],
- columns, selection, new String[] { schemePlusHost }, null,
- null, null);
- if (cursor.moveToFirst()) {
- ret = new String[2];
- ret[0] = cursor.getString(
- cursor.getColumnIndex(PASSWORD_USERNAME_COL));
- ret[1] = cursor.getString(
- cursor.getColumnIndex(PASSWORD_PASSWORD_COL));
- }
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "getUsernamePassword", e);
- } finally {
- if (cursor != null) cursor.close();
- }
- return ret;
- }
- }
-
- /**
- * Find out if there are any passwords saved.
- *
- * @return TRUE if there is passwords saved
+ * @return true if there are any username/passwords used in web
+ * forms saved
*/
public boolean hasUsernamePassword() {
- synchronized (mPasswordLock) {
- return hasEntries(TABLE_PASSWORD_ID);
- }
+ throw new MustOverrideException();
}
/**
- * Clear password database
+ * Clears any username/password combinations saved from web forms.
*/
public void clearUsernamePassword() {
- if (!checkInitialized()) {
- return;
- }
-
- synchronized (mPasswordLock) {
- mDatabase.delete(mTableNames[TABLE_PASSWORD_ID], null, null);
- }
- }
-
- //
- // http authentication password functions
- //
-
- /**
- * Set HTTP authentication password. Tuple (HTTPAUTH_HOST_COL,
- * HTTPAUTH_REALM_COL, HTTPAUTH_USERNAME_COL) is unique.
- *
- * @param host The host for the password
- * @param realm The realm for the password
- * @param username The username for the password. If it is null, it means
- * password can't be saved.
- * @param password The password
- */
- void setHttpAuthUsernamePassword(String host, String realm, String username,
- String password) {
- if (host == null || realm == null || !checkInitialized()) {
- return;
- }
-
- synchronized (mHttpAuthLock) {
- final ContentValues c = new ContentValues();
- c.put(HTTPAUTH_HOST_COL, host);
- c.put(HTTPAUTH_REALM_COL, realm);
- c.put(HTTPAUTH_USERNAME_COL, username);
- c.put(HTTPAUTH_PASSWORD_COL, password);
- mDatabase.insert(mTableNames[TABLE_HTTPAUTH_ID], HTTPAUTH_HOST_COL,
- c);
- }
+ throw new MustOverrideException();
}
/**
- * Retrieve the HTTP authentication username and password for a given
- * host+realm pair
+ * Gets whether there are any HTTP authentication username/password combinations saved.
*
- * @param host The host the password applies to
- * @param realm The realm the password applies to
- * @return String[] if found, String[0] is username, which can be null and
- * String[1] is password. Return null if it can't find anything.
- */
- String[] getHttpAuthUsernamePassword(String host, String realm) {
- if (host == null || realm == null || !checkInitialized()){
- return null;
- }
-
- final String[] columns = new String[] {
- HTTPAUTH_USERNAME_COL, HTTPAUTH_PASSWORD_COL
- };
- final String selection = "(" + HTTPAUTH_HOST_COL + " == ?) AND ("
- + HTTPAUTH_REALM_COL + " == ?)";
- synchronized (mHttpAuthLock) {
- String[] ret = null;
- Cursor cursor = null;
- try {
- cursor = mDatabase.query(mTableNames[TABLE_HTTPAUTH_ID],
- columns, selection, new String[] { host, realm }, null,
- null, null);
- if (cursor.moveToFirst()) {
- ret = new String[2];
- ret[0] = cursor.getString(
- cursor.getColumnIndex(HTTPAUTH_USERNAME_COL));
- ret[1] = cursor.getString(
- cursor.getColumnIndex(HTTPAUTH_PASSWORD_COL));
- }
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "getHttpAuthUsernamePassword", e);
- } finally {
- if (cursor != null) cursor.close();
- }
- return ret;
- }
- }
-
- /**
- * Find out if there are any HTTP authentication passwords saved.
- *
- * @return TRUE if there are passwords saved
+ * @return true if there are any HTTP authentication username/passwords saved
*/
public boolean hasHttpAuthUsernamePassword() {
- synchronized (mHttpAuthLock) {
- return hasEntries(TABLE_HTTPAUTH_ID);
- }
+ throw new MustOverrideException();
}
/**
- * Clear HTTP authentication password database
+ * Clears any HTTP authentication username/passwords that are saved.
*/
public void clearHttpAuthUsernamePassword() {
- if (!checkInitialized()) {
- return;
- }
-
- synchronized (mHttpAuthLock) {
- mDatabase.delete(mTableNames[TABLE_HTTPAUTH_ID], null, null);
- }
- }
-
- //
- // form data functions
- //
-
- /**
- * Set form data for a site. Tuple (FORMDATA_URLID_COL, FORMDATA_NAME_COL,
- * FORMDATA_VALUE_COL) is unique
- *
- * @param url The url of the site
- * @param formdata The form data in HashMap
- */
- void setFormData(String url, HashMap<String, String> formdata) {
- if (url == null || formdata == null || !checkInitialized()) {
- return;
- }
-
- final String selection = "(" + FORMURL_URL_COL + " == ?)";
- synchronized (mFormLock) {
- long urlid = -1;
- Cursor cursor = null;
- try {
- cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
- ID_PROJECTION, selection, new String[] { url }, null, null,
- null);
- if (cursor.moveToFirst()) {
- urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
- } else {
- ContentValues c = new ContentValues();
- c.put(FORMURL_URL_COL, url);
- urlid = mDatabase.insert(
- mTableNames[TABLE_FORMURL_ID], null, c);
- }
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "setFormData", e);
- } finally {
- if (cursor != null) cursor.close();
- }
- if (urlid >= 0) {
- Set<Entry<String, String>> set = formdata.entrySet();
- Iterator<Entry<String, String>> iter = set.iterator();
- ContentValues map = new ContentValues();
- map.put(FORMDATA_URLID_COL, urlid);
- while (iter.hasNext()) {
- Entry<String, String> entry = iter.next();
- map.put(FORMDATA_NAME_COL, entry.getKey());
- map.put(FORMDATA_VALUE_COL, entry.getValue());
- mDatabase.insert(mTableNames[TABLE_FORMDATA_ID], null, map);
- }
- }
- }
+ throw new MustOverrideException();
}
/**
- * Get all the values for a form entry with "name" in a given site
+ * Gets whether there is any previously-entered form data saved.
*
- * @param url The url of the site
- * @param name The name of the form entry
- * @return A list of values. Return empty list if nothing is found.
- */
- ArrayList<String> getFormData(String url, String name) {
- ArrayList<String> values = new ArrayList<String>();
- if (url == null || name == null || !checkInitialized()) {
- return values;
- }
-
- final String urlSelection = "(" + FORMURL_URL_COL + " == ?)";
- final String dataSelection = "(" + FORMDATA_URLID_COL + " == ?) AND ("
- + FORMDATA_NAME_COL + " == ?)";
- synchronized (mFormLock) {
- Cursor cursor = null;
- try {
- cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
- ID_PROJECTION, urlSelection, new String[] { url }, null,
- null, null);
- while (cursor.moveToNext()) {
- long urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
- Cursor dataCursor = null;
- try {
- dataCursor = mDatabase.query(
- mTableNames[TABLE_FORMDATA_ID],
- new String[] { ID_COL, FORMDATA_VALUE_COL },
- dataSelection,
- new String[] { Long.toString(urlid), name },
- null, null, null);
- if (dataCursor.moveToFirst()) {
- int valueCol = dataCursor.getColumnIndex(
- FORMDATA_VALUE_COL);
- do {
- values.add(dataCursor.getString(valueCol));
- } while (dataCursor.moveToNext());
- }
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "getFormData dataCursor", e);
- } finally {
- if (dataCursor != null) dataCursor.close();
- }
- }
- } catch (IllegalStateException e) {
- Log.e(LOGTAG, "getFormData cursor", e);
- } finally {
- if (cursor != null) cursor.close();
- }
- return values;
- }
- }
-
- /**
- * Find out if there is form data saved.
- *
- * @return TRUE if there is form data in the database
+ * @return true if there is form data saved
*/
public boolean hasFormData() {
- synchronized (mFormLock) {
- return hasEntries(TABLE_FORMURL_ID);
- }
+ throw new MustOverrideException();
}
/**
- * Clear form database
+ * Clears any stored previously-entered form data.
*/
public void clearFormData() {
- if (!checkInitialized()) {
- return;
- }
-
- synchronized (mFormLock) {
- mDatabase.delete(mTableNames[TABLE_FORMURL_ID], null, null);
- mDatabase.delete(mTableNames[TABLE_FORMDATA_ID], null, null);
- }
+ throw new MustOverrideException();
}
}
diff --git a/core/java/android/webkit/WebViewDatabaseClassic.java b/core/java/android/webkit/WebViewDatabaseClassic.java
new file mode 100644
index 0000000..9b1d4cb
--- /dev/null
+++ b/core/java/android/webkit/WebViewDatabaseClassic.java
@@ -0,0 +1,624 @@
+/*
+ * Copyright (C) 2012 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.webkit;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+import java.util.Map.Entry;
+
+import android.content.ContentValues;
+import android.content.Context;
+import android.database.Cursor;
+import android.database.DatabaseUtils;
+import android.database.sqlite.SQLiteDatabase;
+import android.database.sqlite.SQLiteException;
+import android.database.sqlite.SQLiteStatement;
+import android.util.Log;
+
+final class WebViewDatabaseClassic extends WebViewDatabase {
+ private static final String LOGTAG = "WebViewDatabaseClassic";
+ private static final String DATABASE_FILE = "webview.db";
+ private static final String CACHE_DATABASE_FILE = "webviewCache.db";
+
+ private static final int DATABASE_VERSION = 11;
+ // 2 -> 3 Modified Cache table to allow cache of redirects
+ // 3 -> 4 Added Oma-Downloads table
+ // 4 -> 5 Modified Cache table to support persistent contentLength
+ // 5 -> 4 Removed Oma-Downoads table
+ // 5 -> 6 Add INDEX for cache table
+ // 6 -> 7 Change cache localPath from int to String
+ // 7 -> 8 Move cache to its own db
+ // 8 -> 9 Store both scheme and host when storing passwords
+ // 9 -> 10 Update httpauth table UNIQUE
+ // 10 -> 11 Drop cookies and cache now managed by the chromium stack,
+ // and update the form data table to use the new format
+ // implemented for b/5265606.
+
+ private static WebViewDatabaseClassic sInstance = null;
+
+ private static SQLiteDatabase sDatabase = null;
+
+ // synchronize locks
+ private final Object mPasswordLock = new Object();
+ private final Object mFormLock = new Object();
+ private final Object mHttpAuthLock = new Object();
+
+ private static final String mTableNames[] = {
+ "password", "formurl", "formdata", "httpauth"
+ };
+
+ // Table ids (they are index to mTableNames)
+ private static final int TABLE_PASSWORD_ID = 0;
+ private static final int TABLE_FORMURL_ID = 1;
+ private static final int TABLE_FORMDATA_ID = 2;
+ private static final int TABLE_HTTPAUTH_ID = 3;
+
+ // column id strings for "_id" which can be used by any table
+ private static final String ID_COL = "_id";
+
+ private static final String[] ID_PROJECTION = new String[] {
+ "_id"
+ };
+
+ // column id strings for "password" table
+ private static final String PASSWORD_HOST_COL = "host";
+ private static final String PASSWORD_USERNAME_COL = "username";
+ private static final String PASSWORD_PASSWORD_COL = "password";
+
+ // column id strings for "formurl" table
+ private static final String FORMURL_URL_COL = "url";
+
+ // column id strings for "formdata" table
+ private static final String FORMDATA_URLID_COL = "urlid";
+ private static final String FORMDATA_NAME_COL = "name";
+ private static final String FORMDATA_VALUE_COL = "value";
+
+ // column id strings for "httpauth" table
+ private static final String HTTPAUTH_HOST_COL = "host";
+ private static final String HTTPAUTH_REALM_COL = "realm";
+ private static final String HTTPAUTH_USERNAME_COL = "username";
+ private static final String HTTPAUTH_PASSWORD_COL = "password";
+
+ // Initially true until the background thread completes.
+ private boolean mInitialized = false;
+
+ WebViewDatabaseClassic(final Context context) {
+ new Thread() {
+ @Override
+ public void run() {
+ init(context);
+ }
+ }.start();
+
+ // Singleton only, use getInstance()
+ }
+
+ public static synchronized WebViewDatabaseClassic getInstance(Context context) {
+ if (sInstance == null) {
+ sInstance = new WebViewDatabaseClassic(context);
+ }
+ return sInstance;
+ }
+
+ private synchronized void init(Context context) {
+ if (mInitialized) {
+ return;
+ }
+
+ initDatabase(context);
+ // Before using the Chromium HTTP stack, we stored the WebKit cache in
+ // our own DB. Clean up the DB file if it's still around.
+ context.deleteDatabase(CACHE_DATABASE_FILE);
+
+ // Thread done, notify.
+ mInitialized = true;
+ notify();
+ }
+
+ private void initDatabase(Context context) {
+ try {
+ sDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0, null);
+ } catch (SQLiteException e) {
+ // try again by deleting the old db and create a new one
+ if (context.deleteDatabase(DATABASE_FILE)) {
+ sDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0,
+ null);
+ }
+ }
+
+ // sDatabase should not be null,
+ // the only case is RequestAPI test has problem to create db
+ if (sDatabase == null) {
+ mInitialized = true;
+ notify();
+ return;
+ }
+
+ if (sDatabase.getVersion() != DATABASE_VERSION) {
+ sDatabase.beginTransactionNonExclusive();
+ try {
+ upgradeDatabase();
+ sDatabase.setTransactionSuccessful();
+ } finally {
+ sDatabase.endTransaction();
+ }
+ }
+ }
+
+ private static void upgradeDatabase() {
+ upgradeDatabaseToV10();
+ upgradeDatabaseFromV10ToV11();
+ // Add future database upgrade functions here, one version at a
+ // time.
+ sDatabase.setVersion(DATABASE_VERSION);
+ }
+
+ private static void upgradeDatabaseFromV10ToV11() {
+ int oldVersion = sDatabase.getVersion();
+
+ if (oldVersion >= 11) {
+ // Nothing to do.
+ return;
+ }
+
+ // Clear out old java stack cookies - this data is now stored in
+ // a separate database managed by the Chrome stack.
+ sDatabase.execSQL("DROP TABLE IF EXISTS cookies");
+
+ // Likewise for the old cache table.
+ sDatabase.execSQL("DROP TABLE IF EXISTS cache");
+
+ // Update form autocomplete URLs to match new ICS formatting.
+ Cursor c = sDatabase.query(mTableNames[TABLE_FORMURL_ID], null, null,
+ null, null, null, null);
+ while (c.moveToNext()) {
+ String urlId = Long.toString(c.getLong(c.getColumnIndex(ID_COL)));
+ String url = c.getString(c.getColumnIndex(FORMURL_URL_COL));
+ ContentValues cv = new ContentValues(1);
+ cv.put(FORMURL_URL_COL, WebTextView.urlForAutoCompleteData(url));
+ sDatabase.update(mTableNames[TABLE_FORMURL_ID], cv, ID_COL + "=?",
+ new String[] { urlId });
+ }
+ c.close();
+ }
+
+ private static void upgradeDatabaseToV10() {
+ int oldVersion = sDatabase.getVersion();
+
+ if (oldVersion >= 10) {
+ // Nothing to do.
+ return;
+ }
+
+ if (oldVersion != 0) {
+ Log.i(LOGTAG, "Upgrading database from version "
+ + oldVersion + " to "
+ + DATABASE_VERSION + ", which will destroy old data");
+ }
+
+ if (9 == oldVersion) {
+ sDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_HTTPAUTH_ID]);
+ sDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+ + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
+ + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
+ + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
+ + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
+ + ") ON CONFLICT REPLACE);");
+ return;
+ }
+
+ sDatabase.execSQL("DROP TABLE IF EXISTS cookies");
+ sDatabase.execSQL("DROP TABLE IF EXISTS cache");
+ sDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_FORMURL_ID]);
+ sDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_FORMDATA_ID]);
+ sDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_HTTPAUTH_ID]);
+ sDatabase.execSQL("DROP TABLE IF EXISTS "
+ + mTableNames[TABLE_PASSWORD_ID]);
+
+ // formurl
+ sDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMURL_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, " + FORMURL_URL_COL
+ + " TEXT" + ");");
+
+ // formdata
+ sDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMDATA_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+ + FORMDATA_URLID_COL + " INTEGER, " + FORMDATA_NAME_COL
+ + " TEXT, " + FORMDATA_VALUE_COL + " TEXT," + " UNIQUE ("
+ + FORMDATA_URLID_COL + ", " + FORMDATA_NAME_COL + ", "
+ + FORMDATA_VALUE_COL + ") ON CONFLICT IGNORE);");
+
+ // httpauth
+ sDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+ + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
+ + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
+ + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
+ + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
+ + ") ON CONFLICT REPLACE);");
+ // passwords
+ sDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_PASSWORD_ID]
+ + " (" + ID_COL + " INTEGER PRIMARY KEY, "
+ + PASSWORD_HOST_COL + " TEXT, " + PASSWORD_USERNAME_COL
+ + " TEXT, " + PASSWORD_PASSWORD_COL + " TEXT," + " UNIQUE ("
+ + PASSWORD_HOST_COL + ", " + PASSWORD_USERNAME_COL
+ + ") ON CONFLICT REPLACE);");
+ }
+
+ // Wait for the background initialization thread to complete and check the
+ // database creation status.
+ private boolean checkInitialized() {
+ synchronized (this) {
+ while (!mInitialized) {
+ try {
+ wait();
+ } catch (InterruptedException e) {
+ Log.e(LOGTAG, "Caught exception while checking " +
+ "initialization");
+ Log.e(LOGTAG, Log.getStackTraceString(e));
+ }
+ }
+ }
+ return sDatabase != null;
+ }
+
+ private boolean hasEntries(int tableId) {
+ if (!checkInitialized()) {
+ return false;
+ }
+
+ Cursor cursor = null;
+ boolean ret = false;
+ try {
+ cursor = sDatabase.query(mTableNames[tableId], ID_PROJECTION,
+ null, null, null, null, null);
+ ret = cursor.moveToFirst() == true;
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "hasEntries", e);
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ return ret;
+ }
+
+ //
+ // password functions
+ //
+
+ /**
+ * Set password. Tuple (PASSWORD_HOST_COL, PASSWORD_USERNAME_COL) is unique.
+ *
+ * @param schemePlusHost The scheme and host for the password
+ * @param username The username for the password. If it is null, it means
+ * password can't be saved.
+ * @param password The password
+ */
+ void setUsernamePassword(String schemePlusHost, String username,
+ String password) {
+ if (schemePlusHost == null || !checkInitialized()) {
+ return;
+ }
+
+ synchronized (mPasswordLock) {
+ final ContentValues c = new ContentValues();
+ c.put(PASSWORD_HOST_COL, schemePlusHost);
+ c.put(PASSWORD_USERNAME_COL, username);
+ c.put(PASSWORD_PASSWORD_COL, password);
+ sDatabase.insert(mTableNames[TABLE_PASSWORD_ID], PASSWORD_HOST_COL,
+ c);
+ }
+ }
+
+ /**
+ * Retrieve the username and password for a given host
+ *
+ * @param schemePlusHost The scheme and host which passwords applies to
+ * @return String[] if found, String[0] is username, which can be null and
+ * String[1] is password. Return null if it can't find anything.
+ */
+ String[] getUsernamePassword(String schemePlusHost) {
+ if (schemePlusHost == null || !checkInitialized()) {
+ return null;
+ }
+
+ final String[] columns = new String[] {
+ PASSWORD_USERNAME_COL, PASSWORD_PASSWORD_COL
+ };
+ final String selection = "(" + PASSWORD_HOST_COL + " == ?)";
+ synchronized (mPasswordLock) {
+ String[] ret = null;
+ Cursor cursor = null;
+ try {
+ cursor = sDatabase.query(mTableNames[TABLE_PASSWORD_ID],
+ columns, selection, new String[] { schemePlusHost }, null,
+ null, null);
+ if (cursor.moveToFirst()) {
+ ret = new String[2];
+ ret[0] = cursor.getString(
+ cursor.getColumnIndex(PASSWORD_USERNAME_COL));
+ ret[1] = cursor.getString(
+ cursor.getColumnIndex(PASSWORD_PASSWORD_COL));
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getUsernamePassword", e);
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ return ret;
+ }
+ }
+
+ /**
+ * @see WebViewDatabase#hasUsernamePassword
+ */
+ @Override
+ public boolean hasUsernamePassword() {
+ synchronized (mPasswordLock) {
+ return hasEntries(TABLE_PASSWORD_ID);
+ }
+ }
+
+ /**
+ * @see WebViewDatabase#clearUsernamePassword
+ */
+ @Override
+ public void clearUsernamePassword() {
+ if (!checkInitialized()) {
+ return;
+ }
+
+ synchronized (mPasswordLock) {
+ sDatabase.delete(mTableNames[TABLE_PASSWORD_ID], null, null);
+ }
+ }
+
+ //
+ // http authentication password functions
+ //
+
+ /**
+ * Set HTTP authentication password. Tuple (HTTPAUTH_HOST_COL,
+ * HTTPAUTH_REALM_COL, HTTPAUTH_USERNAME_COL) is unique.
+ *
+ * @param host The host for the password
+ * @param realm The realm for the password
+ * @param username The username for the password. If it is null, it means
+ * password can't be saved.
+ * @param password The password
+ */
+ void setHttpAuthUsernamePassword(String host, String realm, String username,
+ String password) {
+ if (host == null || realm == null || !checkInitialized()) {
+ return;
+ }
+
+ synchronized (mHttpAuthLock) {
+ final ContentValues c = new ContentValues();
+ c.put(HTTPAUTH_HOST_COL, host);
+ c.put(HTTPAUTH_REALM_COL, realm);
+ c.put(HTTPAUTH_USERNAME_COL, username);
+ c.put(HTTPAUTH_PASSWORD_COL, password);
+ sDatabase.insert(mTableNames[TABLE_HTTPAUTH_ID], HTTPAUTH_HOST_COL,
+ c);
+ }
+ }
+
+ /**
+ * Retrieve the HTTP authentication username and password for a given
+ * host+realm pair
+ *
+ * @param host The host the password applies to
+ * @param realm The realm the password applies to
+ * @return String[] if found, String[0] is username, which can be null and
+ * String[1] is password. Return null if it can't find anything.
+ */
+ String[] getHttpAuthUsernamePassword(String host, String realm) {
+ if (host == null || realm == null || !checkInitialized()){
+ return null;
+ }
+
+ final String[] columns = new String[] {
+ HTTPAUTH_USERNAME_COL, HTTPAUTH_PASSWORD_COL
+ };
+ final String selection = "(" + HTTPAUTH_HOST_COL + " == ?) AND ("
+ + HTTPAUTH_REALM_COL + " == ?)";
+ synchronized (mHttpAuthLock) {
+ String[] ret = null;
+ Cursor cursor = null;
+ try {
+ cursor = sDatabase.query(mTableNames[TABLE_HTTPAUTH_ID],
+ columns, selection, new String[] { host, realm }, null,
+ null, null);
+ if (cursor.moveToFirst()) {
+ ret = new String[2];
+ ret[0] = cursor.getString(
+ cursor.getColumnIndex(HTTPAUTH_USERNAME_COL));
+ ret[1] = cursor.getString(
+ cursor.getColumnIndex(HTTPAUTH_PASSWORD_COL));
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getHttpAuthUsernamePassword", e);
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ return ret;
+ }
+ }
+
+ /**
+ * @see WebViewDatabase#hasHttpAuthUsernamePassword
+ */
+ @Override
+ public boolean hasHttpAuthUsernamePassword() {
+ synchronized (mHttpAuthLock) {
+ return hasEntries(TABLE_HTTPAUTH_ID);
+ }
+ }
+
+ /**
+ * @see WebViewDatabase#clearHttpAuthUsernamePassword
+ */
+ @Override
+ public void clearHttpAuthUsernamePassword() {
+ if (!checkInitialized()) {
+ return;
+ }
+
+ synchronized (mHttpAuthLock) {
+ sDatabase.delete(mTableNames[TABLE_HTTPAUTH_ID], null, null);
+ }
+ }
+
+ //
+ // form data functions
+ //
+
+ /**
+ * Set form data for a site. Tuple (FORMDATA_URLID_COL, FORMDATA_NAME_COL,
+ * FORMDATA_VALUE_COL) is unique
+ *
+ * @param url The url of the site
+ * @param formdata The form data in HashMap
+ */
+ void setFormData(String url, HashMap<String, String> formdata) {
+ if (url == null || formdata == null || !checkInitialized()) {
+ return;
+ }
+
+ final String selection = "(" + FORMURL_URL_COL + " == ?)";
+ synchronized (mFormLock) {
+ long urlid = -1;
+ Cursor cursor = null;
+ try {
+ cursor = sDatabase.query(mTableNames[TABLE_FORMURL_ID],
+ ID_PROJECTION, selection, new String[] { url }, null, null,
+ null);
+ if (cursor.moveToFirst()) {
+ urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
+ } else {
+ ContentValues c = new ContentValues();
+ c.put(FORMURL_URL_COL, url);
+ urlid = sDatabase.insert(
+ mTableNames[TABLE_FORMURL_ID], null, c);
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "setFormData", e);
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ if (urlid >= 0) {
+ Set<Entry<String, String>> set = formdata.entrySet();
+ Iterator<Entry<String, String>> iter = set.iterator();
+ ContentValues map = new ContentValues();
+ map.put(FORMDATA_URLID_COL, urlid);
+ while (iter.hasNext()) {
+ Entry<String, String> entry = iter.next();
+ map.put(FORMDATA_NAME_COL, entry.getKey());
+ map.put(FORMDATA_VALUE_COL, entry.getValue());
+ sDatabase.insert(mTableNames[TABLE_FORMDATA_ID], null, map);
+ }
+ }
+ }
+ }
+
+ /**
+ * Get all the values for a form entry with "name" in a given site
+ *
+ * @param url The url of the site
+ * @param name The name of the form entry
+ * @return A list of values. Return empty list if nothing is found.
+ */
+ ArrayList<String> getFormData(String url, String name) {
+ ArrayList<String> values = new ArrayList<String>();
+ if (url == null || name == null || !checkInitialized()) {
+ return values;
+ }
+
+ final String urlSelection = "(" + FORMURL_URL_COL + " == ?)";
+ final String dataSelection = "(" + FORMDATA_URLID_COL + " == ?) AND ("
+ + FORMDATA_NAME_COL + " == ?)";
+ synchronized (mFormLock) {
+ Cursor cursor = null;
+ try {
+ cursor = sDatabase.query(mTableNames[TABLE_FORMURL_ID],
+ ID_PROJECTION, urlSelection, new String[] { url }, null,
+ null, null);
+ while (cursor.moveToNext()) {
+ long urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
+ Cursor dataCursor = null;
+ try {
+ dataCursor = sDatabase.query(
+ mTableNames[TABLE_FORMDATA_ID],
+ new String[] { ID_COL, FORMDATA_VALUE_COL },
+ dataSelection,
+ new String[] { Long.toString(urlid), name },
+ null, null, null);
+ if (dataCursor.moveToFirst()) {
+ int valueCol = dataCursor.getColumnIndex(
+ FORMDATA_VALUE_COL);
+ do {
+ values.add(dataCursor.getString(valueCol));
+ } while (dataCursor.moveToNext());
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getFormData dataCursor", e);
+ } finally {
+ if (dataCursor != null) dataCursor.close();
+ }
+ }
+ } catch (IllegalStateException e) {
+ Log.e(LOGTAG, "getFormData cursor", e);
+ } finally {
+ if (cursor != null) cursor.close();
+ }
+ return values;
+ }
+ }
+
+ /**
+ * @see WebViewDatabase#hasFormData
+ */
+ @Override
+ public boolean hasFormData() {
+ synchronized (mFormLock) {
+ return hasEntries(TABLE_FORMURL_ID);
+ }
+ }
+
+ /**
+ * @see WebViewDatabase#clearFormData
+ */
+ @Override
+ public void clearFormData() {
+ if (!checkInitialized()) {
+ return;
+ }
+
+ synchronized (mFormLock) {
+ sDatabase.delete(mTableNames[TABLE_FORMURL_ID], null, null);
+ sDatabase.delete(mTableNames[TABLE_FORMDATA_ID], null, null);
+ }
+ }
+}
diff --git a/core/java/android/webkit/WebViewFactoryProvider.java b/core/java/android/webkit/WebViewFactoryProvider.java
index a832b0a..1d302f1 100644
--- a/core/java/android/webkit/WebViewFactoryProvider.java
+++ b/core/java/android/webkit/WebViewFactoryProvider.java
@@ -16,6 +16,8 @@
package android.webkit;
+import android.content.Context;
+
/**
* This is the main entry-point into the WebView back end implementations, which the WebView
* proxy class uses to instantiate all the other objects as needed. The backend must provide an
@@ -63,21 +65,32 @@
/**
* Gets the singleton CookieManager instance for this WebView implementation. The
* implementation must return the same instance on subsequent calls.
- * @return the singleton CookieManager instance.
+ *
+ * @return the singleton CookieManager instance
*/
CookieManager getCookieManager();
/**
* Gets the singleton WebIconDatabase instance for this WebView implementation. The
* implementation must return the same instance on subsequent calls.
- * @return the singleton WebIconDatabase instance.
+ *
+ * @return the singleton WebIconDatabase instance
*/
WebIconDatabase getWebIconDatabase();
/**
* Gets the singleton WebStorage instance for this WebView implementation. The
* implementation must return the same instance on subsequent calls.
- * @return the singleton WebStorage instance.
+ *
+ * @return the singleton WebStorage instance
*/
WebStorage getWebStorage();
+
+ /**
+ * Gets the singleton WebViewDatabase instance for this WebView implementation. The
+ * implementation must return the same instance on subsequent calls.
+ *
+ * @return the singleton WebViewDatabase instance
+ */
+ WebViewDatabase getWebViewDatabase(Context context);
}