summaryrefslogtreecommitdiffstats
path: root/services/sync/Weave.sys.mjs
diff options
context:
space:
mode:
Diffstat (limited to 'services/sync/Weave.sys.mjs')
-rw-r--r--services/sync/Weave.sys.mjs190
1 files changed, 190 insertions, 0 deletions
diff --git a/services/sync/Weave.sys.mjs b/services/sync/Weave.sys.mjs
new file mode 100644
index 0000000000..05a7031a73
--- /dev/null
+++ b/services/sync/Weave.sys.mjs
@@ -0,0 +1,190 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this
+ * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
+
+const lazy = {};
+ChromeUtils.defineESModuleGetters(lazy, {
+ CLIENT_NOT_CONFIGURED: "resource://services-sync/constants.sys.mjs",
+ FileUtils: "resource://gre/modules/FileUtils.sys.mjs",
+});
+
+XPCOMUtils.defineLazyPreferenceGetter(
+ lazy,
+ "syncUsername",
+ "services.sync.username"
+);
+
+/**
+ * Sync's XPCOM service.
+ *
+ * It is named "Weave" for historical reasons.
+ *
+ * It's worth noting how Sync is lazily loaded. We register a timer that
+ * loads Sync a few seconds after app startup. This is so Sync does not
+ * adversely affect application start time.
+ *
+ * If Sync is not configured, no extra Sync code is loaded. If an
+ * external component (say the UI) needs to interact with Sync, it
+ * should use the promise-base function whenLoaded() - something like the
+ * following:
+ *
+ * // 1. Grab a handle to the Sync XPCOM service.
+ * let service = Cc["@mozilla.org/weave/service;1"]
+ * .getService(Components.interfaces.nsISupports)
+ * .wrappedJSObject;
+ *
+ * // 2. Use the .then method of the promise.
+ * service.whenLoaded().then(() => {
+ * // You are free to interact with "Weave." objects.
+ * return;
+ * });
+ *
+ * And that's it! However, if you really want to avoid promises and do it
+ * old-school, then
+ *
+ * // 1. Get a reference to the service as done in (1) above.
+ *
+ * // 2. Check if the service has been initialized.
+ * if (service.ready) {
+ * // You are free to interact with "Weave." objects.
+ * return;
+ * }
+ *
+ * // 3. Install "ready" listener.
+ * Services.obs.addObserver(function onReady() {
+ * Services.obs.removeObserver(onReady, "weave:service:ready");
+ *
+ * // You are free to interact with "Weave." objects.
+ * }, "weave:service:ready", false);
+ *
+ * // 4. Trigger loading of Sync.
+ * service.ensureLoaded();
+ */
+export function WeaveService() {
+ this.wrappedJSObject = this;
+ this.ready = false;
+}
+
+WeaveService.prototype = {
+ classID: Components.ID("{74b89fb0-f200-4ae8-a3ec-dd164117f6de}"),
+
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIObserver",
+ "nsISupportsWeakReference",
+ ]),
+
+ get Weave() {
+ const { Weave } = ChromeUtils.importESModule(
+ "resource://services-sync/main.sys.mjs"
+ );
+ return Weave;
+ },
+
+ ensureLoaded() {
+ // Side-effect of accessing the service is that it is instantiated.
+ this.Weave.Service;
+ },
+
+ whenLoaded() {
+ if (this.ready) {
+ return Promise.resolve();
+ }
+ let onReadyPromise = new Promise(resolve => {
+ Services.obs.addObserver(function onReady() {
+ Services.obs.removeObserver(onReady, "weave:service:ready");
+ resolve();
+ }, "weave:service:ready");
+ });
+ this.ensureLoaded();
+ return onReadyPromise;
+ },
+
+ init() {
+ // Force Weave service to load if it hasn't triggered from overlays
+ this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
+ this.timer.initWithCallback(
+ {
+ notify: () => {
+ let isConfigured = false;
+ // We only load more if it looks like Sync is configured.
+ if (this.enabled) {
+ // We have an associated FxAccount. So, do a more thorough check.
+ // This will import a number of modules and thus increase memory
+ // accordingly. We could potentially copy code performed by
+ // this check into this file if our above code is yielding too
+ // many false positives.
+ var { Weave } = ChromeUtils.importESModule(
+ "resource://services-sync/main.sys.mjs"
+ );
+ isConfigured =
+ Weave.Status.checkSetup() != lazy.CLIENT_NOT_CONFIGURED;
+ }
+ if (isConfigured) {
+ this.ensureLoaded();
+ }
+ },
+ },
+ 10000,
+ Ci.nsITimer.TYPE_ONE_SHOT
+ );
+ },
+
+ /**
+ * Whether Sync appears to be enabled.
+ *
+ * This returns true if we have an associated FxA account and Sync is enabled.
+ *
+ * It does *not* perform a robust check to see if the client is working.
+ * For that, you'll want to check Weave.Status.checkSetup().
+ */
+ get enabled() {
+ return (
+ !!lazy.syncUsername &&
+ Services.prefs.getBoolPref("identity.fxaccounts.enabled")
+ );
+ },
+};
+
+export function AboutWeaveLog() {}
+AboutWeaveLog.prototype = {
+ classID: Components.ID("{d28f8a0b-95da-48f4-b712-caf37097be41}"),
+
+ QueryInterface: ChromeUtils.generateQI([
+ "nsIAboutModule",
+ "nsISupportsWeakReference",
+ ]),
+
+ getURIFlags(aURI) {
+ return 0;
+ },
+
+ newChannel(aURI, aLoadInfo) {
+ let dir = lazy.FileUtils.getDir("ProfD", ["weave", "logs"]);
+ try {
+ dir.create(Ci.nsIFile.DIRECTORY_TYPE, lazy.FileUtils.PERMS_DIRECTORY);
+ } catch (ex) {
+ if (ex.result != Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
+ throw ex;
+ }
+ // Ignore the exception due to a directory that already exists.
+ }
+ let uri = Services.io.newFileURI(dir);
+ let channel = Services.io.newChannelFromURIWithLoadInfo(uri, aLoadInfo);
+
+ channel.originalURI = aURI;
+
+ // Ensure that the about page has the same privileges as a regular directory
+ // view. That way links to files can be opened. make sure we use the correct
+ // origin attributes when creating the principal for accessing the
+ // about:sync-log data.
+ let principal = Services.scriptSecurityManager.createContentPrincipal(
+ uri,
+ aLoadInfo.originAttributes
+ );
+
+ channel.owner = principal;
+ return channel;
+ },
+};