Dactyloidae/toolkit/components/places/tests/migration/test_current_from_v34.js

141 lines
5 KiB
JavaScript

Cu.importGlobalProperties(["URL", "crypto"]);
const { TYPE_BOOKMARK, TYPE_FOLDER } = Ci.nsINavBookmarksService;
const { EXPIRE_NEVER, TYPE_INT32 } = Ci.nsIAnnotationService;
function makeGuid() {
return ChromeUtils.base64URLEncode(crypto.getRandomValues(new Uint8Array(9)), {
pad: false,
});
}
// These queries are more or less copied directly from Bookmarks.jsm, but
// operate on the old, pre-migration DB. We can't use any of the Places SQL
// functions yet, because those are only registered for the main connection.
function* insertItem(db, info) {
let [parentInfo] = yield db.execute(`
SELECT b.id, (SELECT count(*) FROM moz_bookmarks
WHERE parent = b.id) AS childCount
FROM moz_bookmarks b
WHERE b.guid = :parentGuid`,
{ parentGuid: info.parentGuid });
let guid = makeGuid();
yield db.execute(`
INSERT INTO moz_bookmarks (fk, type, parent, position, guid)
VALUES ((SELECT id FROM moz_places WHERE url = :url),
:type, :parent, :position, :guid)`,
{ url: info.url || "nonexistent", type: info.type, guid,
// Just append items.
position: parentInfo.getResultByName("childCount"),
parent: parentInfo.getResultByName("id") });
let id = (yield db.execute(`
SELECT id FROM moz_bookmarks WHERE guid = :guid LIMIT 1`,
{ guid }))[0].getResultByName("id");
return { id, guid };
}
function insertBookmark(db, info) {
return db.executeTransaction(function* () {
if (info.type == TYPE_BOOKMARK) {
// We don't have access to the hash function here, so we omit the
// `url_hash` column. These will be fixed up automatically during
// migration.
let url = new URL(info.url);
let placeGuid = makeGuid();
yield db.execute(`
INSERT INTO moz_places (url, rev_host, hidden, frecency, guid)
VALUES (:url, :rev_host, 0, -1, :guid)`,
{ url: url.href, guid: placeGuid,
rev_host: PlacesUtils.getReversedHost(url) });
}
return yield* insertItem(db, info);
});
}
function* insertAnno(db, itemId, name, value) {
yield db.execute(`INSERT OR IGNORE INTO moz_anno_attributes (name)
VALUES (:name)`, { name });
yield db.execute(`
INSERT INTO moz_items_annos
(item_id, anno_attribute_id, content, flags,
expiration, type, dateAdded, lastModified)
VALUES (:itemId,
(SELECT id FROM moz_anno_attributes
WHERE name = :name),
1, 0, :expiration, :type, 0, 0)
`, { itemId, name, expiration: EXPIRE_NEVER, type: TYPE_INT32 });
}
function insertMobileFolder(db) {
return db.executeTransaction(function* () {
let item = yield* insertItem(db, {
type: TYPE_FOLDER,
parentGuid: "root________",
});
yield* insertAnno(db, item.id, "mobile/bookmarksRoot", 1);
return item;
});
}
var mobileId, mobileGuid, fxGuid;
var dupeMobileId, dupeMobileGuid, tbGuid;
add_task(function* setup() {
yield setupPlacesDatabase("places_v34.sqlite");
// Setup database contents to be migrated.
let path = OS.Path.join(OS.Constants.Path.profileDir, DB_FILENAME);
let db = yield Sqlite.openConnection({ path });
do_print("Create mobile folder with bookmarks");
({ id: mobileId, guid: mobileGuid } = yield insertMobileFolder(db));
({ guid: fxGuid } = yield insertBookmark(db, {
type: TYPE_BOOKMARK,
url: "http://getfirefox.com",
parentGuid: mobileGuid,
}));
// We should only have one mobile folder, but, in case an old version of Sync
// did the wrong thing and created multiple mobile folders, we should merge
// their contents into the new mobile root.
do_print("Create second mobile folder with different bookmarks");
({ id: dupeMobileId, guid: dupeMobileGuid } = yield insertMobileFolder(db));
({ guid: tbGuid } = yield insertBookmark(db, {
type: TYPE_BOOKMARK,
url: "http://getthunderbird.com",
parentGuid: dupeMobileGuid,
}));
yield db.close();
});
add_task(function* database_is_valid() {
// Accessing the database for the first time triggers migration.
Assert.equal(PlacesUtils.history.databaseStatus,
PlacesUtils.history.DATABASE_STATUS_UPGRADED);
let db = yield PlacesUtils.promiseDBConnection();
Assert.equal((yield db.getSchemaVersion()), CURRENT_SCHEMA_VERSION);
});
add_task(function* test_mobile_root() {
let fxBmk = yield PlacesUtils.bookmarks.fetch(fxGuid);
equal(fxBmk.parentGuid, PlacesUtils.bookmarks.mobileGuid,
"Firefox bookmark should be moved to new mobile root");
equal(fxBmk.index, 0, "Firefox bookmark should be first child of new root");
let tbBmk = yield PlacesUtils.bookmarks.fetch(tbGuid);
equal(tbBmk.parentGuid, PlacesUtils.bookmarks.mobileGuid,
"Thunderbird bookmark should be moved to new mobile root");
equal(tbBmk.index, 1,
"Thunderbird bookmark should be second child of new root");
let mobileRootId = PlacesUtils.promiseItemId(
PlacesUtils.bookmarks.mobileGuid);
let annoItemIds = PlacesUtils.annotations.getItemsWithAnnotation(
PlacesUtils.MOBILE_ROOT_ANNO, {});
deepEqual(annoItemIds, [mobileRootId],
"Only mobile root should have mobile anno");
});