Closed Bug 1596322 Opened 5 years ago Closed 5 years ago

Add bindings for implementing Sync engines in Rust

Categories

(Firefox :: Sync, defect, P1)

defect

Tracking

()

RESOLVED FIXED
Firefox 77
Tracking Status
firefox77 --- fixed

People

(Reporter: lina, Assigned: lina)

References

(Regression)

Details

(Keywords: regression)

Attachments

(1 file, 2 obsolete files)

As part of shipping Remerge (generic sync) on Desktop, we'll need to figure out how to integrate it with the existing Sync machinery. In a-s, this is handled entirely by the sync15 crate, which manages authentication with the token server, setting up the server, fetching and uploading BSOs, and record crypto.

It also provides a Store abstraction, which all our syncable data stores implement, as well as top-level sync functions for kicking the whole process off.

Shipping sync15 on Desktop will be tricky to do in its current state, because it pulls in networking libraries, and also (IIUC) depends on the a-s copy of NSS for crypto. Long-term, we'll definitely consider writing a Viaduct backend for HTTP requests, and linking to Gecko. Additionally, Desktop already has logic for talking to the token server, setting up storage, and downloading and uploading records. Having two state machines run as part of the same sync also duplicates work, and introduces more opportunities for things to go wrong.

In the meantime, we can make incremental progress by using our existing Sync code, and having the Rust code do all the heavy lifting for merging and storage. This would also bring us a step closer to landing Rust components on Desktop, without boiling the ocean.

Let's use this bug to brainstorm and prototype ideas.

I'll go first, to get things going! 😁

I wonder, can we use Rust XPCOM bindings to make a "native engine", with the guts of the storage and merging logic encapsulated entirely in Rust, but leaning on the Sync JS code for networking and crypto? I'm imagining a minimal interface that looks something like this:

interface mozIBridgedSyncEngineCallback {
    void handleSuccess(in nsIVariant result);
    void handleError(in AString message);
};

interface mozIBridgedSyncEngineSyncCallback : mozIBridgedSyncEngineCallback {
    void queueForUpload(in AString collectionName,
                        in Array<AString> recordsAsJSON);
};

interface mozIBridgedSyncEngine {
    attribute mozISyncedBookmarksMirrorLogger logger;

    void getLastSync(in AString collectionName,
                     in mozIBridgedSyncEngineCallback callback);
    void setLastSync(in AString collectionName,
                     in mozIBridgedSyncEngineCallback callback);

    void withIncomingRecords(in AString collectionName,
                             in Array<AString> recordsAsJSON);

    mozIPlacesPendingOperation sync(in mozIBridgedSyncEngineCallback callback);

    void syncFinished(in AString collectionName,
                      in Array<AString> uploadedIds);
};

Since we already get a JSON string when we decrypt incoming records, we can pass them directly over to Rust, instead of parsing them and inflating them into records on the JS side. The JS side would also take care of fetching from the data and metadata collections (if we keep using multiple collections), and the Rust code would stitch it together.

A Rust implementation of mozIBridgedSyncEngine would also manage a background thread, which we can use for merging and running synchronous storage operations. Gecko has a thread pool designed for this kind of thing, which we can lean on. We'll also need to figure out initializing the database connection, how we run storage operations, whether we use Rusqlite or mozStorage—but one step at a time. sync returns an interruptible operation, and there's a logger that we can use to integrate with Sync logging, like we do for bookmarks now...but, other than that, merging is completely opaque to the Sync JS code.

On success, Remerge can hand us records to upload, which we'd queue on the JS side until handleSuccess is called. We'd encrypt these directly, without parsing them first, and upload them to the data and meta collections.

There's also some boilerplate-y methods for managing the last sync time, which the JS side needs to know to fetch and upload records, and syncFinished, to tell Remerge to write everything that just got uploaded back to its mirror.

There isn't nearly enough detail in this—and, when it comes to Sync, the 😈 is in the details—but something to get us started.

Depends on: 1622082
Summary: Design and prototype a bridge for Rust generic sync on Desktop → Design and prototype a bridge for a Rust extension storage engine on Desktop
Attachment #9130685 - Attachment description: Bug 1596322 - Scaffolding for a Remerge Sync bridge. → Bug 1596322 - Scaffolding for an extension storage Sync engine in Rust.
Depends on: 1622949
See Also: → 1623245

We aren't intending to land this; this is more of a demo to show how
we could expose and configure bridged Rust storage (and soon, sync!)
interfaces.

Depends on D65268

Assignee: nobody → lina
Status: NEW → ASSIGNED
Priority: P2 → P1
Depends on: 1625286
Attachment #9130685 - Attachment description: Bug 1596322 - Scaffolding for an extension storage Sync engine in Rust. → Bug 1596322 - Add XPCOM bindings for Rust Sync engines. r?markh!,tcsc!,LougeniaBailey!
Attachment #9134867 - Attachment description: Bug 1596322 - Add an example form autofill storage implementation. → Bug 1596322 - [DO NOT LAND] Add an example form autofill storage implementation.

