FileDocCategorySizeDatePackage
WebViewDatabase.javaAPI DocAndroid 1.5 API35258Wed May 06 22:41:56 BST 2009android.webkit

WebViewDatabase

public class WebViewDatabase extends Object

Fields Summary
private static final String
DATABASE_FILE
private static final String
CACHE_DATABASE_FILE
protected static final String
LOGTAG
private static final int
DATABASE_VERSION
private static final int
CACHE_DATABASE_VERSION
private static WebViewDatabase
mInstance
private static android.database.sqlite.SQLiteDatabase
mDatabase
private static android.database.sqlite.SQLiteDatabase
mCacheDatabase
private final Object
mCookieLock
private final Object
mPasswordLock
private final Object
mFormLock
private final Object
mHttpAuthLock
private static final String[]
mTableNames
private static final int
TABLE_COOKIES_ID
private static final int
TABLE_PASSWORD_ID
private static final int
TABLE_FORMURL_ID
private static final int
TABLE_FORMDATA_ID
private static final int
TABLE_HTTPAUTH_ID
private static final String
ID_COL
private static final String[]
ID_PROJECTION
private static final String
COOKIES_NAME_COL
private static final String
COOKIES_VALUE_COL
private static final String
COOKIES_DOMAIN_COL
private static final String
COOKIES_PATH_COL
private static final String
COOKIES_EXPIRES_COL
private static final String
COOKIES_SECURE_COL
private static final String
CACHE_URL_COL
private static final String
CACHE_FILE_PATH_COL
private static final String
CACHE_LAST_MODIFY_COL
private static final String
CACHE_ETAG_COL
private static final String
CACHE_EXPIRES_COL
private static final String
CACHE_MIMETYPE_COL
private static final String
CACHE_ENCODING_COL
private static final String
CACHE_HTTP_STATUS_COL
private static final String
CACHE_LOCATION_COL
private static final String
CACHE_CONTENTLENGTH_COL
private static final String
PASSWORD_HOST_COL
private static final String
PASSWORD_USERNAME_COL
private static final String
PASSWORD_PASSWORD_COL
private static final String
FORMURL_URL_COL
private static final String
FORMDATA_URLID_COL
private static final String
FORMDATA_NAME_COL
private static final String
FORMDATA_VALUE_COL
private static final String
HTTPAUTH_HOST_COL
private static final String
HTTPAUTH_REALM_COL
private static final String
HTTPAUTH_USERNAME_COL
private static final String
HTTPAUTH_PASSWORD_COL
private static DatabaseUtils.InsertHelper
mCacheInserter
private static int
mCacheUrlColIndex
private static int
mCacheFilePathColIndex
private static int
mCacheLastModifyColIndex
private static int
mCacheETagColIndex
private static int
mCacheExpiresColIndex
private static int
mCacheMimeTypeColIndex
private static int
mCacheEncodingColIndex
private static int
mCacheHttpStatusColIndex
private static int
mCacheLocationColIndex
private static int
mCacheContentLengthColIndex
private static int
mCacheTransactionRefcount
Constructors Summary
private WebViewDatabase()


      
        // Singleton only, use getInstance()
    
Methods Summary
voidaddCache(java.lang.String url, android.webkit.CacheManager.CacheResult c)
Add or update a cache. CACHE_URL_COL is unique in the table.

param
url The url
param
c The CacheManager.CacheResult

        if (url == null || mCacheDatabase == null) {
            return;
        }

        mCacheInserter.prepareForInsert();
        mCacheInserter.bind(mCacheUrlColIndex, url);
        mCacheInserter.bind(mCacheFilePathColIndex, c.localPath);
        mCacheInserter.bind(mCacheLastModifyColIndex, c.lastModified);
        mCacheInserter.bind(mCacheETagColIndex, c.etag);
        mCacheInserter.bind(mCacheExpiresColIndex, c.expires);
        mCacheInserter.bind(mCacheMimeTypeColIndex, c.mimeType);
        mCacheInserter.bind(mCacheEncodingColIndex, c.encoding);
        mCacheInserter.bind(mCacheHttpStatusColIndex, c.httpStatusCode);
        mCacheInserter.bind(mCacheLocationColIndex, c.location);
        mCacheInserter.bind(mCacheContentLengthColIndex, c.contentLength);
        mCacheInserter.execute();
    
