Bug 1846030 [wpt PR 41229] - CloseWatcher: factor out and expand Esc key tests, a...
[gecko.git] / services / sync / Weave.sys.mjs
blob05a7031a7374328a174a43a8c2a67f7874184024
1 /* This Source Code Form is subject to the terms of the Mozilla Public
2  * License, v. 2.0. If a copy of the MPL was not distributed with this
3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
5 import { XPCOMUtils } from "resource://gre/modules/XPCOMUtils.sys.mjs";
7 const lazy = {};
8 ChromeUtils.defineESModuleGetters(lazy, {
9   CLIENT_NOT_CONFIGURED: "resource://services-sync/constants.sys.mjs",
10   FileUtils: "resource://gre/modules/FileUtils.sys.mjs",
11 });
13 XPCOMUtils.defineLazyPreferenceGetter(
14   lazy,
15   "syncUsername",
16   "services.sync.username"
19 /**
20  * Sync's XPCOM service.
21  *
22  * It is named "Weave" for historical reasons.
23  *
24  * It's worth noting how Sync is lazily loaded. We register a timer that
25  * loads Sync a few seconds after app startup. This is so Sync does not
26  * adversely affect application start time.
27  *
28  * If Sync is not configured, no extra Sync code is loaded. If an
29  * external component (say the UI) needs to interact with Sync, it
30  * should use the promise-base function whenLoaded() - something like the
31  * following:
32  *
33  * // 1. Grab a handle to the Sync XPCOM service.
34  * let service = Cc["@mozilla.org/weave/service;1"]
35  *                 .getService(Components.interfaces.nsISupports)
36  *                 .wrappedJSObject;
37  *
38  * // 2. Use the .then method of the promise.
39  * service.whenLoaded().then(() => {
40  *   // You are free to interact with "Weave." objects.
41  *   return;
42  * });
43  *
44  * And that's it!  However, if you really want to avoid promises and do it
45  * old-school, then
46  *
47  * // 1. Get a reference to the service as done in (1) above.
48  *
49  * // 2. Check if the service has been initialized.
50  * if (service.ready) {
51  *   // You are free to interact with "Weave." objects.
52  *   return;
53  * }
54  *
55  * // 3. Install "ready" listener.
56  * Services.obs.addObserver(function onReady() {
57  *   Services.obs.removeObserver(onReady, "weave:service:ready");
58  *
59  *   // You are free to interact with "Weave." objects.
60  * }, "weave:service:ready", false);
61  *
62  * // 4. Trigger loading of Sync.
63  * service.ensureLoaded();
64  */
65 export function WeaveService() {
66   this.wrappedJSObject = this;
67   this.ready = false;
70 WeaveService.prototype = {
71   classID: Components.ID("{74b89fb0-f200-4ae8-a3ec-dd164117f6de}"),
73   QueryInterface: ChromeUtils.generateQI([
74     "nsIObserver",
75     "nsISupportsWeakReference",
76   ]),
78   get Weave() {
79     const { Weave } = ChromeUtils.importESModule(
80       "resource://services-sync/main.sys.mjs"
81     );
82     return Weave;
83   },
85   ensureLoaded() {
86     // Side-effect of accessing the service is that it is instantiated.
87     this.Weave.Service;
88   },
90   whenLoaded() {
91     if (this.ready) {
92       return Promise.resolve();
93     }
94     let onReadyPromise = new Promise(resolve => {
95       Services.obs.addObserver(function onReady() {
96         Services.obs.removeObserver(onReady, "weave:service:ready");
97         resolve();
98       }, "weave:service:ready");
99     });
100     this.ensureLoaded();
101     return onReadyPromise;
102   },
104   init() {
105     // Force Weave service to load if it hasn't triggered from overlays
106     this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
107     this.timer.initWithCallback(
108       {
109         notify: () => {
110           let isConfigured = false;
111           // We only load more if it looks like Sync is configured.
112           if (this.enabled) {
113             // We have an associated FxAccount. So, do a more thorough check.
114             // This will import a number of modules and thus increase memory
115             // accordingly. We could potentially copy code performed by
116             // this check into this file if our above code is yielding too
117             // many false positives.
118             var { Weave } = ChromeUtils.importESModule(
119               "resource://services-sync/main.sys.mjs"
120             );
121             isConfigured =
122               Weave.Status.checkSetup() != lazy.CLIENT_NOT_CONFIGURED;
123           }
124           if (isConfigured) {
125             this.ensureLoaded();
126           }
127         },
128       },
129       10000,
130       Ci.nsITimer.TYPE_ONE_SHOT
131     );
132   },
134   /**
135    * Whether Sync appears to be enabled.
136    *
137    * This returns true if we have an associated FxA account and Sync is enabled.
138    *
139    * It does *not* perform a robust check to see if the client is working.
140    * For that, you'll want to check Weave.Status.checkSetup().
141    */
142   get enabled() {
143     return (
144       !!lazy.syncUsername &&
145       Services.prefs.getBoolPref("identity.fxaccounts.enabled")
146     );
147   },
150 export function AboutWeaveLog() {}
151 AboutWeaveLog.prototype = {
152   classID: Components.ID("{d28f8a0b-95da-48f4-b712-caf37097be41}"),
154   QueryInterface: ChromeUtils.generateQI([
155     "nsIAboutModule",
156     "nsISupportsWeakReference",
157   ]),
159   getURIFlags(aURI) {
160     return 0;
161   },
163   newChannel(aURI, aLoadInfo) {
164     let dir = lazy.FileUtils.getDir("ProfD", ["weave", "logs"]);
165     try {
166       dir.create(Ci.nsIFile.DIRECTORY_TYPE, lazy.FileUtils.PERMS_DIRECTORY);
167     } catch (ex) {
168       if (ex.result != Cr.NS_ERROR_FILE_ALREADY_EXISTS) {
169         throw ex;
170       }
171       // Ignore the exception due to a directory that already exists.
172     }
173     let uri = Services.io.newFileURI(dir);
174     let channel = Services.io.newChannelFromURIWithLoadInfo(uri, aLoadInfo);
176     channel.originalURI = aURI;
178     // Ensure that the about page has the same privileges as a regular directory
179     // view. That way links to files can be opened. make sure we use the correct
180     // origin attributes when creating the principal for accessing the
181     // about:sync-log data.
182     let principal = Services.scriptSecurityManager.createContentPrincipal(
183       uri,
184       aLoadInfo.originAttributes
185     );
187     channel.owner = principal;
188     return channel;
189   },