Closed
Bug 1444262
Opened 6 years ago
Closed 6 years ago
A bookmark that later becomes a query breaks the mirror
Categories
(Firefox :: Sync, defect, P2)
Firefox
Sync
Tracking
()
RESOLVED
FIXED
Firefox 61
People
(Reporter: markh, Assigned: markh)
References
(Blocks 1 open bug)
Details
Attachments
(1 file, 1 obsolete file)
STR: * Create a new bookmark in the UI. * Wait for Sync to complete. * Change the URL to a valid query URL (ie, a URL starting with place:) * Sync again. Expected: * everything works. Actual: * Exception syncing: > 1520468286316 Sync.ErrorHandler DEBUG bookmarks failed: Error: Can't merge different item kinds (resource://gre/modules/SyncedBookmarksMirror.jsm:3366:11) JS Stack trace: ConsistencyError@SyncedBookmarksMirror.jsm:829:19 twoWayMerge@SyncedBookmarksMirror.jsm:3366:11 ... The issue is that a bookmark is initially created with about:blank as the URI, so ends up with type="bookmark" in the mirror. When the place: URL is used, it ends up as type="query", so the merger gets upset. The same issue happens for livemarks, but that appears to already be handled and have a test. Kit, what do you think of this patch? (Note it also changes some log.trace calls with log.warn which make sense to me, but may not to you :)
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Comment hidden (mozreview-request) |
Assignee | ||
Updated•6 years ago
|
Attachment #8957394 -
Attachment is obsolete: true
Attachment #8957394 -
Flags: review?(kit)
Comment 4•6 years ago
|
||
mozreview-review |
Comment on attachment 8957393 [details] Bug 1444262 - ensure that a bookmark that later becomes a query doesn't break the mirror. https://reviewboard.mozilla.org/r/226326/#review232250 This looks good to me, and thanks for the test! I think we can factor this logic out into a separate method and clean up `twoWayMerge`, but, if you think that would make things worse, please re-flag me, and we can land your patch as-is. ::: toolkit/components/places/SyncedBookmarksMirror.jsm:3407 (Diff revision 2) > MirrorLog.error("Merging local folder ${localNode} and remote " + > "non-folder ${remoteNode}", { localNode, remoteNode }); > throw new SyncedBookmarksMirror.ConsistencyError( > "Can't merge folder and non-folder"); > } > + // We are merging 2 non-folders. We allow bookmarks and queries to be I wonder if we can simplify this function a bit, and handle livemarks the same way. How do you feel about removing the livemark check in the block above, adding a `hasCompatibleKind(otherNode)` method to `BookmarkNode` with logic for queries and livemarks, and checking that here? If we're not merging two folders, and the kinds aren't compatible, we throw.
Attachment #8957393 -
Flags: review?(kit)
Updated•6 years ago
|
Priority: -- → P2
Comment hidden (mozreview-request) |
Comment 6•6 years ago
|
||
mozreview-review |
Comment on attachment 8957393 [details] Bug 1444262 - ensure that a bookmark that later becomes a query doesn't break the mirror. https://reviewboard.mozilla.org/r/226326/#review233768 Code analysis found 5 defects in this patch: - 5 defects found by mozlint You can run this analysis locally with: - `./mach lint path/to/file` (JS/Python) If you see a problem in this automated review, please report it here: http://bit.ly/2y9N9Vx ::: toolkit/components/places/SyncedBookmarksMirror.jsm:3420 (Diff revision 3) > + if (!localNode.hasCompatibleKind(remoteNode)) { > + MirrorLog.error("Merging local ${localNode} and remote ${remoteNode} " + > + "with different kinds", { localNode, remoteNode }); > + this.telemetryEvents.push({ > + value: "kind-mismatch", > + extra: { local: ""+localNode.kind, remote: ""+remoteNode.kind }, Error: Infix operators must be spaced. [eslint: space-infix-ops] ::: toolkit/components/places/SyncedBookmarksMirror.jsm:3420 (Diff revision 3) > + if (!localNode.hasCompatibleKind(remoteNode)) { > + MirrorLog.error("Merging local ${localNode} and remote ${remoteNode} " + > + "with different kinds", { localNode, remoteNode }); > + this.telemetryEvents.push({ > + value: "kind-mismatch", > + extra: { local: ""+localNode.kind, remote: ""+remoteNode.kind }, Error: Infix operators must be spaced. [eslint: space-infix-ops] ::: toolkit/components/places/tests/sync/test_bookmark_kinds.js:372 (Diff revision 3) > + extra.local == SyncedBookmarksMirror.KIND.LIVEMARK && > + extra.remote && typeof extra.remote == "string" && > + extra.remote == SyncedBookmarksMirror.KIND.FOLDER) { > + sawMismatchEvent = true; > + } > + } Error: Missing semicolon. [eslint: semi] ::: toolkit/components/places/tests/sync/test_bookmark_kinds.js:494 (Diff revision 3) > + extra.local == SyncedBookmarksMirror.KIND.BOOKMARK && > + extra.remote && typeof extra.remote == "string" && > + extra.remote == SyncedBookmarksMirror.KIND.FOLDER) { > + sawMismatchEvent = true; > + } > + } Error: Missing semicolon. [eslint: semi] ::: toolkit/components/places/tests/sync/test_bookmark_kinds.js:510 (Diff revision 3) > + url: "about:blank", > + }, > + ], > + }); > + > + let changes = await buf.apply(); Error: 'changes' is assigned a value but never used. [eslint: no-unused-vars]
Comment hidden (mozreview-request) |
Comment 8•6 years ago
|
||
mozreview-review |
Comment on attachment 8957393 [details] Bug 1444262 - ensure that a bookmark that later becomes a query doesn't break the mirror. https://reviewboard.mozilla.org/r/226326/#review234364 Awesome, thanks, Mark! Feel free to take or drop nits as you see fit. ::: toolkit/components/places/SyncedBookmarksMirror.jsm:401 (Diff revision 4) > remoteTree, newRemoteContents); > - let mergedRoot = await merger.merge(); > + let mergedRoot; > + try { > + mergedRoot = await merger.merge(); > + } finally { > - for (let { value, extra } of merger.telemetryEvents) { > + for (let { value, extra } of merger.telemetryEvents) { Oh, nice catch! ::: toolkit/components/places/SyncedBookmarksMirror.jsm:2933 (Diff revision 4) > + * - Local folders are compatible with remote livemarks, but not vice-versa > + * - Bookmarks and queries are always compatible. > + * > + * @return {Boolean} > + */ > + hasCompatibleKind(remoteNode) { Micro-nit: Let's call this `otherNode`. ::: toolkit/components/places/SyncedBookmarksMirror.jsm:3435 (Diff revision 4) > MirrorLog.trace("Merging folders ${localNode} and ${remoteNode}", > { localNode, remoteNode }); > await this.mergeChildListsIntoMergedNode(mergedNode, localNode, remoteNode); > return mergedNode; > } > - > + // Otherwise it must be a livemark. Unless you think the logging would be useful to keep (we don't log for queries, so I'd be inclined to drop it), I think you can drop this entire block, including the `return`, let it fall through to the end, and move this comment into `hasCompatibleKind`. ::: toolkit/components/places/SyncedBookmarksMirror.jsm:3447 (Diff revision 4) > - value: "kind", > - extra: { local: "folder", remote: "folder" }, > - }); > - return mergedNode; > + return mergedNode; > - } > + } > - > + // Otherwise are compatible types, so return the merged node. Micro-nit: types -> kinds, let's also mention we don't need to walk children for these kinds. ::: toolkit/components/places/tests/sync/test_bookmark_kinds.js:392 (Diff revision 4) > + }], > + }); > + await PlacesTestUtils.markBookmarksAsSynced(); > + > + info("Make remote changes"); > + await buf.store([{ Nit: Same comment as `bookmarkBBBB` below; `livemarkAAAA` is technically an orphan, the `parentid` is ignored, and the `parentName` doesn't match up. ::: toolkit/components/places/tests/sync/test_bookmark_kinds.js:444 (Diff revision 4) > + > + // Now pretend that same records are already on the server. > + await buf.store([{ > + id: "menu", > + type: "folder", > + children: ["bookmarkAAAA"], Nit: Let's add `bookmarkBBBB` here, too. It's technically not necessary for this test, but the merger will treat B as an orphan, and my inner quibbler would feel better if that weren't a factor in this test. :-) ::: toolkit/components/places/tests/sync/test_bookmark_kinds.js:447 (Diff revision 4) > + id: "menu", > + type: "folder", > + children: ["bookmarkAAAA"], > + }, { > + id: "bookmarkAAAA", > + parentId: PlacesSyncUtils.bookmarks.guidToRecordId(PlacesUtils.bookmarks.menuGuid), Nit: "menu" is shorter, but this property is spelled `parentid`, and the merger ignores it, anyway. :-) ::: toolkit/components/places/tests/sync/test_bookmark_kinds.js:520 (Diff revision 4) > + id: "menu", > + type: "folder", > + children: ["AAAAAAAAAAAA"], > + }, { > + id: "AAAAAAAAAAAA", > + parentId: PlacesSyncUtils.bookmarks.guidToRecordId(PlacesUtils.bookmarks.menuGuid), Ditto.
Attachment #8957393 -
Flags: review?(kit) → review+
Comment hidden (mozreview-request) |
Comment 10•6 years ago
|
||
Pushed by mhammond@skippinet.com.au: https://hg.mozilla.org/integration/autoland/rev/41c707ae4d6d ensure that a bookmark that later becomes a query doesn't break the mirror. r=kitcambridge
Comment 11•6 years ago
|
||
bugherder |
https://hg.mozilla.org/mozilla-central/rev/41c707ae4d6d
Status: ASSIGNED → RESOLVED
Closed: 6 years ago
status-firefox61:
--- → fixed
Resolution: --- → FIXED
Target Milestone: --- → Firefox 61
Updated•6 years ago
|
Updated•6 years ago
|
You need to log in
before you can comment on or make changes to this bug.
Description
•