/* Any copyright is dedicated to the Public Domain. * http://creativecommons.org/publicdomain/zero/1.0/ */ add_task(async function test_queries() { let buf = await openMirror("queries"); info("Set up places"); // create a tag and grab the local folder ID. let tag = await PlacesUtils.bookmarks.insert({ type: PlacesUtils.bookmarks.TYPE_FOLDER, parentGuid: PlacesUtils.bookmarks.tagsGuid, title: "a-tag", }); await PlacesTestUtils.markBookmarksAsSynced(); await PlacesUtils.bookmarks.insertTree({ guid: PlacesUtils.bookmarks.menuGuid, children: [ { // this entry has a tag= query param for a tag that exists. guid: "queryAAAAAAA", type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "TAG_QUERY query", url: `place:tag=a-tag&&sort=14&maxResults=10`, }, { // this entry has a tag= query param for a tag that doesn't exist. guid: "queryBBBBBBB", type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "TAG_QUERY query but invalid folder id", url: `place:tag=b-tag&sort=14&maxResults=10`, }, { // this entry has no tag= query param. guid: "queryCCCCCCC", type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "TAG_QUERY without a folder at all", url: "place:sort=14&maxResults=10", }, { // this entry has only a tag= query. guid: "queryDDDDDDD", type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "TAG_QUERY without a folder at all", url: "place:tag=a-tag", }, ], }); info("Make remote changes"); await storeRecords( buf, shuffle([ { id: "toolbar", parentid: "places", type: "folder", children: [ "queryEEEEEEE", "queryFFFFFFF", "queryGGGGGGG", "queryHHHHHHH", "queryIIIIIII", ], }, { // Legacy tag query. id: "queryEEEEEEE", parentid: "toolbar", type: "query", title: "E", bmkUri: "place:type=7&folder=999", folderName: "taggy", }, { // New tag query. id: "queryFFFFFFF", parentid: "toolbar", type: "query", title: "F", bmkUri: "place:tag=a-tag", folderName: "a-tag", }, { // Legacy tag query referencing the same tag as the new query. id: "queryGGGGGGG", parentid: "toolbar", type: "query", title: "G", bmkUri: "place:type=7&folder=111&something=else", folderName: "a-tag", }, { // Legacy folder lookup query. id: "queryHHHHHHH", parentid: "toolbar", type: "query", title: "H", bmkUri: "place:folder=1", }, { // Legacy tag query with invalid tag folder name. id: "queryIIIIIII", parentid: "toolbar", type: "query", title: "I", bmkUri: "place:type=7&folder=222", folderName: " ", }, ]) ); info("Create records to upload"); let changes = await buf.apply(); deepEqual( Object.keys(changes), [ "menu", "toolbar", "queryAAAAAAA", "queryBBBBBBB", "queryCCCCCCC", "queryDDDDDDD", "queryEEEEEEE", "queryGGGGGGG", "queryHHHHHHH", "queryIIIIIII", ], "Should upload roots, new queries, and rewritten queries" ); Assert.strictEqual(changes.queryAAAAAAA.cleartext.folderName, tag.title); Assert.strictEqual(changes.queryBBBBBBB.cleartext.folderName, "b-tag"); Assert.strictEqual(changes.queryCCCCCCC.cleartext.folderName, undefined); Assert.strictEqual(changes.queryDDDDDDD.cleartext.folderName, tag.title); Assert.strictEqual(changes.queryIIIIIII.tombstone, true); await assertLocalTree( PlacesUtils.bookmarks.toolbarGuid, { guid: PlacesUtils.bookmarks.toolbarGuid, type: PlacesUtils.bookmarks.TYPE_FOLDER, index: 1, title: BookmarksToolbarTitle, children: [ { guid: "queryEEEEEEE", type: PlacesUtils.bookmarks.TYPE_BOOKMARK, index: 0, title: "E", url: "place:tag=taggy", }, { guid: "queryFFFFFFF", type: PlacesUtils.bookmarks.TYPE_BOOKMARK, index: 1, title: "F", url: "place:tag=a-tag", }, { guid: "queryGGGGGGG", type: PlacesUtils.bookmarks.TYPE_BOOKMARK, index: 2, title: "G", url: "place:tag=a-tag", }, { guid: "queryHHHHHHH", type: PlacesUtils.bookmarks.TYPE_BOOKMARK, index: 3, title: "H", url: "place:folder=1&excludeItems=1", }, ], }, "Should rewrite legacy remote queries" ); await buf.finalize(); await PlacesUtils.bookmarks.eraseEverything(); await PlacesSyncUtils.bookmarks.reset(); }); add_task(async function test_different_but_compatible_bookmark_types() { let buf = await openMirror("partial_queries"); try { await PlacesUtils.bookmarks.insertTree({ guid: PlacesUtils.bookmarks.menuGuid, children: [ { guid: "bookmarkAAAA", type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "not yet a query", url: "about:blank", }, { guid: "bookmarkBBBB", type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "a query", url: "place:foo", }, ], }); let changes = await buf.apply(); // We should have an outgoing record for bookmarkA with type=bookmark // and bookmarkB with type=query. Assert.equal(changes.bookmarkAAAA.cleartext.type, "bookmark"); Assert.equal(changes.bookmarkBBBB.cleartext.type, "query"); // Now pretend that same records are already on the server. await storeRecords( buf, [ { id: "menu", parentid: "places", type: "folder", children: ["bookmarkAAAA", "bookmarkBBBB"], }, { id: "bookmarkAAAA", parentid: "menu", type: "bookmark", title: "not yet a query", bmkUri: "about:blank", }, { id: "bookmarkBBBB", parentid: "menu", type: "query", title: "a query", bmkUri: "place:foo", }, ], { needsMerge: false } ); await PlacesTestUtils.markBookmarksAsSynced(); // change the url of bookmarkA to be a "real" query and of bookmarkB to // no longer be a query. await PlacesUtils.bookmarks.update({ guid: "bookmarkAAAA", url: "place:type=6&sort=14&maxResults=10", }); await PlacesUtils.bookmarks.update({ guid: "bookmarkBBBB", url: "about:robots", }); changes = await buf.apply(); // We should have an outgoing record for bookmarkA with type=query and // for bookmarkB with type=bookmark Assert.equal(changes.bookmarkAAAA.cleartext.type, "query"); Assert.equal(changes.bookmarkBBBB.cleartext.type, "bookmark"); } finally { await buf.finalize(); await PlacesUtils.bookmarks.eraseEverything(); await PlacesSyncUtils.bookmarks.reset(); } }); add_task(async function test_incompatible_types() { try { let buf = await openMirror("incompatible_types"); await PlacesUtils.bookmarks.insertTree({ guid: PlacesUtils.bookmarks.menuGuid, children: [ { guid: "AAAAAAAAAAAA", type: PlacesUtils.bookmarks.TYPE_BOOKMARK, title: "a bookmark", url: "about:blank", }, ], }); await buf.apply(); // Now pretend that same records are already on the server with incompatible // types. await storeRecords( buf, [ { id: "menu", parentid: "places", type: "folder", children: ["AAAAAAAAAAAA"], }, { id: "AAAAAAAAAAAA", parentid: "menu", type: "folder", title: "conflicting folder", }, ], { needsMerge: true } ); await PlacesTestUtils.markBookmarksAsSynced(); await Assert.rejects( buf.apply(), /Can't merge local Bookmark and remote Folder / ); } finally { await PlacesUtils.bookmarks.eraseEverything(); await PlacesSyncUtils.bookmarks.reset(); } });