voidaddCookie(android.webkit.CookieManager.Cookie cookie)
Add a cookie to the database

param
cookie

        if (cookie.domain == null || cookie.path == null || cookie.name == null
                || mDatabase == null) {
            return;
        }

        synchronized (mCookieLock) {
            ContentValues cookieVal = new ContentValues();
            cookieVal.put(COOKIES_DOMAIN_COL, cookie.domain);
            cookieVal.put(COOKIES_PATH_COL, cookie.path);
            cookieVal.put(COOKIES_NAME_COL, cookie.name);
            cookieVal.put(COOKIES_VALUE_COL, cookie.value);
            if (cookie.expires != -1) {
                cookieVal.put(COOKIES_EXPIRES_COL, cookie.expires);
            }
            cookieVal.put(COOKIES_SECURE_COL, cookie.secure);
            mDatabase.insert(mTableNames[TABLE_COOKIES_ID], null, cookieVal);
        }
    
private static voidbootstrapCacheDatabase()

        if (mCacheDatabase != null) {
            mCacheDatabase.execSQL("CREATE TABLE cache"
                    + " (" + ID_COL + " INTEGER PRIMARY KEY, " + CACHE_URL_COL
                    + " TEXT, " + CACHE_FILE_PATH_COL + " TEXT, "
                    + CACHE_LAST_MODIFY_COL + " TEXT, " + CACHE_ETAG_COL
                    + " TEXT, " + CACHE_EXPIRES_COL + " INTEGER, "
                    + CACHE_MIMETYPE_COL + " TEXT, " + CACHE_ENCODING_COL
                    + " TEXT," + CACHE_HTTP_STATUS_COL + " INTEGER, "
                    + CACHE_LOCATION_COL + " TEXT, " + CACHE_CONTENTLENGTH_COL
                    + " INTEGER, " + " UNIQUE (" + CACHE_URL_COL
                    + ") ON CONFLICT REPLACE);");
            mCacheDatabase.execSQL("CREATE INDEX cacheUrlIndex ON cache ("
                    + CACHE_URL_COL + ")");
        }
    
voidclearCache()
Clear cache database

        if (mCacheDatabase == null) {
            return;
        }

        mCacheDatabase.delete("cache", null, null);
    
voidclearCookies()
Clear cookie database

        if (mDatabase == null) {
            return;
        }

        synchronized (mCookieLock) {
            mDatabase.delete(mTableNames[TABLE_COOKIES_ID], null, null);
        }
    
voidclearExpiredCookies(long now)
Clear expired cookies

param
now Time for now

        if (mDatabase == null) {
            return;
        }

        final String expires = COOKIES_EXPIRES_COL + " <= ?";
        synchronized (mCookieLock) {
            mDatabase.delete(mTableNames[TABLE_COOKIES_ID], expires,
                    new String[] { Long.toString(now) });
        }
    
public voidclearFormData()
Clear form database

        if (mDatabase == null) {
            return;
        }

        synchronized (mFormLock) {
            mDatabase.delete(mTableNames[TABLE_FORMURL_ID], null, null);
            mDatabase.delete(mTableNames[TABLE_FORMDATA_ID], null, null);
        }
    
public voidclearHttpAuthUsernamePassword()
Clear HTTP authentication password database

        if (mDatabase == null) {
            return;
        }

        synchronized (mHttpAuthLock) {
            mDatabase.delete(mTableNames[TABLE_HTTPAUTH_ID], null, null);
        }
    
