diff --git a/mobile/android/base/ProfileMigrator.java b/mobile/android/base/ProfileMigrator.java index 3b3123ed19c..a7f4bd30ef9 100644 --- a/mobile/android/base/ProfileMigrator.java +++ b/mobile/android/base/ProfileMigrator.java @@ -216,12 +216,12 @@ public class ProfileMigrator { return isBookmarksMigrated() && isHistoryMigrated(); } - protected SharedPreferences getPreferences() { - return GeckoApp.mAppContext.getSharedPreferences(PREFS_NAME, 0); + public boolean isBookmarksMigrated() { + return getPreferences().getBoolean(PREFS_MIGRATE_BOOKMARKS_DONE, false); } - protected boolean isBookmarksMigrated() { - return getPreferences().getBoolean(PREFS_MIGRATE_BOOKMARKS_DONE, false); + protected SharedPreferences getPreferences() { + return GeckoApp.mAppContext.getSharedPreferences(PREFS_NAME, 0); } protected boolean isHistoryMigrated() { diff --git a/mobile/android/base/db/BrowserContract.java.in b/mobile/android/base/db/BrowserContract.java.in index 211f35c8c65..5edd61a204f 100644 --- a/mobile/android/base/db/BrowserContract.java.in +++ b/mobile/android/base/db/BrowserContract.java.in @@ -159,6 +159,17 @@ public class BrowserContract { 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"); diff --git a/mobile/android/base/db/BrowserProvider.java.in b/mobile/android/base/db/BrowserProvider.java.in index f3c9855139e..58bf16e3b87 100644 --- a/mobile/android/base/db/BrowserProvider.java.in +++ b/mobile/android/base/db/BrowserProvider.java.in @@ -27,6 +27,7 @@ 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; @@ -34,6 +35,7 @@ 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; @@ -105,6 +107,9 @@ public class BrowserProvider extends ContentProvider { // 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"; @@ -211,6 +216,10 @@ public class BrowserProvider extends ContentProvider { map = new HashMap(); map.put(Schema.VERSION, Schema.VERSION); SCHEMA_PROJECTION_MAP = Collections.unmodifiableMap(map); + + + // Control + URI_MATCHER.addURI(BrowserContract.AUTHORITY, "control", CONTROL); } private HashMap mDatabasePerProfile; @@ -1403,6 +1412,74 @@ public class BrowserProvider extends ContentProvider { 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) { @@ -1512,6 +1589,15 @@ public class BrowserProvider extends ContentProvider { 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); }