Bug 725150 - Expose CONTROL Uri for BrowserProvider. r=lucasr
authorGian-Carlo Pascutto <gpascutto@mozilla.com>
Wed, 04 Apr 2012 21:48:46 +0200
changeset 94333 02b15cf9157fb02b4132ed25b5009ac40dcf6812
parent 94332 b6cc76f45b95e6637cf6fee180f52ab591d320a0
child 94334 f1e4ac6159f882274386adc5a9de6b28f92ccd11
push id886
push userlsblakk@mozilla.com
push dateMon, 04 Jun 2012 19:57:52 +0000
treeherdermozilla-beta@bbd8d5efd6d1 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerslucasr
bugs725150
milestone14.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 725150 - Expose CONTROL Uri for BrowserProvider. r=lucasr
mobile/android/base/ProfileMigrator.java
mobile/android/base/db/BrowserContract.java.in
mobile/android/base/db/BrowserProvider.java.in
--- a/mobile/android/base/ProfileMigrator.java
+++ b/mobile/android/base/ProfileMigrator.java
@@ -211,24 +211,24 @@ public class ProfileMigrator {
         return isBookmarksMigrated() && (getMigratedHistoryEntries() > 0);
     }
 
     // Has migration entirely finished?
     public boolean hasMigrationFinished() {
         return isBookmarksMigrated() && isHistoryMigrated();
     }
 
+    public boolean isBookmarksMigrated() {
+        return getPreferences().getBoolean(PREFS_MIGRATE_BOOKMARKS_DONE, false);
+    }
+
     protected SharedPreferences getPreferences() {
         return GeckoApp.mAppContext.getSharedPreferences(PREFS_NAME, 0);
     }
 
-    protected boolean isBookmarksMigrated() {
-        return getPreferences().getBoolean(PREFS_MIGRATE_BOOKMARKS_DONE, false);
-    }
-
     protected boolean isHistoryMigrated() {
         return getPreferences().getBoolean(PREFS_MIGRATE_HISTORY_DONE, false);
     }
 
     protected int getMigratedHistoryEntries() {
         return getPreferences().getInt(PREFS_MIGRATE_HISTORY_COUNT, 0);
     }
 
--- a/mobile/android/base/db/BrowserContract.java.in
+++ b/mobile/android/base/db/BrowserContract.java.in
@@ -154,16 +154,27 @@ public class BrowserContract {
 
     public static final class Schema {
         private Schema() {}
         public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "schema");
 
         public static final String VERSION = "version";
     }
 
+    public static final class Control {
+        private Control() {}
+
+        public static final Uri CONTENT_URI = Uri.withAppendedPath(AUTHORITY_URI, "control");
+
+        // Check if history was completely migrated, do a bunch if it wasn't.
+        public static final String ENSURE_HISTORY_MIGRATED = "ensure_history_migrated";
+        // Check if bookmarks were completely migrated, migrate them if not.
+        public static final String ENSURE_BOOKMARKS_MIGRATED = "ensure_bookmarks_migrated";
+    }
+
     public static final class Passwords {
         private Passwords() {}
         public static final Uri CONTENT_URI = Uri.withAppendedPath(PASSWORDS_AUTHORITY_URI, "passwords");
         public static final String CONTENT_TYPE = "vnd.android.cursor.dir/passwords";
 
         public static final String ID = "id";
         public static final String HOSTNAME = "hostname";
         public static final String HTTP_REALM = "httpRealm";
--- a/mobile/android/base/db/BrowserProvider.java.in
+++ b/mobile/android/base/db/BrowserProvider.java.in
@@ -22,23 +22,25 @@ import java.util.regex.Pattern;
 import java.util.regex.Matcher;
 
 import org.mozilla.gecko.GeckoBackgroundThread;
 import org.mozilla.gecko.GeckoProfile;
 import org.mozilla.gecko.R;
 import org.mozilla.gecko.db.BrowserContract.Bookmarks;
 import org.mozilla.gecko.db.BrowserContract.Combined;
 import org.mozilla.gecko.db.BrowserContract.CommonColumns;
+import org.mozilla.gecko.db.BrowserContract.Control;
 import org.mozilla.gecko.db.BrowserContract.History;
 import org.mozilla.gecko.db.BrowserContract.Images;
 import org.mozilla.gecko.db.BrowserContract.Schema;
 import org.mozilla.gecko.db.BrowserContract.SyncColumns;
 import org.mozilla.gecko.db.BrowserContract.URLColumns;
 import org.mozilla.gecko.db.BrowserContract;
 import org.mozilla.gecko.db.DBUtils;
+import org.mozilla.gecko.ProfileMigrator;
 import org.mozilla.gecko.sync.Utils;
 
 import android.content.ContentProvider;
 import android.content.ContentUris;
 import android.content.ContentValues;
 import android.content.ContentProviderResult;
 import android.content.ContentProviderOperation;
 import android.content.OperationApplicationException;
@@ -100,16 +102,19 @@ public class BrowserProvider extends Con
     static final int IMAGES_ID = 301;
 
     // Schema matches
     static final int SCHEMA = 400;
 
     // Combined bookmarks and history matches
     static final int COMBINED = 500;
 
+    // Control matches
+    static final int CONTROL = 600;
+
     static final String DEFAULT_BOOKMARKS_SORT_ORDER = Bookmarks.TYPE
             + " ASC, " + Bookmarks.POSITION + " ASC, " + Bookmarks._ID
             + " ASC";
 
     static final String DEFAULT_HISTORY_SORT_ORDER = History.DATE_LAST_VISITED + " DESC";
 
     static final String TABLE_BOOKMARKS_JOIN_IMAGES = TABLE_BOOKMARKS + " LEFT OUTER JOIN " +
             TABLE_IMAGES + " ON " + qualifyColumn(TABLE_BOOKMARKS, Bookmarks.URL) + " = " +
@@ -206,16 +211,20 @@ public class BrowserProvider extends Con
         COMBINED_PROJECTION_MAP = Collections.unmodifiableMap(map);
 
         // Schema
         URI_MATCHER.addURI(BrowserContract.AUTHORITY, "schema", SCHEMA);
 
         map = new HashMap<String, String>();
         map.put(Schema.VERSION, Schema.VERSION);
         SCHEMA_PROJECTION_MAP = Collections.unmodifiableMap(map);
+
+
+        // Control
+        URI_MATCHER.addURI(BrowserContract.AUTHORITY, "control", CONTROL);
     }
 
     private HashMap<String, DatabaseHelper> mDatabasePerProfile;
 
     private interface BookmarkMigrator {
         public void updateForNewTable(ContentValues bookmark);
     }
 