OK, I think this is finally ready for review! I think the order of dependencies here will turn out to be something like this:

  • Review and land D65268. I put up the extension storage and autofill storage as examples, but neither of those should land—they're just showing how we could use Golden Gate to hook up a Rust engine.
  • Once that's in, file and fix follow-up tickets for the TODOs in that patch: for example, exposing modified to Rust, refactoring CryptoWrapper to avoid the parse-then-stringify dance that we do now, and so on.
  • In parallel, get bug 1623245 (and the a-s pieces) to a reviewable state, with syncing hooked up. We'll also likely make changes to Golden Gate as we work on this. Bug 1623245 depends on having the a-s engine in place and vendored, which also means vendoring Rusqlite.

How does that sound?

Summary: Design and prototype a bridge for a Rust extension storage engine on Desktop → Add bindings for implementing Sync engines in Rust
Blocks: 1626125
Blocks: 1626128
Pushed by kcambridge@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/2b02e71f1780 Add XPCOM bindings for Rust Sync engines. r=markh,tcsc,LougeniaBailey
Pushed by kcambridge@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/d8ef791a2165 Add XPCOM bindings for Rust Sync engines. r=markh,tcsc,LougeniaBailey
Status: ASSIGNED → RESOLVED
Closed: 5 years ago
Resolution: --- → FIXED
Target Milestone: --- → Firefox 77

Backed out changeset d8ef791a2165 (bug 1596322) for browser_all_files_referenced.js failures

Push with failures: https://treeherder.mozilla.org/#/jobs?repo=autoland&searchStr=os%2Cx%2C10.14%2Cshippable%2Copt%2Cmochitests%2Ctest-macosx1014-64-shippable%2Fopt-mochitest-browser-chrome-e10s-1%2Cm%28bc1%29&fromchange=ef27657560d14ca61a6441c6b1e02ae6e446e712&tochange=b0496779c7cde65032214c2d3905cb7e42148f4f&selectedJob=296920268

Backout link: https://hg.mozilla.org/integration/autoland/rev/dfb06ae2f058e6743e0e7baab5d2625b62d7bd33

Failure log: https://treeherder.mozilla.org/logviewer.html#/jobs?job_id=296920268&repo=autoland&lineNumber=3391

