19066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project/*
29066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Copyright (C) 2007 The Android Open Source Project
39066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
49066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Licensed under the Apache License, Version 2.0 (the "License");
59066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * you may not use this file except in compliance with the License.
69066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * You may obtain a copy of the License at
79066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
89066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *      http://www.apache.org/licenses/LICENSE-2.0
99066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project *
109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * Unless required by applicable law or agreed to in writing, software
119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * distributed under the License is distributed on an "AS IS" BASIS,
129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * See the License for the specific language governing permissions and
149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project * limitations under the License.
159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project */
169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpackage android.webkit;
189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.ArrayList;
209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.HashMap;
219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Iterator;
222036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Klobaimport java.util.List;
239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Set;
249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport java.util.Map.Entry;
259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.ContentValues;
279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.content.Context;
289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.Cursor;
299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.DatabaseUtils;
309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteDatabase;
3158def690a87b4aa2c01331c06b61e457198de0eaGrace Klobaimport android.database.sqlite.SQLiteException;
329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.database.sqlite.SQLiteStatement;
339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.util.Log;
349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.webkit.CookieManager.Cookie;
359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectimport android.webkit.CacheManager.CacheResult;
369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Projectpublic class WebViewDatabase {
389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String DATABASE_FILE = "webview.db";
399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CACHE_DATABASE_FILE = "webviewCache.db";
409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // log tag
429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    protected static final String LOGTAG = "webviewdatabase";
439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
44b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba    private static final int DATABASE_VERSION = 10;
459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // 2 -> 3 Modified Cache table to allow cache of redirects
469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // 3 -> 4 Added Oma-Downloads table
479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // 4 -> 5 Modified Cache table to support persistent contentLength
489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // 5 -> 4 Removed Oma-Downoads table
499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // 5 -> 6 Add INDEX for cache table
509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // 6 -> 7 Change cache localPath from int to String
519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // 7 -> 8 Move cache to its own db
529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // 8 -> 9 Store both scheme and host when storing passwords
53b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba    // 9 -> 10 Update httpauth table UNIQUE
5460708a75120c4469dc2683485301ff9ee3b022e0Leon Clarke    private static final int CACHE_DATABASE_VERSION = 4;
55e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba    // 1 -> 2 Add expires String
560b956e1353a691674cb22c899c5a444b92532b60Grace Kloba    // 2 -> 3 Add content-disposition
5760708a75120c4469dc2683485301ff9ee3b022e0Leon Clarke    // 3 -> 4 Add crossdomain (For x-permitted-cross-domain-policies header)
589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static WebViewDatabase mInstance = null;
609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static SQLiteDatabase mDatabase = null;
629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static SQLiteDatabase mCacheDatabase = null;
639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // synchronize locks
659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Object mCookieLock = new Object();
669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Object mPasswordLock = new Object();
679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Object mFormLock = new Object();
689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private final Object mHttpAuthLock = new Object();
699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String mTableNames[] = {
719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "cookies", "password", "formurl", "formdata", "httpauth"
729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // Table ids (they are index to mTableNames)
759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int TABLE_COOKIES_ID = 0;
769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int TABLE_PASSWORD_ID = 1;
789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int TABLE_FORMURL_ID = 2;
809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int TABLE_FORMDATA_ID = 3;
829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final int TABLE_HTTPAUTH_ID = 4;
849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // column id strings for "_id" which can be used by any table
869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String ID_COL = "_id";
879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String[] ID_PROJECTION = new String[] {
899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        "_id"
909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    };
919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // column id strings for "cookies" table
939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String COOKIES_NAME_COL = "name";
949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String COOKIES_VALUE_COL = "value";
969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String COOKIES_DOMAIN_COL = "domain";
989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String COOKIES_PATH_COL = "path";
1009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String COOKIES_EXPIRES_COL = "expires";
1029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String COOKIES_SECURE_COL = "secure";
1049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // column id strings for "cache" table
1069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CACHE_URL_COL = "url";
1079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CACHE_FILE_PATH_COL = "filepath";
1099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CACHE_LAST_MODIFY_COL = "lastmodify";
1119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CACHE_ETAG_COL = "etag";
1139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CACHE_EXPIRES_COL = "expires";
1159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
116e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba    private static final String CACHE_EXPIRES_STRING_COL = "expiresstring";
117e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba
1189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CACHE_MIMETYPE_COL = "mimetype";
1199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CACHE_ENCODING_COL = "encoding";
1219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CACHE_HTTP_STATUS_COL = "httpstatus";
1239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CACHE_LOCATION_COL = "location";
1259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String CACHE_CONTENTLENGTH_COL = "contentlength";
1279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1280b956e1353a691674cb22c899c5a444b92532b60Grace Kloba    private static final String CACHE_CONTENTDISPOSITION_COL = "contentdisposition";
1290b956e1353a691674cb22c899c5a444b92532b60Grace Kloba
13060708a75120c4469dc2683485301ff9ee3b022e0Leon Clarke    private static final String CACHE_CROSSDOMAIN_COL = "crossdomain";
13160708a75120c4469dc2683485301ff9ee3b022e0Leon Clarke
1329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // column id strings for "password" table
1339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PASSWORD_HOST_COL = "host";
1349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PASSWORD_USERNAME_COL = "username";
1369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String PASSWORD_PASSWORD_COL = "password";
1389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // column id strings for "formurl" table
1409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String FORMURL_URL_COL = "url";
1419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // column id strings for "formdata" table
1439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String FORMDATA_URLID_COL = "urlid";
1449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String FORMDATA_NAME_COL = "name";
1469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String FORMDATA_VALUE_COL = "value";
1489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // column id strings for "httpauth" table
1509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String HTTPAUTH_HOST_COL = "host";
1519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String HTTPAUTH_REALM_COL = "realm";
1539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String HTTPAUTH_USERNAME_COL = "username";
1559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static final String HTTPAUTH_PASSWORD_COL = "password";
1579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // use InsertHelper to improve insert performance by 40%
1599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static DatabaseUtils.InsertHelper mCacheInserter;
1609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int mCacheUrlColIndex;
1619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int mCacheFilePathColIndex;
1629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int mCacheLastModifyColIndex;
1639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int mCacheETagColIndex;
1649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int mCacheExpiresColIndex;
165e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba    private static int mCacheExpiresStringColIndex;
1669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int mCacheMimeTypeColIndex;
1679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int mCacheEncodingColIndex;
1689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int mCacheHttpStatusColIndex;
1699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int mCacheLocationColIndex;
1709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int mCacheContentLengthColIndex;
1710b956e1353a691674cb22c899c5a444b92532b60Grace Kloba    private static int mCacheContentDispositionColIndex;
17260708a75120c4469dc2683485301ff9ee3b022e0Leon Clarke    private static int mCacheCrossDomainColIndex;
1739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static int mCacheTransactionRefcount;
1759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private WebViewDatabase() {
1779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // Singleton only, use getInstance()
1789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
1799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public static synchronized WebViewDatabase getInstance(Context context) {
1819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mInstance == null) {
1829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mInstance = new WebViewDatabase();
18358def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba            try {
18458def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                mDatabase = context
18558def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                        .openOrCreateDatabase(DATABASE_FILE, 0, null);
18658def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba            } catch (SQLiteException e) {
18758def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                // try again by deleting the old db and create a new one
18858def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                if (context.deleteDatabase(DATABASE_FILE)) {
18958def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                    mDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0,
19058def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                            null);
19158def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                }
19258def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba            }
1939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
1949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // mDatabase should not be null,
1959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // the only case is RequestAPI test has problem to create db
1969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDatabase != null && mDatabase.getVersion() != DATABASE_VERSION) {
1979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDatabase.beginTransaction();
1989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
1999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    upgradeDatabase();
2009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mDatabase.setTransactionSuccessful();
2019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } finally {
2029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mDatabase.endTransaction();
2039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mDatabase != null) {
2079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // use per table Mutex lock, turn off database lock, this
2089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // improves performance as database's ReentrantLock is expansive
2099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mDatabase.setLockingEnabled(false);
2109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
21258def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba            try {
21358def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                mCacheDatabase = context.openOrCreateDatabase(
21458def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                        CACHE_DATABASE_FILE, 0, null);
21558def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba            } catch (SQLiteException e) {
21658def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                // try again by deleting the old db and create a new one
21758def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                if (context.deleteDatabase(CACHE_DATABASE_FILE)) {
21858def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                    mCacheDatabase = context.openOrCreateDatabase(
21958def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                            CACHE_DATABASE_FILE, 0, null);
22058def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba                }
22158def690a87b4aa2c01331c06b61e457198de0eaGrace Kloba            }
2229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // mCacheDatabase should not be null,
2249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // the only case is RequestAPI test has problem to create db
2259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCacheDatabase != null
2269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    && mCacheDatabase.getVersion() != CACHE_DATABASE_VERSION) {
2279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheDatabase.beginTransaction();
2289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                try {
2299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    upgradeCacheDatabase();
2309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    bootstrapCacheDatabase();
2319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCacheDatabase.setTransactionSuccessful();
2329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                } finally {
2339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mCacheDatabase.endTransaction();
2349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
2359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // Erase the files from the file system in the
2369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // case that the database was updated and the
2379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // there were existing cache content
2389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                CacheManager.removeAllCacheFiles();
2399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (mCacheDatabase != null) {
2422036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                // use read_uncommitted to speed up READ
2432036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                mCacheDatabase.execSQL("PRAGMA read_uncommitted = true;");
2442036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                // as only READ can be called in the non-WebViewWorkerThread,
2452036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                // and read_uncommitted is used, we can turn off database lock
2462036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                // to use transaction.
2472036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                mCacheDatabase.setLockingEnabled(false);
2482036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba
2499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                // use InsertHelper for faster insertion
2509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheInserter = new DatabaseUtils.InsertHelper(mCacheDatabase,
2519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        "cache");
2529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheUrlColIndex = mCacheInserter
2539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getColumnIndex(CACHE_URL_COL);
2549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheFilePathColIndex = mCacheInserter
2559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getColumnIndex(CACHE_FILE_PATH_COL);
2569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheLastModifyColIndex = mCacheInserter
2579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getColumnIndex(CACHE_LAST_MODIFY_COL);
2589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheETagColIndex = mCacheInserter
2599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getColumnIndex(CACHE_ETAG_COL);
2609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheExpiresColIndex = mCacheInserter
2619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getColumnIndex(CACHE_EXPIRES_COL);
262e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba                mCacheExpiresStringColIndex = mCacheInserter
263e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba                        .getColumnIndex(CACHE_EXPIRES_STRING_COL);
2649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheMimeTypeColIndex = mCacheInserter
2659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getColumnIndex(CACHE_MIMETYPE_COL);
2669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheEncodingColIndex = mCacheInserter
2679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getColumnIndex(CACHE_ENCODING_COL);
2689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheHttpStatusColIndex = mCacheInserter
2699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getColumnIndex(CACHE_HTTP_STATUS_COL);
2709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheLocationColIndex = mCacheInserter
2719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getColumnIndex(CACHE_LOCATION_COL);
2729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheContentLengthColIndex = mCacheInserter
2739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        .getColumnIndex(CACHE_CONTENTLENGTH_COL);
2740b956e1353a691674cb22c899c5a444b92532b60Grace Kloba                mCacheContentDispositionColIndex = mCacheInserter
2750b956e1353a691674cb22c899c5a444b92532b60Grace Kloba                        .getColumnIndex(CACHE_CONTENTDISPOSITION_COL);
27660708a75120c4469dc2683485301ff9ee3b022e0Leon Clarke                mCacheCrossDomainColIndex = mCacheInserter
27760708a75120c4469dc2683485301ff9ee3b022e0Leon Clarke                        .getColumnIndex(CACHE_CROSSDOMAIN_COL);
2789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
2799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return mInstance;
2829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
2839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
2849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void upgradeDatabase() {
2859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int oldVersion = mDatabase.getVersion();
2869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (oldVersion != 0) {
2879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.i(LOGTAG, "Upgrading database from version "
2889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + oldVersion + " to "
2899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + DATABASE_VERSION + ", which will destroy old data");
2909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
2919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        boolean justPasswords = 8 == oldVersion && 9 == DATABASE_VERSION;
292b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba        boolean justAuth = 9 == oldVersion && 10 == DATABASE_VERSION;
293b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba        if (justAuth) {
294b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba            mDatabase.execSQL("DROP TABLE IF EXISTS "
295b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba                    + mTableNames[TABLE_HTTPAUTH_ID]);
296b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba            mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
297b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba                    + " (" + ID_COL + " INTEGER PRIMARY KEY, "
298b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba                    + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
299b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba                    + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
300b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba                    + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
301b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba                    + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
302b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba                    + ") ON CONFLICT REPLACE);");
303b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba            return;
304b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba        }
305b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba
3069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!justPasswords) {
3079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.execSQL("DROP TABLE IF EXISTS "
3089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mTableNames[TABLE_COOKIES_ID]);
3099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.execSQL("DROP TABLE IF EXISTS cache");
3109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.execSQL("DROP TABLE IF EXISTS "
3119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mTableNames[TABLE_FORMURL_ID]);
3129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.execSQL("DROP TABLE IF EXISTS "
3139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mTableNames[TABLE_FORMDATA_ID]);
3149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.execSQL("DROP TABLE IF EXISTS "
3159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mTableNames[TABLE_HTTPAUTH_ID]);
3169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDatabase.execSQL("DROP TABLE IF EXISTS "
3189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + mTableNames[TABLE_PASSWORD_ID]);
3199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDatabase.setVersion(DATABASE_VERSION);
3219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (!justPasswords) {
3239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // cookies
3249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_COOKIES_ID]
3259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " (" + ID_COL + " INTEGER PRIMARY KEY, "
3269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + COOKIES_NAME_COL + " TEXT, " + COOKIES_VALUE_COL
3279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " TEXT, " + COOKIES_DOMAIN_COL + " TEXT, "
3289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + COOKIES_PATH_COL + " TEXT, " + COOKIES_EXPIRES_COL
3299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " INTEGER, " + COOKIES_SECURE_COL + " INTEGER" + ");");
3309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.execSQL("CREATE INDEX cookiesIndex ON "
3319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + mTableNames[TABLE_COOKIES_ID] + " (path)");
3329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // formurl
3349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMURL_ID]
3359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " (" + ID_COL + " INTEGER PRIMARY KEY, " + FORMURL_URL_COL
3369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " TEXT" + ");");
3379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // formdata
3399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMDATA_ID]
3409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " (" + ID_COL + " INTEGER PRIMARY KEY, "
3419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + FORMDATA_URLID_COL + " INTEGER, " + FORMDATA_NAME_COL
3429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " TEXT, " + FORMDATA_VALUE_COL + " TEXT," + " UNIQUE ("
3439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + FORMDATA_URLID_COL + ", " + FORMDATA_NAME_COL + ", "
3449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + FORMDATA_VALUE_COL + ") ON CONFLICT IGNORE);");
3459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            // httpauth
3479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
3489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " (" + ID_COL + " INTEGER PRIMARY KEY, "
3499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
3509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
3519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
352b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba                    + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL
353b6e164c779881cf68768224bd67a8d949be0618aGrace Kloba                    + ") ON CONFLICT REPLACE);");
3549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        // passwords
3569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_PASSWORD_ID]
3579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " (" + ID_COL + " INTEGER PRIMARY KEY, "
3589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + PASSWORD_HOST_COL + " TEXT, " + PASSWORD_USERNAME_COL
3599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + " TEXT, " + PASSWORD_PASSWORD_COL + " TEXT," + " UNIQUE ("
3609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + PASSWORD_HOST_COL + ", " + PASSWORD_USERNAME_COL
3619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + ") ON CONFLICT REPLACE);");
3629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void upgradeCacheDatabase() {
3659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        int oldVersion = mCacheDatabase.getVersion();
3669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (oldVersion != 0) {
3679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            Log.i(LOGTAG, "Upgrading cache database from version "
3689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + oldVersion + " to "
3699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + DATABASE_VERSION + ", which will destroy all old data");
3709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheDatabase.execSQL("DROP TABLE IF EXISTS cache");
3729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheDatabase.setVersion(CACHE_DATABASE_VERSION);
3739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private static void bootstrapCacheDatabase() {
3769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCacheDatabase != null) {
3779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCacheDatabase.execSQL("CREATE TABLE cache"
3789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " (" + ID_COL + " INTEGER PRIMARY KEY, " + CACHE_URL_COL
3799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " TEXT, " + CACHE_FILE_PATH_COL + " TEXT, "
3809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + CACHE_LAST_MODIFY_COL + " TEXT, " + CACHE_ETAG_COL
3819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " TEXT, " + CACHE_EXPIRES_COL + " INTEGER, "
382e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba                    + CACHE_EXPIRES_STRING_COL + " TEXT, "
3839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + CACHE_MIMETYPE_COL + " TEXT, " + CACHE_ENCODING_COL
3849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " TEXT," + CACHE_HTTP_STATUS_COL + " INTEGER, "
3859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + CACHE_LOCATION_COL + " TEXT, " + CACHE_CONTENTLENGTH_COL
3860b956e1353a691674cb22c899c5a444b92532b60Grace Kloba                    + " INTEGER, " + CACHE_CONTENTDISPOSITION_COL + " TEXT, "
38760708a75120c4469dc2683485301ff9ee3b022e0Leon Clarke                    + CACHE_CROSSDOMAIN_COL + " TEXT,"
3880b956e1353a691674cb22c899c5a444b92532b60Grace Kloba                    + " UNIQUE (" + CACHE_URL_COL + ") ON CONFLICT REPLACE);");
3899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCacheDatabase.execSQL("CREATE INDEX cacheUrlIndex ON cache ("
3909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + CACHE_URL_COL + ")");
3919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
3939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    private boolean hasEntries(int tableId) {
3959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDatabase == null) {
3969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
3979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
3989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
3990fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        Cursor cursor = null;
4000fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        boolean ret = false;
4010fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        try {
4020fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            cursor = mDatabase.query(mTableNames[tableId], ID_PROJECTION,
4030fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    null, null, null, null, null);
4040fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            ret = cursor.moveToFirst() == true;
4050fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        } catch (IllegalStateException e) {
4060fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            Log.e(LOGTAG, "hasEntries", e);
4070fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        } finally {
4080fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            if (cursor != null) cursor.close();
4090fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        }
4109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ret;
4119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //
4149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // cookies functions
4159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //
4169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get cookies in the format of CookieManager.Cookie inside an ArrayList for
4199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * a given domain
4209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return ArrayList<Cookie> If nothing is found, return an empty list.
4229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayList<Cookie> getCookiesForDomain(String domain) {
4249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<Cookie> list = new ArrayList<Cookie>();
4259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (domain == null || mDatabase == null) {
4269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return list;
4279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCookieLock) {
4309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String[] columns = new String[] {
4319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    ID_COL, COOKIES_DOMAIN_COL, COOKIES_PATH_COL,
4329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    COOKIES_NAME_COL, COOKIES_VALUE_COL, COOKIES_EXPIRES_COL,
4339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    COOKIES_SECURE_COL
4349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            };
4359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String selection = "(" + COOKIES_DOMAIN_COL
4369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " GLOB '*' || ?)";
4370fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            Cursor cursor = null;
4380fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            try {
4390fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                cursor = mDatabase.query(mTableNames[TABLE_COOKIES_ID],
4400fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        columns, selection, new String[] { domain }, null, null,
4410fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        null);
4420fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                if (cursor.moveToFirst()) {
4430fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    int domainCol = cursor.getColumnIndex(COOKIES_DOMAIN_COL);
4440fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    int pathCol = cursor.getColumnIndex(COOKIES_PATH_COL);
4450fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    int nameCol = cursor.getColumnIndex(COOKIES_NAME_COL);
4460fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    int valueCol = cursor.getColumnIndex(COOKIES_VALUE_COL);
4470fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    int expiresCol = cursor.getColumnIndex(COOKIES_EXPIRES_COL);
4480fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    int secureCol = cursor.getColumnIndex(COOKIES_SECURE_COL);
4490fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    do {
4500fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        Cookie cookie = new Cookie();
4510fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        cookie.domain = cursor.getString(domainCol);
4520fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        cookie.path = cursor.getString(pathCol);
4530fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        cookie.name = cursor.getString(nameCol);
4540fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        cookie.value = cursor.getString(valueCol);
4550fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        if (cursor.isNull(expiresCol)) {
4560fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            cookie.expires = -1;
4570fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        } else {
4580fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            cookie.expires = cursor.getLong(expiresCol);
4590fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        }
4600fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        cookie.secure = cursor.getShort(secureCol) != 0;
4610fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        cookie.mode = Cookie.MODE_NORMAL;
4620fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        list.add(cookie);
4630fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    } while (cursor.moveToNext());
4640fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                }
4650fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            } catch (IllegalStateException e) {
4660fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                Log.e(LOGTAG, "getCookiesForDomain", e);
4670fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            } finally {
4680fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                if (cursor != null) cursor.close();
4699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
4709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return list;
4719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Delete cookies which matches (domain, path, name).
4769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
4779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param domain If it is null, nothing happens.
4789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param path If it is null, all the cookies match (domain) will be
4799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            deleted.
4809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param name If it is null, all the cookies match (domain, path) will be
4819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            deleted.
4829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
4839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void deleteCookies(String domain, String path, String name) {
4849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (domain == null || mDatabase == null) {
4859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
4869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCookieLock) {
4899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final String where = "(" + COOKIES_DOMAIN_COL + " == ?) AND ("
4909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + COOKIES_PATH_COL + " == ?) AND (" + COOKIES_NAME_COL
4919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    + " == ?)";
4929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.delete(mTableNames[TABLE_COOKIES_ID], where,
4939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    new String[] { domain, path, name });
4949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
4959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
4969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
4979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
4989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Add a cookie to the database
4999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param cookie
5019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void addCookie(Cookie cookie) {
5039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (cookie.domain == null || cookie.path == null || cookie.name == null
5049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                || mDatabase == null) {
5059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCookieLock) {
5099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            ContentValues cookieVal = new ContentValues();
5109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cookieVal.put(COOKIES_DOMAIN_COL, cookie.domain);
5119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cookieVal.put(COOKIES_PATH_COL, cookie.path);
5129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cookieVal.put(COOKIES_NAME_COL, cookie.name);
5139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cookieVal.put(COOKIES_VALUE_COL, cookie.value);
5149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cookie.expires != -1) {
5159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                cookieVal.put(COOKIES_EXPIRES_COL, cookie.expires);
5169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
5179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            cookieVal.put(COOKIES_SECURE_COL, cookie.secure);
5189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.insert(mTableNames[TABLE_COOKIES_ID], null, cookieVal);
5199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Whether there is any cookies in the database
5249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return TRUE if there is cookie.
5269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean hasCookies() {
5289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCookieLock) {
5299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return hasEntries(TABLE_COOKIES_ID);
5309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clear cookie database
5359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void clearCookies() {
5379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDatabase == null) {
5389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCookieLock) {
5429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.delete(mTableNames[TABLE_COOKIES_ID], null, null);
5439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clear session cookies, which means cookie doesn't have EXPIRES.
5489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void clearSessionCookies() {
5509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDatabase == null) {
5519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String sessionExpired = COOKIES_EXPIRES_COL + " ISNULL";
5559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCookieLock) {
5569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.delete(mTableNames[TABLE_COOKIES_ID], sessionExpired,
5579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    null);
5589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
5629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clear expired cookies
5639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
5649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param now Time for now
5659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
5669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void clearExpiredCookies(long now) {
5679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDatabase == null) {
5689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
5699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String expires = COOKIES_EXPIRES_COL + " <= ?";
5729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mCookieLock) {
5739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.delete(mTableNames[TABLE_COOKIES_ID], expires,
5749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    new String[] { Long.toString(now) });
5759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //
5792036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba    // cache functions
5809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //
5819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5822036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba    // only called from WebViewWorkerThread
5839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean startCacheTransaction() {
5849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (++mCacheTransactionRefcount == 1) {
5852036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba            if (!Thread.currentThread().equals(
5862036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                    WebViewWorker.getHandler().getLooper().getThread())) {
5872036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                Log.w(LOGTAG, "startCacheTransaction should be called from "
5882036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                        + "WebViewWorkerThread instead of from "
5892036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                        + Thread.currentThread().getName());
5902036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba            }
5919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mCacheDatabase.beginTransaction();
5929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
5939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
5949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
5959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
5969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
5972036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba    // only called from WebViewWorkerThread
5989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean endCacheTransaction() {
5999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (--mCacheTransactionRefcount == 0) {
6002036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba            if (!Thread.currentThread().equals(
6012036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                    WebViewWorker.getHandler().getLooper().getThread())) {
6022036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                Log.w(LOGTAG, "endCacheTransaction should be called from "
6032036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                        + "WebViewWorkerThread instead of from "
6042036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba                        + Thread.currentThread().getName());
6052036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba            }
6069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            try {
6079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheDatabase.setTransactionSuccessful();
6089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            } finally {
6099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                mCacheDatabase.endTransaction();
6109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return true;
6129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return false;
6149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get a cache item.
6189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param url The url
6209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return CacheResult The CacheManager.CacheResult
6219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    CacheResult getCache(String url) {
6239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (url == null || mCacheDatabase == null) {
6249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
6259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6270fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        Cursor cursor = null;
6280fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        final String query = "SELECT filepath, lastmodify, etag, expires, "
6290fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                + "expiresstring, mimetype, encoding, httpstatus, location, contentlength, "
63060708a75120c4469dc2683485301ff9ee3b022e0Leon Clarke                + "contentdisposition, crossdomain FROM cache WHERE url = ?";
6319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        try {
6320fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            cursor = mCacheDatabase.rawQuery(query, new String[] { url });
6339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cursor.moveToFirst()) {
6349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                CacheResult ret = new CacheResult();
6359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ret.localPath = cursor.getString(0);
6369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ret.lastModified = cursor.getString(1);
6379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ret.etag = cursor.getString(2);
6389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ret.expires = cursor.getLong(3);
639e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba                ret.expiresString = cursor.getString(4);
640e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba                ret.mimeType = cursor.getString(5);
641e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba                ret.encoding = cursor.getString(6);
642e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba                ret.httpStatusCode = cursor.getInt(7);
643e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba                ret.location = cursor.getString(8);
644e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba                ret.contentLength = cursor.getLong(9);
6450b956e1353a691674cb22c899c5a444b92532b60Grace Kloba                ret.contentdisposition = cursor.getString(10);
64660708a75120c4469dc2683485301ff9ee3b022e0Leon Clarke                ret.crossDomain = cursor.getString(11);
6479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                return ret;
6489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
6490fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        } catch (IllegalStateException e) {
6500fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            Log.e(LOGTAG, "getCache", e);
6519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        } finally {
6529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (cursor != null) cursor.close();
6539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return null;
6559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Remove a cache item.
6599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param url The url
6619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void removeCache(String url) {
6639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (url == null || mCacheDatabase == null) {
6649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheDatabase.execSQL("DELETE FROM cache WHERE url = ?", new String[] { url });
6689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
6719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Add or update a cache. CACHE_URL_COL is unique in the table.
6729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
6739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param url The url
6749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param c The CacheManager.CacheResult
6759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
6769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void addCache(String url, CacheResult c) {
6779066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (url == null || mCacheDatabase == null) {
6789066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
6799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
6809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.prepareForInsert();
6829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.bind(mCacheUrlColIndex, url);
6839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.bind(mCacheFilePathColIndex, c.localPath);
6849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.bind(mCacheLastModifyColIndex, c.lastModified);
6859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.bind(mCacheETagColIndex, c.etag);
6869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.bind(mCacheExpiresColIndex, c.expires);
687e64c5567de20d06ac7ed1f5a01f018991cd40a52Grace Kloba        mCacheInserter.bind(mCacheExpiresStringColIndex, c.expiresString);
6889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.bind(mCacheMimeTypeColIndex, c.mimeType);
6899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.bind(mCacheEncodingColIndex, c.encoding);
6909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.bind(mCacheHttpStatusColIndex, c.httpStatusCode);
6919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.bind(mCacheLocationColIndex, c.location);
6929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.bind(mCacheContentLengthColIndex, c.contentLength);
6930b956e1353a691674cb22c899c5a444b92532b60Grace Kloba        mCacheInserter.bind(mCacheContentDispositionColIndex,
6940b956e1353a691674cb22c899c5a444b92532b60Grace Kloba                c.contentdisposition);
69560708a75120c4469dc2683485301ff9ee3b022e0Leon Clarke        mCacheInserter.bind(mCacheCrossDomainColIndex, c.crossDomain);
6969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheInserter.execute();
6979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
6989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
6999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
7009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clear cache database
7019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
7029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void clearCache() {
7039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCacheDatabase == null) {
7049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
7059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        mCacheDatabase.delete("cache", null, null);
7089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    boolean hasCache() {
7119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mCacheDatabase == null) {
7129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return false;
7139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7150fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        Cursor cursor = null;
7160fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        boolean ret = false;
7170fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        try {
7180fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            cursor = mCacheDatabase.query("cache", ID_PROJECTION,
7190fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    null, null, null, null, null);
7200fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            ret = cursor.moveToFirst() == true;
7210fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        } catch (IllegalStateException e) {
7220fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            Log.e(LOGTAG, "hasCache", e);
7230fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        } finally {
7240fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            if (cursor != null) cursor.close();
7250fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        }
7269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return ret;
7279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    long getCacheTotalSize() {
7309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        long size = 0;
7310fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        Cursor cursor = null;
7320fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        final String query = "SELECT SUM(contentlength) as sum FROM cache";
7330fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        try {
7340fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            cursor = mCacheDatabase.rawQuery(query, null);
7350fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            if (cursor.moveToFirst()) {
7360fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                size = cursor.getLong(0);
7370fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            }
7380fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        } catch (IllegalStateException e) {
7390fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            Log.e(LOGTAG, "getCacheTotalSize", e);
7400fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        } finally {
7410fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            if (cursor != null) cursor.close();
7429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return size;
7449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
7462036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba    List<String> trimCache(long amount) {
7479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<String> pathList = new ArrayList<String>(100);
7480fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        Cursor cursor = null;
7490fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        final String query = "SELECT contentlength, filepath FROM cache ORDER BY expires ASC";
7500fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        try {
7510fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            cursor = mCacheDatabase.rawQuery(query, null);
7520fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            if (cursor.moveToFirst()) {
7530fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                int batchSize = 100;
7540fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                StringBuilder pathStr = new StringBuilder(20 + 16 * batchSize);
7550fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                pathStr.append("DELETE FROM cache WHERE filepath IN (?");
7560fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                for (int i = 1; i < batchSize; i++) {
7570fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    pathStr.append(", ?");
7589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7590fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                pathStr.append(")");
7600fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                SQLiteStatement statement = null;
7610fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                try {
7620fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    statement = mCacheDatabase.compileStatement(
7630fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            pathStr.toString());
7640fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    // as bindString() uses 1-based index, initialize index to 1
7650fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    int index = 1;
7660fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    do {
7670fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        long length = cursor.getLong(0);
7680fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        if (length == 0) {
7690fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            continue;
7700fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        }
7710fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        amount -= length;
7720fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        String filePath = cursor.getString(1);
7730fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        statement.bindString(index, filePath);
7740fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        pathList.add(filePath);
7750fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        if (index++ == batchSize) {
7760fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            statement.execute();
7770fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            statement.clearBindings();
7780fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            index = 1;
7790fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        }
7800fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    } while (cursor.moveToNext() && amount > 0);
7810fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    if (index > 1) {
7820fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        // there may be old bindings from the previous statement
7830fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        // if index is less than batchSize, which is Ok.
7840fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        statement.execute();
7850fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    }
7860fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                } catch (IllegalStateException e) {
7870fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    Log.e(LOGTAG, "trimCache SQLiteStatement", e);
7880fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                } finally {
7890fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    if (statement != null) statement.close();
7909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
7919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
7920fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        } catch (IllegalStateException e) {
7930fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            Log.e(LOGTAG, "trimCache Cursor", e);
7940fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        } finally {
7950fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            if (cursor != null) cursor.close();
7969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
7979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        return pathList;
7989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
7999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8002036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba    List<String> getAllCacheFileNames() {
8012036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba        ArrayList<String> pathList = null;
8020fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        Cursor cursor = null;
8030fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        try {
8040fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            cursor = mCacheDatabase.rawQuery("SELECT filepath FROM cache",
8050fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    null);
8060fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            if (cursor != null && cursor.moveToFirst()) {
8070fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                pathList = new ArrayList<String>(cursor.getCount());
8080fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                do {
8090fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    pathList.add(cursor.getString(0));
8100fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                } while (cursor.moveToNext());
8110fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            }
8120fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        } catch (IllegalStateException e) {
8130fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            Log.e(LOGTAG, "getAllCacheFileNames", e);
8140fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins        } finally {
8150fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            if (cursor != null) cursor.close();
8162036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba        }
8172036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba        return pathList;
8182036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba    }
8192036dbab1726c34953360a7a56d6b9ef1f2aa7ddGrace Kloba
8209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //
8219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // password functions
8229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //
8239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set password. Tuple (PASSWORD_HOST_COL, PASSWORD_USERNAME_COL) is unique.
8269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param schemePlusHost The scheme and host for the password
8289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param username The username for the password. If it is null, it means
8299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            password can't be saved.
8309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param password The password
8319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setUsernamePassword(String schemePlusHost, String username,
8339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                String password) {
8349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (schemePlusHost == null || mDatabase == null) {
8359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
8369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mPasswordLock) {
8399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final ContentValues c = new ContentValues();
8409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.put(PASSWORD_HOST_COL, schemePlusHost);
8419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.put(PASSWORD_USERNAME_COL, username);
8429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.put(PASSWORD_PASSWORD_COL, password);
8439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.insert(mTableNames[TABLE_PASSWORD_ID], PASSWORD_HOST_COL,
8449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    c);
8459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieve the username and password for a given host
8509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param schemePlusHost The scheme and host which passwords applies to
8529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return String[] if found, String[0] is username, which can be null and
8539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         String[1] is password. Return null if it can't find anything.
8549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String[] getUsernamePassword(String schemePlusHost) {
8569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (schemePlusHost == null || mDatabase == null) {
8579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
8589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String[] columns = new String[] {
8619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                PASSWORD_USERNAME_COL, PASSWORD_PASSWORD_COL
8629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
8639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String selection = "(" + PASSWORD_HOST_COL + " == ?)";
8649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mPasswordLock) {
8659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String[] ret = null;
8660fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            Cursor cursor = null;
8670fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            try {
8680fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                cursor = mDatabase.query(mTableNames[TABLE_PASSWORD_ID],
8690fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        columns, selection, new String[] { schemePlusHost }, null,
8700fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        null, null);
8710fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                if (cursor.moveToFirst()) {
8720fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    ret = new String[2];
8730fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    ret[0] = cursor.getString(
8740fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            cursor.getColumnIndex(PASSWORD_USERNAME_COL));
8750fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    ret[1] = cursor.getString(
8760fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            cursor.getColumnIndex(PASSWORD_PASSWORD_COL));
8770fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                }
8780fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            } catch (IllegalStateException e) {
8790fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                Log.e(LOGTAG, "getUsernamePassword", e);
8800fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            } finally {
8810fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                if (cursor != null) cursor.close();
8829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
8839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ret;
8849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Find out if there are any passwords saved.
8899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
8909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return TRUE if there is passwords saved
8919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
8929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasUsernamePassword() {
8939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mPasswordLock) {
8949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return hasEntries(TABLE_PASSWORD_ID);
8959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
8969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
8979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
8989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
8999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clear password database
9009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearUsernamePassword() {
9029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDatabase == null) {
9039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
9049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mPasswordLock) {
9079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.delete(mTableNames[TABLE_PASSWORD_ID], null, null);
9089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //
9129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // http authentication password functions
9139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //
9149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set HTTP authentication password. Tuple (HTTPAUTH_HOST_COL,
9179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * HTTPAUTH_REALM_COL, HTTPAUTH_USERNAME_COL) is unique.
9189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param host The host for the password
9209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param realm The realm for the password
9219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param username The username for the password. If it is null, it means
9229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *            password can't be saved.
9239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param password The password
9249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setHttpAuthUsernamePassword(String host, String realm, String username,
9269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String password) {
9279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (host == null || realm == null || mDatabase == null) {
9289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
9299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mHttpAuthLock) {
9329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            final ContentValues c = new ContentValues();
9339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.put(HTTPAUTH_HOST_COL, host);
9349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.put(HTTPAUTH_REALM_COL, realm);
9359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.put(HTTPAUTH_USERNAME_COL, username);
9369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            c.put(HTTPAUTH_PASSWORD_COL, password);
9379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.insert(mTableNames[TABLE_HTTPAUTH_ID], HTTPAUTH_HOST_COL,
9389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    c);
9399066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9409066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9419066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9429066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9439066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Retrieve the HTTP authentication username and password for a given
9449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * host+realm pair
9459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param host The host the password applies to
9479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param realm The realm the password applies to
9489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return String[] if found, String[0] is username, which can be null and
9499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *         String[1] is password. Return null if it can't find anything.
9509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    String[] getHttpAuthUsernamePassword(String host, String realm) {
9529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (host == null || realm == null || mDatabase == null){
9539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return null;
9549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String[] columns = new String[] {
9579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                HTTPAUTH_USERNAME_COL, HTTPAUTH_PASSWORD_COL
9589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        };
9599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String selection = "(" + HTTPAUTH_HOST_COL + " == ?) AND ("
9609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + HTTPAUTH_REALM_COL + " == ?)";
9619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mHttpAuthLock) {
9629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            String[] ret = null;
9630fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            Cursor cursor = null;
9640fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            try {
9650fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                cursor = mDatabase.query(mTableNames[TABLE_HTTPAUTH_ID],
9660fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        columns, selection, new String[] { host, realm }, null,
9670fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        null, null);
9680fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                if (cursor.moveToFirst()) {
9690fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    ret = new String[2];
9700fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    ret[0] = cursor.getString(
9710fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            cursor.getColumnIndex(HTTPAUTH_USERNAME_COL));
9720fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    ret[1] = cursor.getString(
9730fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            cursor.getColumnIndex(HTTPAUTH_PASSWORD_COL));
9740fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                }
9750fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            } catch (IllegalStateException e) {
9760fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                Log.e(LOGTAG, "getHttpAuthUsernamePassword", e);
9770fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            } finally {
9780fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                if (cursor != null) cursor.close();
9799066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
9809066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return ret;
9819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9829066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9839066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9849066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9859066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *  Find out if there are any HTTP authentication passwords saved.
9869066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
9879066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return TRUE if there are passwords saved
9889066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9899066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasHttpAuthUsernamePassword() {
9909066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mHttpAuthLock) {
9919066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return hasEntries(TABLE_HTTPAUTH_ID);
9929066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
9939066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
9949066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
9959066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
9969066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clear HTTP authentication password database
9979066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
9989066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearHttpAuthUsernamePassword() {
9999066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDatabase == null) {
10009066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
10019066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10029066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10039066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mHttpAuthLock) {
10049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.delete(mTableNames[TABLE_HTTPAUTH_ID], null, null);
10059066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10069066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10079066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10089066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //
10099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    // form data functions
10109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    //
10119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Set form data for a site. Tuple (FORMDATA_URLID_COL, FORMDATA_NAME_COL,
10149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * FORMDATA_VALUE_COL) is unique
10159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param url The url of the site
10179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param formdata The form data in HashMap
10189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    void setFormData(String url, HashMap<String, String> formdata) {
10209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (url == null || formdata == null || mDatabase == null) {
10219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
10229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String selection = "(" + FORMURL_URL_COL + " == ?)";
10259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mFormLock) {
10269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            long urlid = -1;
10270fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            Cursor cursor = null;
10280fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            try {
10290fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
10300fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        ID_PROJECTION, selection, new String[] { url }, null, null,
10310fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        null);
10320fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                if (cursor.moveToFirst()) {
10330fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
10340fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                } else {
10350fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    ContentValues c = new ContentValues();
10360fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    c.put(FORMURL_URL_COL, url);
10370fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    urlid = mDatabase.insert(
10380fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            mTableNames[TABLE_FORMURL_ID], null, c);
10390fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                }
10400fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            } catch (IllegalStateException e) {
10410fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                Log.e(LOGTAG, "setFormData", e);
10420fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            } finally {
10430fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                if (cursor != null) cursor.close();
10449066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10459066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            if (urlid >= 0) {
10469066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Set<Entry<String, String>> set = formdata.entrySet();
10479066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                Iterator<Entry<String, String>> iter = set.iterator();
10489066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                ContentValues map = new ContentValues();
10499066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                map.put(FORMDATA_URLID_COL, urlid);
10509066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                while (iter.hasNext()) {
10519066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    Entry<String, String> entry = iter.next();
10529066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    map.put(FORMDATA_NAME_COL, entry.getKey());
10539066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    map.put(FORMDATA_VALUE_COL, entry.getValue());
10549066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                    mDatabase.insert(mTableNames[TABLE_FORMDATA_ID], null, map);
10559066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
10569066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
10579066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10589066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
10599066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10609066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
10619066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Get all the values for a form entry with "name" in a given site
10629066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
10639066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param url The url of the site
10649066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @param name The name of the form entry
10659066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return A list of values. Return empty list if nothing is found.
10669066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
10679066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    ArrayList<String> getFormData(String url, String name) {
10689066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        ArrayList<String> values = new ArrayList<String>();
10699066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (url == null || name == null || mDatabase == null) {
10709066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return values;
10719066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
10729066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
10739066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String urlSelection = "(" + FORMURL_URL_COL + " == ?)";
10749066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        final String dataSelection = "(" + FORMDATA_URLID_COL + " == ?) AND ("
10759066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                + FORMDATA_NAME_COL + " == ?)";
10769066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mFormLock) {
10770fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            Cursor cursor = null;
10780fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            try {
10790fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
10800fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        ID_PROJECTION, urlSelection, new String[] { url }, null,
10819066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                        null, null);
10820fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                if (cursor.moveToFirst()) {
10830fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    long urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
10840fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    Cursor dataCursor = null;
10850fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    try {
10860fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        dataCursor = mDatabase.query(
10870fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                                mTableNames[TABLE_FORMDATA_ID],
10880fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                                new String[] { ID_COL, FORMDATA_VALUE_COL },
10890fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                                dataSelection,
10900fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                                new String[] { Long.toString(urlid), name },
10910fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                                null, null, null);
10920fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        if (dataCursor.moveToFirst()) {
10930fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            int valueCol = dataCursor.getColumnIndex(
10940fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                                    FORMDATA_VALUE_COL);
10950fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            do {
10960fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                                values.add(dataCursor.getString(valueCol));
10970fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                            } while (dataCursor.moveToNext());
10980fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        }
10990fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    } catch (IllegalStateException e) {
11000fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        Log.e(LOGTAG, "getFormData dataCursor", e);
11010fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    } finally {
11020fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                        if (dataCursor != null) dataCursor.close();
11030fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                    }
11049066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project                }
11050fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            } catch (IllegalStateException e) {
11060fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                Log.e(LOGTAG, "getFormData cursor", e);
11070fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins            } finally {
11080fc140431d620cc7d9f68f43ab3b3a0e36adf224Leon Scroggins                if (cursor != null) cursor.close();
11099066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            }
11109066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return values;
11119066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11129066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11139066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11149066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11159066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Find out if there is form data saved.
11169066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     *
11179066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * @return TRUE if there is form data in the database
11189066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11199066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public boolean hasFormData() {
11209066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mFormLock) {
11219066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return hasEntries(TABLE_FORMURL_ID);
11229066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11239066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11249066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11259066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    /**
11269066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     * Clear form database
11279066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project     */
11289066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    public void clearFormData() {
11299066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        if (mDatabase == null) {
11309066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            return;
11319066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11329066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project
11339066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        synchronized (mFormLock) {
11349066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.delete(mTableNames[TABLE_FORMURL_ID], null, null);
11359066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project            mDatabase.delete(mTableNames[TABLE_FORMDATA_ID], null, null);
11369066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project        }
11379066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project    }
11389066cfe9886ac131c34d59ed0e2d287b0e3c0087The Android Open Source Project}
1139