@@ -1398,16 +1407,84 @@ public class BrowserProvider extends Con
                 throw new UnsupportedOperationException("Unknown update URI " + uri);
         }
 
         debug("Updated " + updated + " rows for URI: " + uri);
 
         return updated;
     }
 
+    private Cursor controlQuery(Uri uri,
+                                String[] projection, String selection,
+                                String[] selectionArgs, String sortOrder) {
+
+        trace("controlQuery projection = " + projection);
+
+        final String[] allFields = {
+            Control.ENSURE_BOOKMARKS_MIGRATED,
+            Control.ENSURE_HISTORY_MIGRATED
+        };
+
+        // null projection must return all fields.
+        if (projection == null) {
+            projection = allFields;
+        }
+
+        if (selection != null) {
+            throw new UnsupportedOperationException("No selection in virtual CONTROL queries");
+        }
+
+        File profileDir = GeckoProfile.get(mContext).getDir();
+
+        if (uri != null) {
+            String profile = uri.getQueryParameter(BrowserContract.PARAM_PROFILE);
+            if (!TextUtils.isEmpty(profile)) {
+                profileDir = GeckoProfile.get(mContext, profile).getDir();
+            }
+        }
+
+        MatrixCursor cursor = new MatrixCursor(projection);
+        MatrixCursor.RowBuilder row = cursor.newRow();
+        synchronized (this) {
+            for (String key : projection) {
+                ProfileMigrator migrator =
+                    new ProfileMigrator(mContext.getContentResolver(), profileDir);
+                if (key.equals(Control.ENSURE_BOOKMARKS_MIGRATED)) {
+                    if (migrator.isBookmarksMigrated()) {
+                        // generic Cursor has no boolean support, use ints.
+                        row.add(1);
+                    } else {
+                        // Start migration.
+                        migrator.launch();
+                        boolean bookmarksDone = migrator.isBookmarksMigrated();
+
+                        // We expect bookmarks to finish in one pass. Warn if
+                        // this is not the case.
+                        if (!bookmarksDone) {
+                            Log.w(LOGTAG, "Bookmarks migration did not finish.");
+                        }
+
+                        row.add(bookmarksDone ? 1 : 0);
+                    }
+                } else if (key.equals(Control.ENSURE_HISTORY_MIGRATED)) {
+                    // Are we done?
+                    if (migrator.hasMigrationFinished()) {
+                        row.add(1);
+                    } else {
+                        // Migrate some more
+                        migrator.launch();
+                        // Are we done now?
+                        row.add(migrator.hasMigrationFinished() ? 1 : 0);
+                    }
+                }
+            }
+        }
+        return cursor;
+    }
+
     @Override
     public Cursor query(Uri uri, String[] projection, String selection,
             String[] selectionArgs, String sortOrder) {
         SQLiteDatabase db = getReadableDatabase(uri);
         final int match = URI_MATCHER.match(uri);
 
         SQLiteQueryBuilder qb = new SQLiteQueryBuilder();
         String limit = uri.getQueryParameter(BrowserContract.PARAM_LIMIT);
@@ -1507,16 +1584,25 @@ public class BrowserProvider extends Con
                     sortOrder = DEFAULT_HISTORY_SORT_ORDER;
 
                 qb.setProjectionMap(COMBINED_PROJECTION_MAP);
                 qb.setTables(VIEW_COMBINED_WITH_IMAGES);
 
                 break;
             }
 
+            case CONTROL: {
+                debug("Query is on control: " + uri);
+
+                Cursor controlCursor =
+                    controlQuery(uri, projection, selection, selectionArgs, sortOrder);
+
+                return controlCursor;
+            }
+
             default:
                 throw new UnsupportedOperationException("Unknown query URI " + uri);
         }
 
         trace("Running built query.");
         Cursor cursor = qb.query(db, projection, selection, selectionArgs, null,
                 null, sortOrder, limit);
         cursor.setNotificationUri(getContext().getContentResolver(),