--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserDatabaseHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserDatabaseHelper.java
@@ -27,16 +27,17 @@ import org.mozilla.gecko.db.BrowserContr
import org.mozilla.gecko.db.BrowserContract.History;
import org.mozilla.gecko.db.BrowserContract.Visits;
import org.mozilla.gecko.db.BrowserContract.PageMetadata;
import org.mozilla.gecko.db.BrowserContract.Numbers;
import org.mozilla.gecko.db.BrowserContract.ReadingListItems;
import org.mozilla.gecko.db.BrowserContract.SearchHistory;
import org.mozilla.gecko.db.BrowserContract.Thumbnails;
import org.mozilla.gecko.db.BrowserContract.UrlAnnotations;
+import org.mozilla.gecko.db.BrowserContract.FormAutofill;
import org.mozilla.gecko.fxa.FirefoxAccounts;
import org.mozilla.gecko.reader.SavedReaderViewHelper;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.repositories.android.RepoUtils;
import org.mozilla.gecko.util.FileUtils;
import static org.mozilla.gecko.db.DBUtils.qualifyColumn;
@@ -55,17 +56,17 @@ import android.util.Log;
// public for robocop testing
public final class BrowserDatabaseHelper extends SQLiteOpenHelper {
private static final String LOGTAG = "GeckoBrowserDBHelper";
// Replace the Bug number below with your Bug that is conducting a DB upgrade, as to force a merge conflict with any
// other patches that require a DB upgrade.
- public static final int DATABASE_VERSION = 36; // Bug 1301717
+ public static final int DATABASE_VERSION = 37; // Bug 1360359
public static final String DATABASE_NAME = "browser.db";
final protected Context mContext;
static final String TABLE_BOOKMARKS = Bookmarks.TABLE_NAME;
static final String TABLE_HISTORY = History.TABLE_NAME;
static final String TABLE_VISITS = Visits.TABLE_NAME;
static final String TABLE_PAGE_METADATA = PageMetadata.TABLE_NAME;
@@ -73,16 +74,17 @@ public final class BrowserDatabaseHelper
static final String TABLE_THUMBNAILS = Thumbnails.TABLE_NAME;
static final String TABLE_READING_LIST = ReadingListItems.TABLE_NAME;
static final String TABLE_TABS = TabsProvider.TABLE_TABS;
static final String TABLE_CLIENTS = TabsProvider.TABLE_CLIENTS;
static final String TABLE_LOGINS = BrowserContract.Logins.TABLE_LOGINS;
static final String TABLE_DELETED_LOGINS = BrowserContract.DeletedLogins.TABLE_DELETED_LOGINS;
static final String TABLE_DISABLED_HOSTS = BrowserContract.LoginsDisabledHosts.TABLE_DISABLED_HOSTS;
static final String TABLE_ANNOTATIONS = UrlAnnotations.TABLE_NAME;
+ static final String TABLE_FORM_AUTOFILL = FormAutofill.TABLE_NAME;
static final String VIEW_COMBINED = Combined.VIEW_NAME;
static final String VIEW_BOOKMARKS_WITH_FAVICONS = Bookmarks.VIEW_WITH_FAVICONS;
static final String VIEW_BOOKMARKS_WITH_ANNOTATIONS = Bookmarks.VIEW_WITH_ANNOTATIONS;
static final String VIEW_HISTORY_WITH_FAVICONS = History.VIEW_WITH_FAVICONS;
static final String VIEW_COMBINED_WITH_FAVICONS = Combined.VIEW_WITH_FAVICONS;
static final String TABLE_BOOKMARKS_JOIN_FAVICONS = TABLE_BOOKMARKS + " LEFT OUTER JOIN " +
@@ -294,16 +296,31 @@ public final class BrowserDatabaseHelper
BrowserContract.Tabs.POSITION + " INTEGER, " +
"FOREIGN KEY (" + BrowserContract.Tabs.CLIENT_GUID + ") REFERENCES " +
TABLE_CLIENTS + "(" + BrowserContract.Clients.GUID + ") ON DELETE CASCADE" +
");");
didCreateTabsTable = true;
}
+ private void createFormAutofillTable(SQLiteDatabase db) {
+ debug("Creating " + TABLE_FORM_AUTOFILL + " table");
+ db.execSQL("CREATE TABLE " + TABLE_FORM_AUTOFILL + "(" +
+ FormAutofill._ID + " INTEGER PRIMARY KEY AUTOINCREMENT," +
+ FormAutofill.GUID + " TEXT NOT NULL," +
+ FormAutofill.JSON + " TEXT, " +
+ FormAutofill.IS_DELETED + " TINYINT NOT NULL DEFAULT 0, " +
+ FormAutofill.DATE_CREATED + " INTEGER NOT NULL, " +
+ FormAutofill.DATE_MODIFIED + " INTEGER NOT NULL" +
+ ");");
+
+ db.execSQL("CREATE UNIQUE INDEX form_autofill_guid_index ON " + TABLE_FORM_AUTOFILL + '('
+ + FormAutofill.GUID + ')');
+ }
+
private void createTabsTableIndices(SQLiteDatabase db, final String tableName) {
// Indices on CLIENT_GUID and POSITION.
db.execSQL("CREATE INDEX " + TabsProvider.INDEX_TABS_GUID +
" ON " + tableName + "(" + BrowserContract.Tabs.CLIENT_GUID + ")");
db.execSQL("CREATE INDEX " + TabsProvider.INDEX_TABS_POSITION +
" ON " + tableName + "(" + BrowserContract.Tabs.POSITION + ")");
}
@@ -746,16 +763,18 @@ public final class BrowserDatabaseHelper
createBookmarksWithAnnotationsView(db);
createVisitsTable(db);
createCombinedViewOn34(db);
createActivityStreamBlocklistTable(db);
createPageMetadataTable(db);
+
+ createFormAutofillTable(db);
}
/**
* Copies the tabs and clients tables out of the given tabs.db file and into the destinationDB.
*
* @param tabsDBFile Path to existing tabs.db.
* @param destinationDB The destination database.
*/
@@ -1975,16 +1994,20 @@ public final class BrowserDatabaseHelper
private void upgradeDatabaseFrom34to35(final SQLiteDatabase db) {
createActivityStreamBlocklistTable(db);
}
private void upgradeDatabaseFrom35to36(final SQLiteDatabase db) {
createPageMetadataTable(db);
}
+ private void upgradeDatabaseFrom36to37(final SQLiteDatabase db) {
+ createFormAutofillTable(db);
+ }
+
private void createV33CombinedView(final SQLiteDatabase db) {
db.execSQL("DROP VIEW IF EXISTS " + VIEW_COMBINED);
db.execSQL("DROP VIEW IF EXISTS " + VIEW_COMBINED_WITH_FAVICONS);
createCombinedViewOn33(db);
}
private void createV34CombinedView(final SQLiteDatabase db) {
@@ -2110,16 +2133,20 @@ public final class BrowserDatabaseHelper
case 35:
upgradeDatabaseFrom34to35(db);
break;
case 36:
upgradeDatabaseFrom35to36(db);
break;
+
+ case 37:
+ upgradeDatabaseFrom36to37(db);
+ break;
}
}
for (Table table : BrowserProvider.sTables) {
table.onUpgrade(db, oldVersion, newVersion);
}
// Delete the obsolete favicon database after all other upgrades complete.
--- a/mobile/android/base/java/org/mozilla/gecko/db/BrowserProvider.java
+++ b/mobile/android/base/java/org/mozilla/gecko/db/BrowserProvider.java
@@ -24,16 +24,17 @@ import org.mozilla.gecko.db.BrowserContr
import org.mozilla.gecko.db.BrowserContract.History;
import org.mozilla.gecko.db.BrowserContract.Visits;
import org.mozilla.gecko.db.BrowserContract.Schema;
import org.mozilla.gecko.db.BrowserContract.Tabs;
import org.mozilla.gecko.db.BrowserContract.Thumbnails;
import org.mozilla.gecko.db.BrowserContract.TopSites;
import org.mozilla.gecko.db.BrowserContract.UrlAnnotations;
import org.mozilla.gecko.db.BrowserContract.PageMetadata;
+import org.mozilla.gecko.db.BrowserContract.FormAutofill;
import org.mozilla.gecko.db.DBUtils.UpdateOperation;
import org.mozilla.gecko.icons.IconsHelper;
import org.mozilla.gecko.sync.Utils;
import org.mozilla.gecko.sync.repositories.android.BrowserContractHelpers;
import org.mozilla.gecko.util.ThreadUtils;
import android.content.BroadcastReceiver;
import android.content.ContentProviderOperation;
@@ -89,16 +90,17 @@ public class BrowserProvider extends Sha
static final String TABLE_HISTORY = History.TABLE_NAME;
static final String TABLE_VISITS = Visits.TABLE_NAME;
static final String TABLE_FAVICONS = Favicons.TABLE_NAME;
static final String TABLE_THUMBNAILS = Thumbnails.TABLE_NAME;
static final String TABLE_TABS = Tabs.TABLE_NAME;
static final String TABLE_URL_ANNOTATIONS = UrlAnnotations.TABLE_NAME;
static final String TABLE_ACTIVITY_STREAM_BLOCKLIST = ActivityStreamBlocklist.TABLE_NAME;
static final String TABLE_PAGE_METADATA = PageMetadata.TABLE_NAME;
+ static final String TABLE_FORM_AUTOFILL = FormAutofill.TABLE_NAME;
static final String VIEW_COMBINED = Combined.VIEW_NAME;
static final String VIEW_BOOKMARKS_WITH_FAVICONS = Bookmarks.VIEW_WITH_FAVICONS;
static final String VIEW_BOOKMARKS_WITH_ANNOTATIONS = Bookmarks.VIEW_WITH_ANNOTATIONS;
static final String VIEW_HISTORY_WITH_FAVICONS = History.VIEW_WITH_FAVICONS;
static final String VIEW_COMBINED_WITH_FAVICONS = Combined.VIEW_WITH_FAVICONS;
// Bookmark matches
@@ -142,16 +144,18 @@ public class BrowserProvider extends Sha
static final int METADATA = 1200;
static final int HIGHLIGHT_CANDIDATES = 1300;
static final int ACTIVITY_STREAM_BLOCKLIST = 1400;
static final int PAGE_METADATA = 1500;
+ static final int FORM_AUTOFILL = 1600;
+
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 DEFAULT_VISITS_SORT_ORDER = Visits.DATE_VISITED + " DESC";
static final UriMatcher URI_MATCHER = new UriMatcher(UriMatcher.NO_MATCH);
@@ -160,16 +164,17 @@ public class BrowserProvider extends Sha
static final Map<String, String> HISTORY_PROJECTION_MAP;
static final Map<String, String> COMBINED_PROJECTION_MAP;
static final Map<String, String> SCHEMA_PROJECTION_MAP;
static final Map<String, String> FAVICONS_PROJECTION_MAP;
static final Map<String, String> THUMBNAILS_PROJECTION_MAP;
static final Map<String, String> URL_ANNOTATIONS_PROJECTION_MAP;
static final Map<String, String> VISIT_PROJECTION_MAP;
static final Map<String, String> PAGE_METADATA_PROJECTION_MAP;
+ static final Map<String, String> FORM_AUTOFILL_PROJECTION_MAP;
static final Table[] sTables;
static {
sTables = new Table[] {
// See awful shortcut assumption hack in getURLImageDataTable.
new URLImageDataTable()
};
// We will reuse this.
@@ -296,16 +301,26 @@ public class BrowserProvider extends Sha
map.put(PageMetadata.HISTORY_GUID, PageMetadata.HISTORY_GUID);
map.put(PageMetadata.DATE_CREATED, PageMetadata.DATE_CREATED);
map.put(PageMetadata.HAS_IMAGE, PageMetadata.HAS_IMAGE);
map.put(PageMetadata.JSON, PageMetadata.JSON);
PAGE_METADATA_PROJECTION_MAP = Collections.unmodifiableMap(map);
URI_MATCHER.addURI(BrowserContract.AUTHORITY, "page_metadata", PAGE_METADATA);
+ map = new HashMap<>();
+ map.put(FormAutofill._ID, FormAutofill._ID);
+ map.put(FormAutofill.GUID, FormAutofill.GUID);
+ map.put(FormAutofill.JSON, FormAutofill.JSON);
+ map.put(FormAutofill.DATE_CREATED, FormAutofill.DATE_CREATED);
+ map.put(FormAutofill.DATE_MODIFIED, FormAutofill.DATE_MODIFIED);
+ FORM_AUTOFILL_PROJECTION_MAP = Collections.unmodifiableMap(map);
+
+ URI_MATCHER.addURI(BrowserContract.AUTHORITY, "form_autofill", FORM_AUTOFILL);
+
// 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);
@@ -644,16 +659,21 @@ public class BrowserProvider extends Sha
deleteUrlAnnotation(uri, selection, selectionArgs);
break;
case PAGE_METADATA:
trace("Delete on PAGE_METADATA: " + uri);
deleted = deletePageMetadata(uri, selection, selectionArgs);
break;
+ case FORM_AUTOFILL:
+ trace("Delete on FORM_AUTOFILL: " + uri);
+ deleted = deleteFormAutofill(uri, selection, selectionArgs);
+ break;
+
default: {
Table table = findTableFor(match);
if (table == null) {
throw new UnsupportedOperationException("Unknown delete URI " + uri);
}
trace("Deleting TABLE: " + uri);
beginWrite(db);
deleted = table.delete(db, uri, match, selection, selectionArgs);
@@ -716,16 +736,22 @@ public class BrowserProvider extends Sha
}
case PAGE_METADATA: {
trace("Insert on PAGE_METADATA: " + uri);
id = insertPageMetadata(uri, values);
break;
}
+ case FORM_AUTOFILL: {
+ trace("Insert on FORM_AUTOFILL: " + uri);
+ id = insertFormAutofill(uri, values);
+ break;
+ }
+
default: {
Table table = findTableFor(match);
if (table == null) {
throw new UnsupportedOperationException("Unknown insert URI " + uri);
}
trace("Insert on TABLE: " + uri);
final SQLiteDatabase db = getWritableDatabase(uri);
@@ -851,16 +877,19 @@ public class BrowserProvider extends Sha
}
break;
}
case URL_ANNOTATIONS:
updateUrlAnnotation(uri, values, selection, selectionArgs);
break;
+ case FORM_AUTOFILL:
+ throw new UnsupportedOperationException("Updating FormAutofill records is not supported");
+
default: {
Table table = findTableFor(match);
if (table == null) {
throw new UnsupportedOperationException("Unknown update URI " + uri);
}
trace("Update TABLE: " + uri);
beginWrite(db);
@@ -1386,16 +1415,28 @@ public class BrowserProvider extends Sha
case PAGE_METADATA: {
debug("PageMetadata query: " + uri);
qb.setProjectionMap(PAGE_METADATA_PROJECTION_MAP);
qb.setTables(TABLE_PAGE_METADATA);
break;
}
+ case FORM_AUTOFILL: {
+ if (!isCallerSync(uri)) {
+ throw new UnsupportedOperationException("Querying FormAutofill data outside of Sync is not supported.");
+ }
+
+ debug("FormAutofill query: " + uri);
+
+ qb.setProjectionMap(FORM_AUTOFILL_PROJECTION_MAP);
+ qb.setTables(TABLE_FORM_AUTOFILL);
+ break;
+ }
+
default: {
Table table = findTableFor(match);
if (table == null) {
throw new UnsupportedOperationException("Unknown query URI " + uri);
}
trace("Update TABLE: " + uri);
return table.query(db, uri, match, projection, selection, selectionArgs, sortOrder, groupBy, limit);
}
@@ -1992,16 +2033,35 @@ public class BrowserProvider extends Sha
beginWrite(db);
// Perform INSERT OR REPLACE, there might be page metadata present and we want to replace it.
// Depends on a conflict arising from unique foreign key (history_guid) constraint violation.
return db.insertWithOnConflict(
TABLE_PAGE_METADATA, null, values, SQLiteDatabase.CONFLICT_REPLACE);
}
+ private long insertFormAutofill(final Uri uri, final ContentValues values) {
+ if (!isCallerSync(uri)) {
+ throw new UnsupportedOperationException("Querying FormAutofill data outside of Sync is not supported.");
+ }
+
+ final SQLiteDatabase db = getWritableDatabase(uri);
+
+ if (!values.containsKey(FormAutofill.DATE_CREATED)) {
+ values.put(FormAutofill.DATE_CREATED, System.currentTimeMillis());
+ }
+
+ beginWrite(db);
+
+ // Perform INSERT OR REPLACE. Local modification is not allowed, and so we're just replacing
+ // whatever we already have. Depends on a conflict arising from unique GUID constraint violation.
+ return db.insertWithOnConflict(
+ TABLE_PAGE_METADATA, null, values, SQLiteDatabase.CONFLICT_REPLACE);
+ }
+
private long insertUrlAnnotation(final Uri uri, final ContentValues values) {
final String url = values.getAsString(UrlAnnotations.URL);
trace("Inserting url annotations for URL: " + url);
final SQLiteDatabase db = getWritableDatabase(uri);
beginWrite(db);
return db.insertOrThrow(TABLE_URL_ANNOTATIONS, null, values);
}
@@ -2015,16 +2075,27 @@ public class BrowserProvider extends Sha
private int deletePageMetadata(final Uri uri, final String selection, final String[] selectionArgs) {
trace("Deleting page metadata for URI: " + uri);
final SQLiteDatabase db = getWritableDatabase(uri);
return db.delete(TABLE_PAGE_METADATA, selection, selectionArgs);
}
+ private int deleteFormAutofill(final Uri uri, final String selection, final String[] selectionArgs) {
+ if (!isCallerSync(uri)) {
+ throw new UnsupportedOperationException("Querying FormAutofill data outside of Sync is not supported.");
+ }
+
+ trace("Deleting form autofill for URI: " + uri);
+
+ final SQLiteDatabase db = getWritableDatabase(uri);
+ return db.delete(TABLE_FORM_AUTOFILL, selection, selectionArgs);
+ }
+
private void updateUrlAnnotation(final Uri uri, final ContentValues values, final String selection, final String[] selectionArgs) {
trace("Updating url annotation for URI: " + uri);
final SQLiteDatabase db = getWritableDatabase(uri);
db.update(TABLE_URL_ANNOTATIONS, values, selection, selectionArgs);
}
private int updateOrInsertThumbnail(Uri uri, ContentValues values, String selection,