199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch/*
299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch * Copyright (C) 2012 The Android Open Source Project
399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch *
499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch * Licensed under the Apache License, Version 2.0 (the "License");
599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch * you may not use this file except in compliance with the License.
699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch * You may obtain a copy of the License at
799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch *
899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch *      http://www.apache.org/licenses/LICENSE-2.0
999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch *
1099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch * Unless required by applicable law or agreed to in writing, software
1199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch * distributed under the License is distributed on an "AS IS" BASIS,
1299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
1399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch * See the License for the specific language governing permissions and
1499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch * limitations under the License.
1599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch */
1699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
1799c12e8d5f12f239c28644a837937810299e5e3fBen Murdochpackage android.webkit;
1899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
1999c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport java.util.ArrayList;
2099c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport java.util.HashMap;
2199c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport java.util.Iterator;
2299c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport java.util.List;
2399c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport java.util.Set;
2499c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport java.util.Map.Entry;
2599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
2699c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport android.content.ContentValues;
2799c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport android.content.Context;
2899c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport android.database.Cursor;
2999c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport android.database.DatabaseUtils;
3099c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport android.database.sqlite.SQLiteDatabase;
3199c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport android.database.sqlite.SQLiteException;
3299c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport android.database.sqlite.SQLiteStatement;
3399c12e8d5f12f239c28644a837937810299e5e3fBen Murdochimport android.util.Log;
3499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
3599c12e8d5f12f239c28644a837937810299e5e3fBen Murdochfinal class WebViewDatabaseClassic extends WebViewDatabase {
3699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String LOGTAG = "WebViewDatabaseClassic";
3799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String DATABASE_FILE = "webview.db";
3899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String CACHE_DATABASE_FILE = "webviewCache.db";
3999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
4099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final int DATABASE_VERSION = 11;
4199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // 2 -> 3 Modified Cache table to allow cache of redirects
4299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // 3 -> 4 Added Oma-Downloads table
4399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // 4 -> 5 Modified Cache table to support persistent contentLength
4499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // 5 -> 4 Removed Oma-Downoads table
4599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // 5 -> 6 Add INDEX for cache table
4699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // 6 -> 7 Change cache localPath from int to String
4799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // 7 -> 8 Move cache to its own db
4899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // 8 -> 9 Store both scheme and host when storing passwords
4999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // 9 -> 10 Update httpauth table UNIQUE
5099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // 10 -> 11 Drop cookies and cache now managed by the chromium stack,
5199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    //          and update the form data table to use the new format
5299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    //          implemented for b/5265606.
5399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
5499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static WebViewDatabaseClassic sInstance = null;
559f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck    private static final Object sInstanceLock = new Object();
5699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
5799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static SQLiteDatabase sDatabase = null;
5899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
5999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // synchronize locks
6099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private final Object mPasswordLock = new Object();
6199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private final Object mFormLock = new Object();
6299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private final Object mHttpAuthLock = new Object();
6399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
6499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String mTableNames[] = {
6599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        "password", "formurl", "formdata", "httpauth"
6699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    };
6799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
6899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // Table ids (they are index to mTableNames)
6999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final int TABLE_PASSWORD_ID = 0;
7099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final int TABLE_FORMURL_ID = 1;
7199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final int TABLE_FORMDATA_ID = 2;
7299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final int TABLE_HTTPAUTH_ID = 3;
7399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
7499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // column id strings for "_id" which can be used by any table
7599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String ID_COL = "_id";
7699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
7799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String[] ID_PROJECTION = new String[] {
7899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        "_id"
7999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    };
8099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
8199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // column id strings for "password" table
8299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String PASSWORD_HOST_COL = "host";
8399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String PASSWORD_USERNAME_COL = "username";
8499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String PASSWORD_PASSWORD_COL = "password";
8599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
8699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // column id strings for "formurl" table
8799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String FORMURL_URL_COL = "url";
8899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
8999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // column id strings for "formdata" table
9099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String FORMDATA_URLID_COL = "urlid";
9199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String FORMDATA_NAME_COL = "name";
9299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String FORMDATA_VALUE_COL = "value";
9399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
9499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // column id strings for "httpauth" table
9599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String HTTPAUTH_HOST_COL = "host";
9699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String HTTPAUTH_REALM_COL = "realm";
9799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String HTTPAUTH_USERNAME_COL = "username";
9899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static final String HTTPAUTH_PASSWORD_COL = "password";
9999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
10099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // Initially true until the background thread completes.
10199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private boolean mInitialized = false;
10299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
1039f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck    private WebViewDatabaseClassic(final Context context) {
10473eeb7b5ed5f88750156b787c665f7d3769fc56aJonathan Dixon        JniUtil.setContext(context);
10599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        new Thread() {
10699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            @Override
10799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            public void run() {
10899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                init(context);
10999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            }
11099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }.start();
11199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
11299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // Singleton only, use getInstance()
11399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
11499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
1159f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck    public static WebViewDatabaseClassic getInstance(Context context) {
1169f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck        synchronized (sInstanceLock) {
1179f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck            if (sInstance == null) {
1189f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck                sInstance = new WebViewDatabaseClassic(context);
1199f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck            }
1209f9d34552f53c534141584a5ad4a8a49ad7939dcJohn Reck            return sInstance;
12199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
12299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
12399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
12499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private synchronized void init(Context context) {
12599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (mInitialized) {
12699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return;
12799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
12899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
12999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        initDatabase(context);
13099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // Before using the Chromium HTTP stack, we stored the WebKit cache in
13199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // our own DB. Clean up the DB file if it's still around.
13299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        context.deleteDatabase(CACHE_DATABASE_FILE);
13399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
13499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // Thread done, notify.
13599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        mInitialized = true;
13699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        notify();
13799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
13899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
13999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private void initDatabase(Context context) {
14099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        try {
14199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            sDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0, null);
14299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        } catch (SQLiteException e) {
14399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            // try again by deleting the old db and create a new one
14499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            if (context.deleteDatabase(DATABASE_FILE)) {
14599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                sDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0,
14699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        null);
14799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            }
14899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
14999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
15099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // sDatabase should not be null,
15199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // the only case is RequestAPI test has problem to create db
15299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (sDatabase == null) {
15399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            mInitialized = true;
15499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            notify();
15599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return;
15699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
15799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
15899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (sDatabase.getVersion() != DATABASE_VERSION) {
15999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            sDatabase.beginTransactionNonExclusive();
16099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            try {
16199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                upgradeDatabase();
16299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                sDatabase.setTransactionSuccessful();
16399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            } finally {
16499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                sDatabase.endTransaction();
16599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            }
16699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
16799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
16899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
16999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static void upgradeDatabase() {
17099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        upgradeDatabaseToV10();
17199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        upgradeDatabaseFromV10ToV11();
17299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // Add future database upgrade functions here, one version at a
17399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // time.
17499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.setVersion(DATABASE_VERSION);
17599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
17699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
17799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static void upgradeDatabaseFromV10ToV11() {
17899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        int oldVersion = sDatabase.getVersion();
17999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
18099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (oldVersion >= 11) {
18199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            // Nothing to do.
18299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return;
18399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
18499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
18599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // Clear out old java stack cookies - this data is now stored in
18699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // a separate database managed by the Chrome stack.
18799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("DROP TABLE IF EXISTS cookies");
18899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
18999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // Likewise for the old cache table.
19099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("DROP TABLE IF EXISTS cache");
19199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
19299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // Update form autocomplete  URLs to match new ICS formatting.
19399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        Cursor c = sDatabase.query(mTableNames[TABLE_FORMURL_ID], null, null,
19499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                null, null, null, null);
19599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        while (c.moveToNext()) {
19699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            String urlId = Long.toString(c.getLong(c.getColumnIndex(ID_COL)));
19799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            String url = c.getString(c.getColumnIndex(FORMURL_URL_COL));
19899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            ContentValues cv = new ContentValues(1);
19999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            cv.put(FORMURL_URL_COL, WebTextView.urlForAutoCompleteData(url));
20099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            sDatabase.update(mTableNames[TABLE_FORMURL_ID], cv, ID_COL + "=?",
20199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    new String[] { urlId });
20299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
20399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        c.close();
20499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
20599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
20699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private static void upgradeDatabaseToV10() {
20799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        int oldVersion = sDatabase.getVersion();
20899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
20999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (oldVersion >= 10) {
21099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            // Nothing to do.
21199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return;
21299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
21399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
21499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (oldVersion != 0) {
21599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            Log.i(LOGTAG, "Upgrading database from version "
21699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    + oldVersion + " to "
21799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    + DATABASE_VERSION + ", which will destroy old data");
21899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
21999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
22099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (9 == oldVersion) {
22199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            sDatabase.execSQL("DROP TABLE IF EXISTS "
22299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    + mTableNames[TABLE_HTTPAUTH_ID]);
22399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            sDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
22499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    + " (" + ID_COL + " INTEGER PRIMARY KEY, "
22599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
22699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
22799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
22899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
22999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    + ") ON CONFLICT REPLACE);");
23099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return;
23199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
23299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
23399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("DROP TABLE IF EXISTS cookies");
23499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("DROP TABLE IF EXISTS cache");
23599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("DROP TABLE IF EXISTS "
23699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + mTableNames[TABLE_FORMURL_ID]);
23799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("DROP TABLE IF EXISTS "
23899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + mTableNames[TABLE_FORMDATA_ID]);
23999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("DROP TABLE IF EXISTS "
24099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + mTableNames[TABLE_HTTPAUTH_ID]);
24199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("DROP TABLE IF EXISTS "
24299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + mTableNames[TABLE_PASSWORD_ID]);
24399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
24499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // formurl
24599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMURL_ID]
24699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + " (" + ID_COL + " INTEGER PRIMARY KEY, " + FORMURL_URL_COL
24799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + " TEXT" + ");");
24899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
24999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // formdata
25099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMDATA_ID]
25199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + " (" + ID_COL + " INTEGER PRIMARY KEY, "
25299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + FORMDATA_URLID_COL + " INTEGER, " + FORMDATA_NAME_COL
25399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + " TEXT, " + FORMDATA_VALUE_COL + " TEXT," + " UNIQUE ("
25499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + FORMDATA_URLID_COL + ", " + FORMDATA_NAME_COL + ", "
25599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + FORMDATA_VALUE_COL + ") ON CONFLICT IGNORE);");
25699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
25799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // httpauth
25899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
25999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + " (" + ID_COL + " INTEGER PRIMARY KEY, "
26099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
26199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
26299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
26399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
26499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + ") ON CONFLICT REPLACE);");
26599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        // passwords
26699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        sDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_PASSWORD_ID]
26799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + " (" + ID_COL + " INTEGER PRIMARY KEY, "
26899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + PASSWORD_HOST_COL + " TEXT, " + PASSWORD_USERNAME_COL
26999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + " TEXT, " + PASSWORD_PASSWORD_COL + " TEXT," + " UNIQUE ("
27099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + PASSWORD_HOST_COL + ", " + PASSWORD_USERNAME_COL
27199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + ") ON CONFLICT REPLACE);");
27299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
27399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
27499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // Wait for the background initialization thread to complete and check the
27599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // database creation status.
27699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private boolean checkInitialized() {
27799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (this) {
27899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            while (!mInitialized) {
27999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                try {
28099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    wait();
28199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                } catch (InterruptedException e) {
28299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    Log.e(LOGTAG, "Caught exception while checking " +
28399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                                  "initialization");
28499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    Log.e(LOGTAG, Log.getStackTraceString(e));
28599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                }
28699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            }
28799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
28899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        return sDatabase != null;
28999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
29099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
29199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    private boolean hasEntries(int tableId) {
29299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (!checkInitialized()) {
29399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return false;
29499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
29599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
29699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        Cursor cursor = null;
29799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        boolean ret = false;
29899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        try {
29999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            cursor = sDatabase.query(mTableNames[tableId], ID_PROJECTION,
30099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    null, null, null, null, null);
30199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            ret = cursor.moveToFirst() == true;
30299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        } catch (IllegalStateException e) {
30399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            Log.e(LOGTAG, "hasEntries", e);
30499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        } finally {
30599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            if (cursor != null) cursor.close();
30699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
30799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        return ret;
30899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
30999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
31099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    //
31199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // password functions
31299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    //
31399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
31499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
31599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * Set password. Tuple (PASSWORD_HOST_COL, PASSWORD_USERNAME_COL) is unique.
31699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     *
31799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param schemePlusHost The scheme and host for the password
31899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param username The username for the password. If it is null, it means
31999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     *            password can't be saved.
32099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param password The password
32199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
32299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    void setUsernamePassword(String schemePlusHost, String username,
32399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                String password) {
32499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (schemePlusHost == null || !checkInitialized()) {
32599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return;
32699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
32799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
32899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mPasswordLock) {
32999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            final ContentValues c = new ContentValues();
33099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            c.put(PASSWORD_HOST_COL, schemePlusHost);
33199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            c.put(PASSWORD_USERNAME_COL, username);
33299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            c.put(PASSWORD_PASSWORD_COL, password);
33399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            sDatabase.insert(mTableNames[TABLE_PASSWORD_ID], PASSWORD_HOST_COL,
33499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    c);
33599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
33699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
33799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
33899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
33999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * Retrieve the username and password for a given host
34099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     *
34199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param schemePlusHost The scheme and host which passwords applies to
34299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @return String[] if found, String[0] is username, which can be null and
34399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     *         String[1] is password. Return null if it can't find anything.
34499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
34599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    String[] getUsernamePassword(String schemePlusHost) {
34699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (schemePlusHost == null || !checkInitialized()) {
34799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return null;
34899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
34999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
35099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        final String[] columns = new String[] {
35199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                PASSWORD_USERNAME_COL, PASSWORD_PASSWORD_COL
35299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        };
35399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        final String selection = "(" + PASSWORD_HOST_COL + " == ?)";
35499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mPasswordLock) {
35599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            String[] ret = null;
35699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            Cursor cursor = null;
35799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            try {
35899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                cursor = sDatabase.query(mTableNames[TABLE_PASSWORD_ID],
35999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        columns, selection, new String[] { schemePlusHost }, null,
36099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        null, null);
36199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                if (cursor.moveToFirst()) {
36299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    ret = new String[2];
36399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    ret[0] = cursor.getString(
36499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                            cursor.getColumnIndex(PASSWORD_USERNAME_COL));
36599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    ret[1] = cursor.getString(
36699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                            cursor.getColumnIndex(PASSWORD_PASSWORD_COL));
36799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                }
36899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            } catch (IllegalStateException e) {
36999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                Log.e(LOGTAG, "getUsernamePassword", e);
37099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            } finally {
37199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                if (cursor != null) cursor.close();
37299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            }
37399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return ret;
37499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
37599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
37699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
37799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
37899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @see WebViewDatabase#hasUsernamePassword
37999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
38099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    @Override
38199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    public boolean hasUsernamePassword() {
38299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mPasswordLock) {
38399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return hasEntries(TABLE_PASSWORD_ID);
38499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
38599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
38699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
38799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
38899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @see WebViewDatabase#clearUsernamePassword
38999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
39099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    @Override
39199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    public void clearUsernamePassword() {
39299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (!checkInitialized()) {
39399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return;
39499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
39599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
39699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mPasswordLock) {
39799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            sDatabase.delete(mTableNames[TABLE_PASSWORD_ID], null, null);
39899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
39999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
40099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
40199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    //
40299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // http authentication password functions
40399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    //
40499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
40599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
40699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * Set HTTP authentication password. Tuple (HTTPAUTH_HOST_COL,
40799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * HTTPAUTH_REALM_COL, HTTPAUTH_USERNAME_COL) is unique.
40899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     *
40999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param host The host for the password
41099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param realm The realm for the password
41199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param username The username for the password. If it is null, it means
41299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     *            password can't be saved.
41399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param password The password
41499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
41599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    void setHttpAuthUsernamePassword(String host, String realm, String username,
41699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            String password) {
41799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (host == null || realm == null || !checkInitialized()) {
41899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return;
41999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
42099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
42199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mHttpAuthLock) {
42299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            final ContentValues c = new ContentValues();
42399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            c.put(HTTPAUTH_HOST_COL, host);
42499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            c.put(HTTPAUTH_REALM_COL, realm);
42599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            c.put(HTTPAUTH_USERNAME_COL, username);
42699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            c.put(HTTPAUTH_PASSWORD_COL, password);
42799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            sDatabase.insert(mTableNames[TABLE_HTTPAUTH_ID], HTTPAUTH_HOST_COL,
42899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    c);
42999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
43099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
43199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
43299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
43399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * Retrieve the HTTP authentication username and password for a given
43499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * host+realm pair
43599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     *
43699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param host The host the password applies to
43799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param realm The realm the password applies to
43899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @return String[] if found, String[0] is username, which can be null and
43999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     *         String[1] is password. Return null if it can't find anything.
44099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
44199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    String[] getHttpAuthUsernamePassword(String host, String realm) {
44299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (host == null || realm == null || !checkInitialized()){
44399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return null;
44499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
44599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
44699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        final String[] columns = new String[] {
44799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                HTTPAUTH_USERNAME_COL, HTTPAUTH_PASSWORD_COL
44899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        };
44999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        final String selection = "(" + HTTPAUTH_HOST_COL + " == ?) AND ("
45099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + HTTPAUTH_REALM_COL + " == ?)";
45199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mHttpAuthLock) {
45299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            String[] ret = null;
45399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            Cursor cursor = null;
45499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            try {
45599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                cursor = sDatabase.query(mTableNames[TABLE_HTTPAUTH_ID],
45699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        columns, selection, new String[] { host, realm }, null,
45799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        null, null);
45899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                if (cursor.moveToFirst()) {
45999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    ret = new String[2];
46099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    ret[0] = cursor.getString(
46199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                            cursor.getColumnIndex(HTTPAUTH_USERNAME_COL));
46299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    ret[1] = cursor.getString(
46399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                            cursor.getColumnIndex(HTTPAUTH_PASSWORD_COL));
46499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                }
46599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            } catch (IllegalStateException e) {
46699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                Log.e(LOGTAG, "getHttpAuthUsernamePassword", e);
46799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            } finally {
46899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                if (cursor != null) cursor.close();
46999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            }
47099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return ret;
47199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
47299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
47399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
47499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
47599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @see WebViewDatabase#hasHttpAuthUsernamePassword
47699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
47799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    @Override
47899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    public boolean hasHttpAuthUsernamePassword() {
47999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mHttpAuthLock) {
48099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return hasEntries(TABLE_HTTPAUTH_ID);
48199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
48299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
48399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
48499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
48599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @see WebViewDatabase#clearHttpAuthUsernamePassword
48699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
48799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    @Override
48899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    public void clearHttpAuthUsernamePassword() {
48999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (!checkInitialized()) {
49099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return;
49199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
49299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
49399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mHttpAuthLock) {
49499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            sDatabase.delete(mTableNames[TABLE_HTTPAUTH_ID], null, null);
49599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
49699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
49799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
49899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    //
49999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    // form data functions
50099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    //
50199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
50299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
50399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * Set form data for a site. Tuple (FORMDATA_URLID_COL, FORMDATA_NAME_COL,
50499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * FORMDATA_VALUE_COL) is unique
50599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     *
50699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param url The url of the site
50799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param formdata The form data in HashMap
50899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
50999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    void setFormData(String url, HashMap<String, String> formdata) {
51099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (url == null || formdata == null || !checkInitialized()) {
51199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return;
51299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
51399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
51499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        final String selection = "(" + FORMURL_URL_COL + " == ?)";
51599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mFormLock) {
51699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            long urlid = -1;
51799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            Cursor cursor = null;
51899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            try {
51999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                cursor = sDatabase.query(mTableNames[TABLE_FORMURL_ID],
52099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        ID_PROJECTION, selection, new String[] { url }, null, null,
52199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        null);
52299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                if (cursor.moveToFirst()) {
52399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
52499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                } else {
52599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    ContentValues c = new ContentValues();
52699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    c.put(FORMURL_URL_COL, url);
52799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    urlid = sDatabase.insert(
52899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                            mTableNames[TABLE_FORMURL_ID], null, c);
52999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                }
53099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            } catch (IllegalStateException e) {
53199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                Log.e(LOGTAG, "setFormData", e);
53299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            } finally {
53399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                if (cursor != null) cursor.close();
53499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            }
53599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            if (urlid >= 0) {
53699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                Set<Entry<String, String>> set = formdata.entrySet();
53799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                Iterator<Entry<String, String>> iter = set.iterator();
53899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                ContentValues map = new ContentValues();
53999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                map.put(FORMDATA_URLID_COL, urlid);
54099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                while (iter.hasNext()) {
54199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    Entry<String, String> entry = iter.next();
54299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    map.put(FORMDATA_NAME_COL, entry.getKey());
54399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    map.put(FORMDATA_VALUE_COL, entry.getValue());
54499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    sDatabase.insert(mTableNames[TABLE_FORMDATA_ID], null, map);
54599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                }
54699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            }
54799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
54899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
54999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
55099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
55199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * Get all the values for a form entry with "name" in a given site
55299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     *
55399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param url The url of the site
55499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @param name The name of the form entry
55599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @return A list of values. Return empty list if nothing is found.
55699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
55799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    ArrayList<String> getFormData(String url, String name) {
55899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        ArrayList<String> values = new ArrayList<String>();
55999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (url == null || name == null || !checkInitialized()) {
56099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return values;
56199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
56299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
56399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        final String urlSelection = "(" + FORMURL_URL_COL + " == ?)";
56499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        final String dataSelection = "(" + FORMDATA_URLID_COL + " == ?) AND ("
56599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                + FORMDATA_NAME_COL + " == ?)";
56699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mFormLock) {
56799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            Cursor cursor = null;
56899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            try {
56999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                cursor = sDatabase.query(mTableNames[TABLE_FORMURL_ID],
57099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        ID_PROJECTION, urlSelection, new String[] { url }, null,
57199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        null, null);
57299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                while (cursor.moveToNext()) {
57399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    long urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
57499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    Cursor dataCursor = null;
57599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    try {
57699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        dataCursor = sDatabase.query(
57799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                                mTableNames[TABLE_FORMDATA_ID],
57899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                                new String[] { ID_COL, FORMDATA_VALUE_COL },
57999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                                dataSelection,
58099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                                new String[] { Long.toString(urlid), name },
58199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                                null, null, null);
58299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        if (dataCursor.moveToFirst()) {
58399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                            int valueCol = dataCursor.getColumnIndex(
58499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                                    FORMDATA_VALUE_COL);
58599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                            do {
58699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                                values.add(dataCursor.getString(valueCol));
58799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                            } while (dataCursor.moveToNext());
58899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        }
58999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    } catch (IllegalStateException e) {
59099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        Log.e(LOGTAG, "getFormData dataCursor", e);
59199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    } finally {
59299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                        if (dataCursor != null) dataCursor.close();
59399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                    }
59499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                }
59599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            } catch (IllegalStateException e) {
59699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                Log.e(LOGTAG, "getFormData cursor", e);
59799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            } finally {
59899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch                if (cursor != null) cursor.close();
59999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            }
60099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return values;
60199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
60299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
60399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
60499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
60599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @see WebViewDatabase#hasFormData
60699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
60799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    @Override
60899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    public boolean hasFormData() {
60999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mFormLock) {
61099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return hasEntries(TABLE_FORMURL_ID);
61199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
61299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
61399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
61499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    /**
61599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     * @see WebViewDatabase#clearFormData
61699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch     */
61799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    @Override
61899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    public void clearFormData() {
61999c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        if (!checkInitialized()) {
62099c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            return;
62199c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
62299c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch
62399c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        synchronized (mFormLock) {
62499c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            sDatabase.delete(mTableNames[TABLE_FORMURL_ID], null, null);
62599c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch            sDatabase.delete(mTableNames[TABLE_FORMDATA_ID], null, null);
62699c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch        }
62799c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch    }
62899c12e8d5f12f239c28644a837937810299e5e3fBen Murdoch}
629