voidclearSessionCookies()
Clear session cookies, which means cookie doesn't have EXPIRES.

        if (mDatabase == null) {
            return;
        }

        final String sessionExpired = COOKIES_EXPIRES_COL + " ISNULL";
        synchronized (mCookieLock) {
            mDatabase.delete(mTableNames[TABLE_COOKIES_ID], sessionExpired,
                    null);
        }
    
public voidclearUsernamePassword()
Clear password database

        if (mDatabase == null) {
            return;
        }

        synchronized (mPasswordLock) {
            mDatabase.delete(mTableNames[TABLE_PASSWORD_ID], null, null);
        }
    
voiddeleteCookies(java.lang.String domain, java.lang.String path, java.lang.String name)
Delete cookies which matches (domain, path, name).

param
domain If it is null, nothing happens.
param
path If it is null, all the cookies match (domain) will be deleted.
param
name If it is null, all the cookies match (domain, path) will be deleted.

        if (domain == null || mDatabase == null) {
            return;
        }

        synchronized (mCookieLock) {
            final String where = "(" + COOKIES_DOMAIN_COL + " == ?) AND ("
                    + COOKIES_PATH_COL + " == ?) AND (" + COOKIES_NAME_COL
                    + " == ?)";
            mDatabase.delete(mTableNames[TABLE_COOKIES_ID], where,
                    new String[] { domain, path, name });
        }
    
booleanendCacheTransaction()

        if (--mCacheTransactionRefcount == 0) {
            try {
                mCacheDatabase.setTransactionSuccessful();
            } finally {
                mCacheDatabase.endTransaction();
            }
            return true;
        }
        return false;
    
android.webkit.CacheManager.CacheResultgetCache(java.lang.String url)
Get a cache item.

param
url The url
return
CacheResult The CacheManager.CacheResult

        if (url == null || mCacheDatabase == null) {
            return null;
        }

        Cursor cursor = mCacheDatabase.rawQuery("SELECT filepath, lastmodify, etag, expires, "
                    + "mimetype, encoding, httpstatus, location, contentlength "
                    + "FROM cache WHERE url = ?",
                new String[] { url });

        try {
            if (cursor.moveToFirst()) {
                CacheResult ret = new CacheResult();
                ret.localPath = cursor.getString(0);
                ret.lastModified = cursor.getString(1);
                ret.etag = cursor.getString(2);
                ret.expires = cursor.getLong(3);
                ret.mimeType = cursor.getString(4);
                ret.encoding = cursor.getString(5);
                ret.httpStatusCode = cursor.getInt(6);
                ret.location = cursor.getString(7);
                ret.contentLength = cursor.getLong(8);
                return ret;
            }
        } finally {
            if (cursor != null) cursor.close();
        }
        return null;
    
longgetCacheTotalSize()

        long size = 0;
        Cursor cursor = mCacheDatabase.rawQuery(
                "SELECT SUM(contentlength) as sum FROM cache", null);
        if (cursor.moveToFirst()) {
            size = cursor.getLong(0);
        }
        cursor.close();
        return size;
    
java.util.ArrayListgetCookiesForDomain(java.lang.String domain)
Get cookies in the format of CookieManager.Cookie inside an ArrayList for a given domain

return
ArrayList If nothing is found, return an empty list.

        ArrayList<Cookie> list = new ArrayList<Cookie>();
        if (domain == null || mDatabase == null) {
            return list;
        }

        synchronized (mCookieLock) {
            final String[] columns = new String[] {
                    ID_COL, COOKIES_DOMAIN_COL, COOKIES_PATH_COL,
                    COOKIES_NAME_COL, COOKIES_VALUE_COL, COOKIES_EXPIRES_COL,
                    COOKIES_SECURE_COL
            };
            final String selection = "(" + COOKIES_DOMAIN_COL
                    + " GLOB '*' || ?)";
            Cursor cursor = mDatabase.query(mTableNames[TABLE_COOKIES_ID],
                    columns, selection, new String[] { domain }, null, null,
                    null);
            if (cursor.moveToFirst()) {
                int domainCol = cursor.getColumnIndex(COOKIES_DOMAIN_COL);
                int pathCol = cursor.getColumnIndex(COOKIES_PATH_COL);
                int nameCol = cursor.getColumnIndex(COOKIES_NAME_COL);
                int valueCol = cursor.getColumnIndex(COOKIES_VALUE_COL);
                int expiresCol = cursor.getColumnIndex(COOKIES_EXPIRES_COL);
                int secureCol = cursor.getColumnIndex(COOKIES_SECURE_COL);
                do {
                    Cookie cookie = new Cookie();
                    cookie.domain = cursor.getString(domainCol);
                    cookie.path = cursor.getString(pathCol);
                    cookie.name = cursor.getString(nameCol);
                    cookie.value = cursor.getString(valueCol);
                    if (cursor.isNull(expiresCol)) {
                        cookie.expires = -1;
                    } else {
                        cookie.expires = cursor.getLong(expiresCol);
                    }
                    cookie.secure = cursor.getShort(secureCol) != 0;
                    cookie.mode = Cookie.MODE_NORMAL;
                    list.add(cookie);
                } while (cursor.moveToNext());
            }
            cursor.close();
            return list;
        }
    
java.util.ArrayListgetFormData(java.lang.String url, java.lang.String name)
Get all the values for a form entry with "name" in a given site

param
url The url of the site
param
name The name of the form entry
return
A list of values. Return empty list if nothing is found.

        ArrayList<String> values = new ArrayList<String>();
        if (url == null || name == null || mDatabase == null) {
            return values;
        }

        final String urlSelection = "(" + FORMURL_URL_COL + " == ?)";
        final String dataSelection = "(" + FORMDATA_URLID_COL + " == ?) AND ("
                + FORMDATA_NAME_COL + " == ?)";
        synchronized (mFormLock) {
            Cursor cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
                    ID_PROJECTION, urlSelection, new String[] { url }, null,
                    null, null);
            if (cursor.moveToFirst()) {
                long urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
                Cursor dataCursor = mDatabase.query(
                        mTableNames[TABLE_FORMDATA_ID],
                        new String[] { ID_COL, FORMDATA_VALUE_COL },
                        dataSelection,
                        new String[] { Long.toString(urlid), name }, null,
                        null, null);
                if (dataCursor.moveToFirst()) {
                    int valueCol =
                            dataCursor.getColumnIndex(FORMDATA_VALUE_COL);
                    do {
                        values.add(dataCursor.getString(valueCol));
                    } while (dataCursor.moveToNext());
                }
                dataCursor.close();
            }
            cursor.close();
            return values;
        }
    
java.lang.String[]getHttpAuthUsernamePassword(java.lang.String host, java.lang.String realm)
Retrieve the HTTP authentication username and password for a given host+realm pair

param
host The host the password applies to
param
realm The realm the password applies to
return
String[] if found, String[0] is username, which can be null and String[1] is password. Return null if it can't find anything.

        if (host == null || realm == null || mDatabase == null){
            return null;
        }

        final String[] columns = new String[] {
                HTTPAUTH_USERNAME_COL, HTTPAUTH_PASSWORD_COL
        };
        final String selection = "(" + HTTPAUTH_HOST_COL + " == ?) AND ("
                + HTTPAUTH_REALM_COL + " == ?)";
        synchronized (mHttpAuthLock) {
            String[] ret = null;
            Cursor cursor = mDatabase.query(mTableNames[TABLE_HTTPAUTH_ID],
                    columns, selection, new String[] { host, realm }, null,
                    null, null);
            if (cursor.moveToFirst()) {
                ret = new String[2];
                ret[0] = cursor.getString(
                        cursor.getColumnIndex(HTTPAUTH_USERNAME_COL));
                ret[1] = cursor.getString(
                        cursor.getColumnIndex(HTTPAUTH_PASSWORD_COL));
            }
            cursor.close();
            return ret;
        }
    
public static synchronized android.webkit.WebViewDatabasegetInstance(android.content.Context context)

        if (mInstance == null) {
            mInstance = new WebViewDatabase();
            mDatabase = context.openOrCreateDatabase(DATABASE_FILE, 0, null);

            // mDatabase should not be null, 
            // the only case is RequestAPI test has problem to create db 
            if (mDatabase != null && mDatabase.getVersion() != DATABASE_VERSION) {
                mDatabase.beginTransaction();
                try {
                    upgradeDatabase();
                    mDatabase.setTransactionSuccessful();
                } finally {
                    mDatabase.endTransaction();
                }
            }

            if (mDatabase != null) {
                // use per table Mutex lock, turn off database lock, this
                // improves performance as database's ReentrantLock is expansive
                mDatabase.setLockingEnabled(false);
            }

            mCacheDatabase = context.openOrCreateDatabase(CACHE_DATABASE_FILE,
                    0, null);

            // mCacheDatabase should not be null, 
            // the only case is RequestAPI test has problem to create db 
            if (mCacheDatabase != null
                    && mCacheDatabase.getVersion() != CACHE_DATABASE_VERSION) {
                mCacheDatabase.beginTransaction();
                try {
                    upgradeCacheDatabase();
                    bootstrapCacheDatabase();
                    mCacheDatabase.setTransactionSuccessful();
                } finally {
                    mCacheDatabase.endTransaction();
                }
                // Erase the files from the file system in the 
                // case that the database was updated and the 
                // there were existing cache content
                CacheManager.removeAllCacheFiles();
            }

            if (mCacheDatabase != null) {
                // use InsertHelper for faster insertion
                mCacheInserter = new DatabaseUtils.InsertHelper(mCacheDatabase,
                        "cache");
                mCacheUrlColIndex = mCacheInserter
                        .getColumnIndex(CACHE_URL_COL);
                mCacheFilePathColIndex = mCacheInserter
                        .getColumnIndex(CACHE_FILE_PATH_COL);
                mCacheLastModifyColIndex = mCacheInserter
                        .getColumnIndex(CACHE_LAST_MODIFY_COL);
                mCacheETagColIndex = mCacheInserter
                        .getColumnIndex(CACHE_ETAG_COL);
                mCacheExpiresColIndex = mCacheInserter
                        .getColumnIndex(CACHE_EXPIRES_COL);
                mCacheMimeTypeColIndex = mCacheInserter
                        .getColumnIndex(CACHE_MIMETYPE_COL);
                mCacheEncodingColIndex = mCacheInserter
                        .getColumnIndex(CACHE_ENCODING_COL);
                mCacheHttpStatusColIndex = mCacheInserter
                        .getColumnIndex(CACHE_HTTP_STATUS_COL);
                mCacheLocationColIndex = mCacheInserter
                        .getColumnIndex(CACHE_LOCATION_COL);
                mCacheContentLengthColIndex = mCacheInserter
                        .getColumnIndex(CACHE_CONTENTLENGTH_COL);
            }
        }

        return mInstance;
    
java.lang.String[]getUsernamePassword(java.lang.String schemePlusHost)
Retrieve the username and password for a given host

