Thu, 22 Jan 2015 13:21:57 +0100
Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6
michael@0 | 1 | /* Any copyright is dedicated to the Public Domain. |
michael@0 | 2 | http://creativecommons.org/publicdomain/zero/1.0/ */ |
michael@0 | 3 | |
michael@0 | 4 | Cu.import("resource://gre/modules/PlacesUtils.jsm"); |
michael@0 | 5 | Cu.import("resource://gre/modules/Log.jsm"); |
michael@0 | 6 | Cu.import("resource://services-sync/engines.js"); |
michael@0 | 7 | Cu.import("resource://services-sync/engines/bookmarks.js"); |
michael@0 | 8 | Cu.import("resource://services-sync/service.js"); |
michael@0 | 9 | Cu.import("resource://services-sync/util.js"); |
michael@0 | 10 | Cu.import("resource://testing-common/services/sync/utils.js"); |
michael@0 | 11 | |
michael@0 | 12 | const SMART_BOOKMARKS_ANNO = "Places/SmartBookmark"; |
michael@0 | 13 | var IOService = Cc["@mozilla.org/network/io-service;1"] |
michael@0 | 14 | .getService(Ci.nsIIOService); |
michael@0 | 15 | ("http://www.mozilla.com", null, null); |
michael@0 | 16 | |
michael@0 | 17 | |
michael@0 | 18 | Service.engineManager.register(BookmarksEngine); |
michael@0 | 19 | let engine = Service.engineManager.get("bookmarks"); |
michael@0 | 20 | let store = engine._store; |
michael@0 | 21 | |
michael@0 | 22 | // Clean up after other tests. Only necessary in XULRunner. |
michael@0 | 23 | store.wipe(); |
michael@0 | 24 | |
michael@0 | 25 | function newSmartBookmark(parent, uri, position, title, queryID) { |
michael@0 | 26 | let id = PlacesUtils.bookmarks.insertBookmark(parent, uri, position, title); |
michael@0 | 27 | PlacesUtils.annotations.setItemAnnotation(id, SMART_BOOKMARKS_ANNO, |
michael@0 | 28 | queryID, 0, |
michael@0 | 29 | PlacesUtils.annotations.EXPIRE_NEVER); |
michael@0 | 30 | return id; |
michael@0 | 31 | } |
michael@0 | 32 | |
michael@0 | 33 | function smartBookmarkCount() { |
michael@0 | 34 | // We do it this way because PlacesUtils.annotations.getItemsWithAnnotation |
michael@0 | 35 | // doesn't work the same (or at all?) between 3.6 and 4.0. |
michael@0 | 36 | let out = {}; |
michael@0 | 37 | PlacesUtils.annotations.getItemsWithAnnotation(SMART_BOOKMARKS_ANNO, out); |
michael@0 | 38 | return out.value; |
michael@0 | 39 | } |
michael@0 | 40 | |
michael@0 | 41 | function clearBookmarks() { |
michael@0 | 42 | _("Cleaning up existing items."); |
michael@0 | 43 | PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.bookmarks.bookmarksMenuFolder); |
michael@0 | 44 | PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.bookmarks.tagsFolder); |
michael@0 | 45 | PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.bookmarks.toolbarFolder); |
michael@0 | 46 | PlacesUtils.bookmarks.removeFolderChildren(PlacesUtils.bookmarks.unfiledBookmarksFolder); |
michael@0 | 47 | startCount = smartBookmarkCount(); |
michael@0 | 48 | } |
michael@0 | 49 | |
michael@0 | 50 | function serverForFoo(engine) { |
michael@0 | 51 | return serverForUsers({"foo": "password"}, { |
michael@0 | 52 | meta: {global: {engines: {bookmarks: {version: engine.version, |
michael@0 | 53 | syncID: engine.syncID}}}}, |
michael@0 | 54 | bookmarks: {} |
michael@0 | 55 | }); |
michael@0 | 56 | } |
michael@0 | 57 | |
michael@0 | 58 | // Verify that Places smart bookmarks have their annotation uploaded and |
michael@0 | 59 | // handled locally. |
michael@0 | 60 | add_test(function test_annotation_uploaded() { |
michael@0 | 61 | let server = serverForFoo(engine); |
michael@0 | 62 | new SyncTestingInfrastructure(server.server); |
michael@0 | 63 | |
michael@0 | 64 | let startCount = smartBookmarkCount(); |
michael@0 | 65 | |
michael@0 | 66 | _("Start count is " + startCount); |
michael@0 | 67 | |
michael@0 | 68 | if (startCount > 0) { |
michael@0 | 69 | // This can happen in XULRunner. |
michael@0 | 70 | clearBookmarks(); |
michael@0 | 71 | _("Start count is now " + startCount); |
michael@0 | 72 | } |
michael@0 | 73 | |
michael@0 | 74 | _("Create a smart bookmark in the toolbar."); |
michael@0 | 75 | let parent = PlacesUtils.toolbarFolderId; |
michael@0 | 76 | let uri = |
michael@0 | 77 | Utils.makeURI("place:sort=" + |
michael@0 | 78 | Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING + |
michael@0 | 79 | "&maxResults=10"); |
michael@0 | 80 | let title = "Most Visited"; |
michael@0 | 81 | |
michael@0 | 82 | let mostVisitedID = newSmartBookmark(parent, uri, -1, title, "MostVisited"); |
michael@0 | 83 | |
michael@0 | 84 | _("New item ID: " + mostVisitedID); |
michael@0 | 85 | do_check_true(!!mostVisitedID); |
michael@0 | 86 | |
michael@0 | 87 | let annoValue = PlacesUtils.annotations.getItemAnnotation(mostVisitedID, |
michael@0 | 88 | SMART_BOOKMARKS_ANNO); |
michael@0 | 89 | _("Anno: " + annoValue); |
michael@0 | 90 | do_check_eq("MostVisited", annoValue); |
michael@0 | 91 | |
michael@0 | 92 | let guid = store.GUIDForId(mostVisitedID); |
michael@0 | 93 | _("GUID: " + guid); |
michael@0 | 94 | do_check_true(!!guid); |
michael@0 | 95 | |
michael@0 | 96 | _("Create record object and verify that it's sane."); |
michael@0 | 97 | let record = store.createRecord(guid); |
michael@0 | 98 | do_check_true(record instanceof Bookmark); |
michael@0 | 99 | do_check_true(record instanceof BookmarkQuery); |
michael@0 | 100 | |
michael@0 | 101 | do_check_eq(record.bmkUri, uri.spec); |
michael@0 | 102 | |
michael@0 | 103 | _("Make sure the new record carries with it the annotation."); |
michael@0 | 104 | do_check_eq("MostVisited", record.queryId); |
michael@0 | 105 | |
michael@0 | 106 | _("Our count has increased since we started."); |
michael@0 | 107 | do_check_eq(smartBookmarkCount(), startCount + 1); |
michael@0 | 108 | |
michael@0 | 109 | _("Sync record to the server."); |
michael@0 | 110 | let collection = server.user("foo").collection("bookmarks"); |
michael@0 | 111 | |
michael@0 | 112 | try { |
michael@0 | 113 | engine.sync(); |
michael@0 | 114 | let wbos = collection.keys(function (id) { |
michael@0 | 115 | return ["menu", "toolbar", "mobile"].indexOf(id) == -1; |
michael@0 | 116 | }); |
michael@0 | 117 | do_check_eq(wbos.length, 1); |
michael@0 | 118 | |
michael@0 | 119 | _("Verify that the server WBO has the annotation."); |
michael@0 | 120 | let serverGUID = wbos[0]; |
michael@0 | 121 | do_check_eq(serverGUID, guid); |
michael@0 | 122 | let serverWBO = collection.wbo(serverGUID); |
michael@0 | 123 | do_check_true(!!serverWBO); |
michael@0 | 124 | let body = JSON.parse(JSON.parse(serverWBO.payload).ciphertext); |
michael@0 | 125 | do_check_eq(body.queryId, "MostVisited"); |
michael@0 | 126 | |
michael@0 | 127 | _("We still have the right count."); |
michael@0 | 128 | do_check_eq(smartBookmarkCount(), startCount + 1); |
michael@0 | 129 | |
michael@0 | 130 | _("Clear local records; now we can't find it."); |
michael@0 | 131 | |
michael@0 | 132 | // "Clear" by changing attributes: if we delete it, apparently it sticks |
michael@0 | 133 | // around as a deleted record... |
michael@0 | 134 | PlacesUtils.bookmarks.setItemTitle(mostVisitedID, "Not Most Visited"); |
michael@0 | 135 | PlacesUtils.bookmarks.changeBookmarkURI( |
michael@0 | 136 | mostVisitedID, Utils.makeURI("http://something/else")); |
michael@0 | 137 | PlacesUtils.annotations.removeItemAnnotation(mostVisitedID, |
michael@0 | 138 | SMART_BOOKMARKS_ANNO); |
michael@0 | 139 | store.wipe(); |
michael@0 | 140 | engine.resetClient(); |
michael@0 | 141 | do_check_eq(smartBookmarkCount(), startCount); |
michael@0 | 142 | |
michael@0 | 143 | _("Sync. Verify that the downloaded record carries the annotation."); |
michael@0 | 144 | engine.sync(); |
michael@0 | 145 | |
michael@0 | 146 | _("Verify that the Places DB now has an annotated bookmark."); |
michael@0 | 147 | _("Our count has increased again."); |
michael@0 | 148 | do_check_eq(smartBookmarkCount(), startCount + 1); |
michael@0 | 149 | |
michael@0 | 150 | _("Find by GUID and verify that it's annotated."); |
michael@0 | 151 | let newID = store.idForGUID(serverGUID); |
michael@0 | 152 | let newAnnoValue = PlacesUtils.annotations.getItemAnnotation( |
michael@0 | 153 | newID, SMART_BOOKMARKS_ANNO); |
michael@0 | 154 | do_check_eq(newAnnoValue, "MostVisited"); |
michael@0 | 155 | do_check_eq(PlacesUtils.bookmarks.getBookmarkURI(newID).spec, uri.spec); |
michael@0 | 156 | |
michael@0 | 157 | _("Test updating."); |
michael@0 | 158 | let newRecord = store.createRecord(serverGUID); |
michael@0 | 159 | do_check_eq(newRecord.queryId, newAnnoValue); |
michael@0 | 160 | newRecord.queryId = "LeastVisited"; |
michael@0 | 161 | store.update(newRecord); |
michael@0 | 162 | do_check_eq("LeastVisited", PlacesUtils.annotations.getItemAnnotation( |
michael@0 | 163 | newID, SMART_BOOKMARKS_ANNO)); |
michael@0 | 164 | |
michael@0 | 165 | |
michael@0 | 166 | } finally { |
michael@0 | 167 | // Clean up. |
michael@0 | 168 | store.wipe(); |
michael@0 | 169 | Svc.Prefs.resetBranch(""); |
michael@0 | 170 | Service.recordManager.clearCache(); |
michael@0 | 171 | server.stop(run_next_test); |
michael@0 | 172 | } |
michael@0 | 173 | }); |
michael@0 | 174 | |
michael@0 | 175 | add_test(function test_smart_bookmarks_duped() { |
michael@0 | 176 | let server = serverForFoo(engine); |
michael@0 | 177 | new SyncTestingInfrastructure(server.server); |
michael@0 | 178 | |
michael@0 | 179 | let parent = PlacesUtils.toolbarFolderId; |
michael@0 | 180 | let uri = |
michael@0 | 181 | Utils.makeURI("place:sort=" + |
michael@0 | 182 | Ci.nsINavHistoryQueryOptions.SORT_BY_VISITCOUNT_DESCENDING + |
michael@0 | 183 | "&maxResults=10"); |
michael@0 | 184 | let title = "Most Visited"; |
michael@0 | 185 | let mostVisitedID = newSmartBookmark(parent, uri, -1, title, "MostVisited"); |
michael@0 | 186 | let mostVisitedGUID = store.GUIDForId(mostVisitedID); |
michael@0 | 187 | |
michael@0 | 188 | let record = store.createRecord(mostVisitedGUID); |
michael@0 | 189 | |
michael@0 | 190 | _("Prepare sync."); |
michael@0 | 191 | let collection = server.user("foo").collection("bookmarks"); |
michael@0 | 192 | |
michael@0 | 193 | try { |
michael@0 | 194 | engine._syncStartup(); |
michael@0 | 195 | |
michael@0 | 196 | _("Verify that mapDupe uses the anno, discovering a dupe regardless of URI."); |
michael@0 | 197 | do_check_eq(mostVisitedGUID, engine._mapDupe(record)); |
michael@0 | 198 | |
michael@0 | 199 | record.bmkUri = "http://foo/"; |
michael@0 | 200 | do_check_eq(mostVisitedGUID, engine._mapDupe(record)); |
michael@0 | 201 | do_check_neq(PlacesUtils.bookmarks.getBookmarkURI(mostVisitedID).spec, |
michael@0 | 202 | record.bmkUri); |
michael@0 | 203 | |
michael@0 | 204 | _("Verify that different annos don't dupe."); |
michael@0 | 205 | let other = new BookmarkQuery("bookmarks", "abcdefabcdef"); |
michael@0 | 206 | other.queryId = "LeastVisited"; |
michael@0 | 207 | other.parentName = "Bookmarks Toolbar"; |
michael@0 | 208 | other.bmkUri = "place:foo"; |
michael@0 | 209 | other.title = ""; |
michael@0 | 210 | do_check_eq(undefined, engine._findDupe(other)); |
michael@0 | 211 | |
michael@0 | 212 | _("Handle records without a queryId entry."); |
michael@0 | 213 | record.bmkUri = uri; |
michael@0 | 214 | delete record.queryId; |
michael@0 | 215 | do_check_eq(mostVisitedGUID, engine._mapDupe(record)); |
michael@0 | 216 | |
michael@0 | 217 | engine._syncFinish(); |
michael@0 | 218 | |
michael@0 | 219 | } finally { |
michael@0 | 220 | // Clean up. |
michael@0 | 221 | store.wipe(); |
michael@0 | 222 | server.stop(do_test_finished); |
michael@0 | 223 | Svc.Prefs.resetBranch(""); |
michael@0 | 224 | Service.recordManager.clearCache(); |
michael@0 | 225 | } |
michael@0 | 226 | }); |
michael@0 | 227 | |
michael@0 | 228 | function run_test() { |
michael@0 | 229 | initTestLogging("Trace"); |
michael@0 | 230 | Log.repository.getLogger("Sync.Engine.Bookmarks").level = Log.Level.Trace; |
michael@0 | 231 | |
michael@0 | 232 | generateNewKeys(Service.collectionKeys); |
michael@0 | 233 | |
michael@0 | 234 | run_next_test(); |
michael@0 | 235 | } |