mobile/android/base/db/SharedBrowserDatabaseProvider.java

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 package org.mozilla.gecko.db;
     7 import org.mozilla.gecko.db.BrowserContract.CommonColumns;
     8 import org.mozilla.gecko.db.BrowserContract.SyncColumns;
     9 import org.mozilla.gecko.db.PerProfileDatabases.DatabaseHelperFactory;
    11 import android.content.Context;
    12 import android.database.Cursor;
    13 import android.database.sqlite.SQLiteDatabase;
    14 import android.net.Uri;
    15 import android.util.Log;
    17 /**
    18  * A ContentProvider subclass that provides per-profile browser.db access
    19  * that can be safely shared between multiple providers.
    20  *
    21  * If multiple ContentProvider classes wish to share a database, it's
    22  * vitally important that they use the same SQLiteOpenHelpers for access.
    23  *
    24  * Failure to do so can cause accidental concurrent writes, with the result
    25  * being unexpected SQLITE_BUSY errors.
    26  *
    27  * This class provides a static {@link PerProfileDatabases} instance, lazily
    28  * initialized within {@link SharedBrowserDatabaseProvider#onCreate()}.
    29  */
    30 public abstract class SharedBrowserDatabaseProvider extends AbstractPerProfileDatabaseProvider {
    31     private static final String LOGTAG = SharedBrowserDatabaseProvider.class.getSimpleName();
    33     private static PerProfileDatabases<BrowserDatabaseHelper> databases;
    35     @Override
    36     protected PerProfileDatabases<BrowserDatabaseHelper> getDatabases() {
    37         return databases;
    38     }
    40     @Override
    41     public boolean onCreate() {
    42         // If necessary, do the shared DB work.
    43         synchronized (SharedBrowserDatabaseProvider.class) {
    44             if (databases != null) {
    45                 return true;
    46             }
    48             final DatabaseHelperFactory<BrowserDatabaseHelper> helperFactory = new DatabaseHelperFactory<BrowserDatabaseHelper>() {
    49                 @Override
    50                 public BrowserDatabaseHelper makeDatabaseHelper(Context context, String databasePath) {
    51                     return new BrowserDatabaseHelper(context, databasePath);
    52                 }
    53             };
    55             databases = new PerProfileDatabases<BrowserDatabaseHelper>(getContext(), BrowserDatabaseHelper.DATABASE_NAME, helperFactory);
    56         }
    58         return true;
    59     }
    61     /**
    62      * Clean up some deleted records from the specified table.
    63      *
    64      * If called in an existing transaction, it is the caller's responsibility
    65      * to ensure that the transaction is already upgraded to a writer, because
    66      * this method issues a read followed by a write, and thus is potentially
    67      * vulnerable to an unhandled SQLITE_BUSY failure during the upgrade.
    68      *
    69      * If not called in an existing transaction, no new explicit transaction
    70      * will be begun.
    71      */
    72     protected void cleanUpSomeDeletedRecords(Uri fromUri, String tableName) {
    73         Log.d(LOGTAG, "Cleaning up deleted records from " + tableName);
    75         // We clean up records marked as deleted that are older than a
    76         // predefined max age. It's important not be too greedy here and
    77         // remove only a few old deleted records at a time.
    79         // we cleanup records marked as deleted that are older than a
    80         // predefined max age. It's important not be too greedy here and
    81         // remove only a few old deleted records at a time.
    83         // Maximum age of deleted records to be cleaned up (20 days in ms)
    84         final long MAX_AGE_OF_DELETED_RECORDS = 86400000 * 20;
    86         // Number of records marked as deleted to be removed
    87         final long DELETED_RECORDS_PURGE_LIMIT = 5;
    89         // Android SQLite doesn't have LIMIT on DELETE. Instead, query for the
    90         // IDs of matching rows, then delete them in one go.
    91         final long now = System.currentTimeMillis();
    92         final String selection = SyncColumns.IS_DELETED + " = 1 AND " +
    93                 SyncColumns.DATE_MODIFIED + " <= " +
    94                 (now - MAX_AGE_OF_DELETED_RECORDS);
    96         final String profile = fromUri.getQueryParameter(BrowserContract.PARAM_PROFILE);
    97         final SQLiteDatabase db = getWritableDatabaseForProfile(profile, isTest(fromUri));
    98         final String[] ids;
    99         final String limit = Long.toString(DELETED_RECORDS_PURGE_LIMIT, 10);
   100         final Cursor cursor = db.query(tableName, new String[] { CommonColumns._ID }, selection, null, null, null, null, limit);
   101         try {
   102             ids = new String[cursor.getCount()];
   103             int i = 0;
   104             while (cursor.moveToNext()) {
   105                 ids[i++] = Long.toString(cursor.getLong(0), 10);
   106             }
   107         } finally {
   108             cursor.close();
   109         }
   111         final String inClause = computeSQLInClause(ids.length,
   112                 CommonColumns._ID);
   113         db.delete(tableName, inClause, ids);
   114     }
   115 }

mercurial