[task 2020-04-09T09:35:43.414Z] 09:35:43     INFO - TEST-START | browser/base/content/test/static/browser_all_files_referenced.js
[task 2020-04-09T09:35:49.277Z] 09:35:49     INFO - TEST-INFO | started process screencapture
[task 2020-04-09T09:35:49.413Z] 09:35:49     INFO - TEST-INFO | screencapture: exit 0
[task 2020-04-09T09:35:49.413Z] 09:35:49     INFO - Buffered messages logged at 09:35:43
[task 2020-04-09T09:35:49.413Z] 09:35:49     INFO - Entering test bound checkAllTheFiles
[task 2020-04-09T09:35:49.413Z] 09:35:49     INFO - Buffered messages logged at 09:35:49
[task 2020-04-09T09:35:49.413Z] 09:35:49     INFO - indirectly whitelisted file: chrome://marionette/content/test_dialog.dtd used from chrome://marionette/content/test_dialog.xhtml
...
[task 2020-04-09T09:35:49.431Z] 09:35:49     INFO - indirectly whitelisted file: chrome://fxr/content/prefs.js used from chrome://fxr/content/prefs.html
[task 2020-04-09T09:35:49.431Z] 09:35:49     INFO - Buffered messages finished
[task 2020-04-09T09:35:49.431Z] 09:35:49     INFO - TEST-UNEXPECTED-FAIL | browser/base/content/test/static/browser_all_files_referenced.js | there should be no unreferenced files - Got 1, expected 0
[task 2020-04-09T09:35:49.432Z] 09:35:49     INFO - Stack trace:
[task 2020-04-09T09:35:49.432Z] 09:35:49     INFO - chrome://mochikit/content/browser-test.js:test_is:1320
[task 2020-04-09T09:35:49.432Z] 09:35:49     INFO - chrome://mochitests/content/browser/browser/base/content/test/static/browser_all_files_referenced.js:checkAllTheFiles:950
[task 2020-04-09T09:35:49.432Z] 09:35:49     INFO - chrome://mochikit/content/browser-test.js:Tester_execTest/<:1062
[task 2020-04-09T09:35:49.432Z] 09:35:49     INFO - chrome://mochikit/content/browser-test.js:Tester_execTest:1097
[task 2020-04-09T09:35:49.432Z] 09:35:49     INFO - chrome://mochikit/content/browser-test.js:nextTest/<:925
[task 2020-04-09T09:35:49.432Z] 09:35:49     INFO - chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:SimpleTest.waitForFocus/waitForFocusInner/focusedOrLoaded/<:918
[task 2020-04-09T09:35:49.432Z] 09:35:49     INFO - Not taking screenshot here: see the one that was previously logged
[task 2020-04-09T09:35:49.434Z] 09:35:49     INFO - TEST-UNEXPECTED-FAIL | browser/base/content/test/static/browser_all_files_referenced.js | unreferenced file: resource://services-sync/bridged_engine.js - 
[task 2020-04-09T09:35:49.434Z] 09:35:49     INFO - Stack trace:
[task 2020-04-09T09:35:49.434Z] 09:35:49     INFO - chrome://mochikit/content/browser-test.js:test_ok:1292
[task 2020-04-09T09:35:49.434Z] 09:35:49     INFO - chrome://mochitests/content/browser/browser/base/content/test/static/browser_all_files_referenced.js:checkAllTheFiles:954
[task 2020-04-09T09:35:49.434Z] 09:35:49     INFO - chrome://mochikit/content/browser-test.js:Tester_execTest/<:1062
[task 2020-04-09T09:35:49.434Z] 09:35:49     INFO - chrome://mochikit/content/browser-test.js:Tester_execTest:1097
[task 2020-04-09T09:35:49.434Z] 09:35:49     INFO - chrome://mochikit/content/browser-test.js:nextTest/<:925
[task 2020-04-09T09:35:49.434Z] 09:35:49     INFO - chrome://mochikit/content/tests/SimpleTest/SimpleTest.js:SimpleTest.waitForFocus/waitForFocusInner/focusedOrLoaded/<:918
[task 2020-04-09T09:35:49.434Z] 09:35:49     INFO - ignored unused whitelist entry: resource://app/blocklist.xml
[task 2020-04-09T09:35:49.435Z] 09:35:49     INFO - ignored unused whitelist entry: resource://gre/gmp-clearkey/0.1/manifest.json
[task 2020-04-09T09:35:49.435Z] 09:35:49     INFO - ignored unused whitelist entry: resource://gre/res/test.properties
[task 2020-04-09T09:35:49.435Z] 09:35:49     INFO - missing file: resource://gre/components/nsAsyncShutdown.js
[task 2020-04-09T09:35:49.435Z] 09:35:49     INFO - missing file: resource://gre/modules/commonjs/toolkit/loader.js
[task 2020-04-09T09:35:49.445Z] 09:35:49     INFO - missing file: resource://search-extensions/yandex/__MSG_extensionIcon__
...
[task 2020-04-09T09:35:49.639Z] 09:35:49     INFO - missing file: resource://app/localization/en-US/toolkit/about/aboutCompat.ftl referenced from jar:file:///Users/cltbld/tasks/task_1586422769/build/application/Firefox%20Nightly.app/Contents/Resources/browser/features/webcompat@mozilla.org.xpi!/about-compat/aboutCompat.html
[task 2020-04-09T09:35:49.677Z] 09:35:49     INFO - Leaving test bound checkAllTheFiles
[task 2020-04-09T09:35:49.680Z] 09:35:49     INFO - Console message: No chrome package registered for chrome://geckoview/content/geckoview.xhtml
[task 2020-04-09T09:35:49.680Z] 09:35:49     INFO - Console message: No chrome package registered for chrome://gfxsanity/content/sanityparent.html
[task 2020-04-09T09:35:49.680Z] 09:35:49     INFO - Console message: No chrome package registered for chrome://help/content/help.js
[task 2020-04-09T09:35:49.750Z] 09:35:49     INFO - GECKO(2190) | MEMORY STAT vsizeMaxContiguous not supported in this build configuration.
[task 2020-04-09T09:35:49.750Z] 09:35:49     INFO - GECKO(2190) | MEMORY STAT | vsize 8092MB | residentFast 808MB | heapAllocated 541MB
[task 2020-04-09T09:35:49.750Z] 09:35:49     INFO - TEST-OK | browser/base/content/test/static/browser_all_files_referenced.js | took 6278ms
Status: RESOLVED → REOPENED
Resolution: FIXED → ---
Target Milestone: Firefox 77 → ---

Please also note that I did a local build which had the last landing of this patch (rev d8ef791a2165) but not the latest backout. On a clobber build, the Cargo.lock file at the root of the tree gets modified to remove the golden_gate and golden_gate_traits crates. I'm guessing this is because the Cargo.toml file wasn't updated to reference these crates and something in the build does a cargo update or similar causing the lockfile to throw out these changes. Please take a look before re-landing, thanks!

Oh, thanks for the heads-up, Kats! The Cargo.lock changes are, indeed, because the two [DO NOT LAND] example commits use golden_gate, but not the first one. I updated that, and also fixed the browser_all_files_referenced.js failure.

Flags: needinfo?(lina)
Depends on: 1628752
Blocks: 1628752
No longer depends on: 1628752
Pushed by kcambridge@mozilla.com: https://hg.mozilla.org/integration/autoland/rev/fb65955a1a82 Add XPCOM bindings for Rust Sync engines. r=markh,tcsc,LougeniaBailey
Status: REOPENED → RESOLVED
Closed: 5 years ago5 years ago
Resolution: --- → FIXED
Target Milestone: --- → Firefox 77
Regressed by: 1629254
Keywords: regression
See Also: 1623245
Attachment #9134867 - Attachment is obsolete: true
Attachment #9136534 - Attachment is obsolete: true
Has Regression Range: --- → yes
Type: task → defect
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: