Bug 1408687 - Add a maintenance task to reset missing or invalid Place GUIDs. r?mak
MozReview-Commit-ID: JPqXnDsg07q
--- a/toolkit/components/places/PlacesDBUtils.jsm
+++ b/toolkit/components/places/PlacesDBUtils.jsm
@@ -780,16 +780,26 @@ this.PlacesDBUtils = {
cleanupStatements.push(fixForeignCount);
// L.5 recalculate missing hashes.
let fixMissingHashes = {
query: `UPDATE moz_places SET url_hash = hash(url) WHERE url_hash = 0`
};
cleanupStatements.push(fixMissingHashes);
+ // L.6 fix invalid Place GUIDs.
+ let fixInvalidPlaceGuids = {
+ query:
+ `UPDATE moz_places
+ SET guid = GENERATE_GUID()
+ WHERE guid IS NULL OR
+ NOT IS_VALID_GUID(guid)`
+ };
+ cleanupStatements.push(fixInvalidPlaceGuids);
+
// MOZ_BOOKMARKS
// S.1 fix invalid GUIDs for synced bookmarks.
// This requires multiple related statements.
// First, we insert tombstones for all synced bookmarks with invalid
// GUIDs, so that we can delete them on the server. Second, we add a
// temporary trigger to bump the change counter for the parents of any
// items we update, since Sync stores the list of child GUIDs on the
// parent. Finally, we assign new GUIDs for all items with missing and
--- a/toolkit/components/places/tests/unit/test_preventive_maintenance.js
+++ b/toolkit/components/places/tests/unit/test_preventive_maintenance.js
@@ -34,21 +34,22 @@ function cleanDatabase() {
mDBConn.executeSimpleSQL("DELETE FROM moz_items_annos");
mDBConn.executeSimpleSQL("DELETE FROM moz_inputhistory");
mDBConn.executeSimpleSQL("DELETE FROM moz_keywords");
mDBConn.executeSimpleSQL("DELETE FROM moz_icons");
mDBConn.executeSimpleSQL("DELETE FROM moz_pages_w_icons");
mDBConn.executeSimpleSQL("DELETE FROM moz_bookmarks WHERE id > " + defaultBookmarksMaxId);
}
-function addPlace(aUrl, aFavicon) {
+function addPlace(aUrl, aFavicon, aGuid = PlacesUtils.history.makeGuid()) {
let href = new URL(aUrl || "http://www.mozilla.org").href;
let stmt = mDBConn.createStatement(
- "INSERT INTO moz_places (url, url_hash) VALUES (:url, hash(:url))");
+ "INSERT INTO moz_places (url, url_hash, guid) VALUES (:url, hash(:url), :guid)");
stmt.params.url = href;
+ stmt.params.guid = aGuid;
stmt.execute();
stmt.finalize();
let id = mDBConn.lastInsertRowID;
if (aFavicon) {
stmt = mDBConn.createStatement(
"INSERT INTO moz_pages_w_icons (page_url, page_url_hash) VALUES (:url, hash(:url))");
stmt.params.url = href;
stmt.execute();
@@ -1236,16 +1237,59 @@ tests.push({
async check() {
Assert.ok((await this._getHash()) > 0);
}
});
// ------------------------------------------------------------------------------
tests.push({
+ name: "L.6",
+ desc: "fix invalid Place GUIDs",
+ _placeIds: [],
+
+ async setup() {
+ let placeWithValidGuid = addPlace("http://example.com/a", null,
+ "placeAAAAAAA");
+ this._placeIds.push(placeWithValidGuid);
+
+ let placeWithEmptyGuid = addPlace("http://example.com/b", null, "");
+ this._placeIds.push(placeWithEmptyGuid);
+
+ let placeWithoutGuid = addPlace("http://example.com/c", null, null);
+ this._placeIds.push(placeWithoutGuid);
+
+ let placeWithInvalidGuid = addPlace("http://example.com/c", null,
+ "{123456}");
+ this._placeIds.push(placeWithInvalidGuid);
+ },
+
+ async check() {
+ let db = await PlacesUtils.promiseDBConnection();
+ let updatedRows = await db.execute(`
+ SELECT id, guid
+ FROM moz_places
+ WHERE id IN (?, ?, ?, ?)`,
+ this._placeIds);
+
+ for (let row of updatedRows) {
+ let id = row.getResultByName("id");
+ let guid = row.getResultByName("guid");
+ if (id == this._placeIds[0]) {
+ do_check_eq(guid, "placeAAAAAAA");
+ } else {
+ do_check_true(PlacesUtils.isValidGuid(guid));
+ }
+ }
+ },
+});
+
+// ------------------------------------------------------------------------------
+
+tests.push({
name: "S.1",
desc: "fix invalid GUIDs for synced bookmarks",
_bookmarkInfos: [],
async setup() {
await PlacesTestUtils.markBookmarksAsSynced();
let folderWithInvalidGuid = addBookmark(