param
schemePlusHost The scheme and host which passwords applies to
return
String[] if found, String[0] is username, which can be null and String[1] is password. Return null if it can't find anything.

        if (schemePlusHost == null || mDatabase == null) {
            return null;
        }

        final String[] columns = new String[] {
                PASSWORD_USERNAME_COL, PASSWORD_PASSWORD_COL
        };
        final String selection = "(" + PASSWORD_HOST_COL + " == ?)";
        synchronized (mPasswordLock) {
            String[] ret = null;
            Cursor cursor = mDatabase.query(mTableNames[TABLE_PASSWORD_ID],
                    columns, selection, new String[] { schemePlusHost }, null,
                    null, null);
            if (cursor.moveToFirst()) {
                ret = new String[2];
                ret[0] = cursor.getString(
                        cursor.getColumnIndex(PASSWORD_USERNAME_COL));
                ret[1] = cursor.getString(
                        cursor.getColumnIndex(PASSWORD_PASSWORD_COL));
            }
            cursor.close();
            return ret;
        }
    
booleanhasCache()

        if (mCacheDatabase == null) {
            return false;
        }

        Cursor cursor = mCacheDatabase.query("cache", ID_PROJECTION,
                null, null, null, null, null);
        boolean ret = cursor.moveToFirst() == true;
        cursor.close();
        return ret;
    
booleanhasCookies()
Whether there is any cookies in the database

return
TRUE if there is cookie.

        synchronized (mCookieLock) {
            return hasEntries(TABLE_COOKIES_ID);
        }
    
private booleanhasEntries(int tableId)

        if (mDatabase == null) {
            return false;
        }

        Cursor cursor = mDatabase.query(mTableNames[tableId], ID_PROJECTION,
                null, null, null, null, null);
        boolean ret = cursor.moveToFirst() == true;
        cursor.close();
        return ret;
    
public booleanhasFormData()
Find out if there is form data saved.

return
TRUE if there is form data in the database

        synchronized (mFormLock) {
            return hasEntries(TABLE_FORMURL_ID);
        }
    
public booleanhasHttpAuthUsernamePassword()
Find out if there are any HTTP authentication passwords saved.

return
TRUE if there are passwords saved

        synchronized (mHttpAuthLock) {
            return hasEntries(TABLE_HTTPAUTH_ID);
        }
    
public booleanhasUsernamePassword()
Find out if there are any passwords saved.

return
TRUE if there is passwords saved

        synchronized (mPasswordLock) {
            return hasEntries(TABLE_PASSWORD_ID);
        }
    
voidremoveCache(java.lang.String url)
Remove a cache item.

param
url The url

        if (url == null || mCacheDatabase == null) {
            return;
        }

        mCacheDatabase.execSQL("DELETE FROM cache WHERE url = ?", new String[] { url });
    
voidsetFormData(java.lang.String url, java.util.HashMap formdata)
Set form data for a site. Tuple (FORMDATA_URLID_COL, FORMDATA_NAME_COL, FORMDATA_VALUE_COL) is unique

param
url The url of the site
param
formdata The form data in HashMap

        if (url == null || formdata == null || mDatabase == null) {
            return;
        }

        final String selection = "(" + FORMURL_URL_COL + " == ?)";
        synchronized (mFormLock) {
            long urlid = -1;
            Cursor cursor = mDatabase.query(mTableNames[TABLE_FORMURL_ID],
                    ID_PROJECTION, selection, new String[] { url }, null, null,
                    null);
            if (cursor.moveToFirst()) {
                urlid = cursor.getLong(cursor.getColumnIndex(ID_COL));
            } else {
                ContentValues c = new ContentValues();
                c.put(FORMURL_URL_COL, url);
                urlid = mDatabase.insert(
                        mTableNames[TABLE_FORMURL_ID], null, c);
            }
            cursor.close();
            if (urlid >= 0) {
                Set<Entry<String, String>> set = formdata.entrySet();
                Iterator<Entry<String, String>> iter = set.iterator();
                ContentValues map = new ContentValues();
                map.put(FORMDATA_URLID_COL, urlid);
                while (iter.hasNext()) {
                    Entry<String, String> entry = iter.next();
                    map.put(FORMDATA_NAME_COL, entry.getKey());
                    map.put(FORMDATA_VALUE_COL, entry.getValue());
                    mDatabase.insert(mTableNames[TABLE_FORMDATA_ID], null, map);
                }
            }
        }
    
voidsetHttpAuthUsernamePassword(java.lang.String host, java.lang.String realm, java.lang.String username, java.lang.String password)
Set HTTP authentication password. Tuple (HTTPAUTH_HOST_COL, HTTPAUTH_REALM_COL, HTTPAUTH_USERNAME_COL) is unique.

param
host The host for the password
param
realm The realm for the password
param
username The username for the password. If it is null, it means password can't be saved.
param
password The password

        if (host == null || realm == null || mDatabase == null) {
            return;
        }

        synchronized (mHttpAuthLock) {
            final ContentValues c = new ContentValues();
            c.put(HTTPAUTH_HOST_COL, host);
            c.put(HTTPAUTH_REALM_COL, realm);
            c.put(HTTPAUTH_USERNAME_COL, username);
            c.put(HTTPAUTH_PASSWORD_COL, password);
            mDatabase.insert(mTableNames[TABLE_HTTPAUTH_ID], HTTPAUTH_HOST_COL,
                    c);
        }
    
voidsetUsernamePassword(java.lang.String schemePlusHost, java.lang.String username, java.lang.String password)
Set password. Tuple (PASSWORD_HOST_COL, PASSWORD_USERNAME_COL) is unique.

param
schemePlusHost The scheme and host for the password
param
username The username for the password. If it is null, it means password can't be saved.
param
password The password

        if (schemePlusHost == null || mDatabase == null) {
            return;
        }

        synchronized (mPasswordLock) {
            final ContentValues c = new ContentValues();
            c.put(PASSWORD_HOST_COL, schemePlusHost);
            c.put(PASSWORD_USERNAME_COL, username);
            c.put(PASSWORD_PASSWORD_COL, password);
            mDatabase.insert(mTableNames[TABLE_PASSWORD_ID], PASSWORD_HOST_COL,
                    c);
        }
    
booleanstartCacheTransaction()

        if (++mCacheTransactionRefcount == 1) {
            mCacheDatabase.beginTransaction();
            return true;
        }
        return false;
    
java.util.ArrayListtrimCache(long amount)

        ArrayList<String> pathList = new ArrayList<String>(100);
        Cursor cursor = mCacheDatabase.rawQuery(
                "SELECT contentlength, filepath FROM cache ORDER BY expires ASC",
                null);
        if (cursor.moveToFirst()) {
            int batchSize = 100;
            StringBuilder pathStr = new StringBuilder(20 + 16 * batchSize);
            pathStr.append("DELETE FROM cache WHERE filepath IN (?");
            for (int i = 1; i < batchSize; i++) {
                pathStr.append(", ?");
            }
            pathStr.append(")");
            SQLiteStatement statement = mCacheDatabase.compileStatement(pathStr
                    .toString());
            // as bindString() uses 1-based index, initialize index to 1
            int index = 1;
            do {
                long length = cursor.getLong(0);
                if (length == 0) {
                    continue;
                }
                amount -= length;
                String filePath = cursor.getString(1);
                statement.bindString(index, filePath);
                pathList.add(filePath);
                if (index++ == batchSize) {
                    statement.execute();
                    statement.clearBindings();
                    index = 1;
                }
            } while (cursor.moveToNext() && amount > 0);
            if (index > 1) {
                // there may be old bindings from the previous statement if
                // index is less than batchSize, which is Ok.
                statement.execute();
            }
            statement.close();
        }
        cursor.close();
        return pathList;
    
private static voidupgradeCacheDatabase()

        int oldVersion = mCacheDatabase.getVersion();
        if (oldVersion != 0) {
            Log.i(LOGTAG, "Upgrading cache database from version "
                    + oldVersion + " to "
                    + DATABASE_VERSION + ", which will destroy all old data");
        }
        mCacheDatabase.execSQL("DROP TABLE IF EXISTS cache");
        mCacheDatabase.setVersion(CACHE_DATABASE_VERSION);
    
private static voidupgradeDatabase()

        int oldVersion = mDatabase.getVersion();
        if (oldVersion != 0) {
            Log.i(LOGTAG, "Upgrading database from version "
                    + oldVersion + " to "
                    + DATABASE_VERSION + ", which will destroy old data");
        }
        boolean justPasswords = 8 == oldVersion && 9 == DATABASE_VERSION;
        if (!justPasswords) {
            mDatabase.execSQL("DROP TABLE IF EXISTS "
                    + mTableNames[TABLE_COOKIES_ID]);
            mDatabase.execSQL("DROP TABLE IF EXISTS cache");
            mDatabase.execSQL("DROP TABLE IF EXISTS "
                    + mTableNames[TABLE_FORMURL_ID]);
            mDatabase.execSQL("DROP TABLE IF EXISTS "
                    + mTableNames[TABLE_FORMDATA_ID]);
            mDatabase.execSQL("DROP TABLE IF EXISTS "
                    + mTableNames[TABLE_HTTPAUTH_ID]);
        }
        mDatabase.execSQL("DROP TABLE IF EXISTS "
                + mTableNames[TABLE_PASSWORD_ID]);

        mDatabase.setVersion(DATABASE_VERSION);

        if (!justPasswords) {
            // cookies
            mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_COOKIES_ID]
                    + " (" + ID_COL + " INTEGER PRIMARY KEY, "
                    + COOKIES_NAME_COL + " TEXT, " + COOKIES_VALUE_COL
                    + " TEXT, " + COOKIES_DOMAIN_COL + " TEXT, "
                    + COOKIES_PATH_COL + " TEXT, " + COOKIES_EXPIRES_COL
                    + " INTEGER, " + COOKIES_SECURE_COL + " INTEGER" + ");");
            mDatabase.execSQL("CREATE INDEX cookiesIndex ON "
                    + mTableNames[TABLE_COOKIES_ID] + " (path)");

            // formurl
            mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMURL_ID]
                    + " (" + ID_COL + " INTEGER PRIMARY KEY, " + FORMURL_URL_COL
                    + " TEXT" + ");");

            // formdata
            mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_FORMDATA_ID]
                    + " (" + ID_COL + " INTEGER PRIMARY KEY, "
                    + FORMDATA_URLID_COL + " INTEGER, " + FORMDATA_NAME_COL
                    + " TEXT, " + FORMDATA_VALUE_COL + " TEXT," + " UNIQUE ("
                    + FORMDATA_URLID_COL + ", " + FORMDATA_NAME_COL + ", "
                    + FORMDATA_VALUE_COL + ") ON CONFLICT IGNORE);");

            // httpauth
            mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_HTTPAUTH_ID]
                    + " (" + ID_COL + " INTEGER PRIMARY KEY, "
                    + HTTPAUTH_HOST_COL + " TEXT, " + HTTPAUTH_REALM_COL
                    + " TEXT, " + HTTPAUTH_USERNAME_COL + " TEXT, "
                    + HTTPAUTH_PASSWORD_COL + " TEXT," + " UNIQUE ("
                    + HTTPAUTH_HOST_COL + ", " + HTTPAUTH_REALM_COL + ", "
                    + HTTPAUTH_USERNAME_COL + ") ON CONFLICT REPLACE);");
        }
        // passwords
        mDatabase.execSQL("CREATE TABLE " + mTableNames[TABLE_PASSWORD_ID]
                + " (" + ID_COL + " INTEGER PRIMARY KEY, "
                + PASSWORD_HOST_COL + " TEXT, " + PASSWORD_USERNAME_COL
                + " TEXT, " + PASSWORD_PASSWORD_COL + " TEXT," + " UNIQUE ("
                + PASSWORD_HOST_COL + ", " + PASSWORD_USERNAME_COL
                + ") ON CONFLICT REPLACE);");