Wed, 31 Dec 2014 07:53:36 +0100
Correct small whitespace inconsistency, lost while renaming variables.
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 const Cc = Components.classes;
6 const Ci = Components.interfaces;
7 const Cu = Components.utils;
9 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
10 Cu.import("resource://gre/modules/Services.jsm");
11 Cu.import("resource://gre/modules/FileUtils.jsm");
12 Cu.import("resource://gre/modules/Promise.jsm");
13 Cu.import("resource://services-sync/util.js");
15 const SYNC_PREFS_BRANCH = "services.sync.";
18 /**
19 * Sync's XPCOM service.
20 *
21 * It is named "Weave" for historical reasons.
22 *
23 * It's worth noting how Sync is lazily loaded. We register a timer that
24 * loads Sync a few seconds after app startup. This is so Sync does not
25 * adversely affect application start time.
26 *
27 * If Sync is not configured, no extra Sync code is loaded. If an
28 * external component (say the UI) needs to interact with Sync, it
29 * should use the promise-base function whenLoaded() - something like the
30 * following:
31 *
32 * // 1. Grab a handle to the Sync XPCOM service.
33 * let service = Cc["@mozilla.org/weave/service;1"]
34 * .getService(Components.interfaces.nsISupports)
35 * .wrappedJSObject;
36 *
37 * // 2. Use the .then method of the promise.
38 * service.whenLoaded().then(() => {
39 * // You are free to interact with "Weave." objects.
40 * return;
41 * });
42 *
43 * And that's it! However, if you really want to avoid promises and do it
44 * old-school, then
45 *
46 * // 1. Get a reference to the service as done in (1) above.
47 *
48 * // 2. Check if the service has been initialized.
49 * if (service.ready) {
50 * // You are free to interact with "Weave." objects.
51 * return;
52 * }
53 *
54 * // 3. Install "ready" listener.
55 * Services.obs.addObserver(function onReady() {
56 * Services.obs.removeObserver(onReady, "weave:service:ready");
57 *
58 * // You are free to interact with "Weave." objects.
59 * }, "weave:service:ready", false);
60 *
61 * // 4. Trigger loading of Sync.
62 * service.ensureLoaded();
63 */
64 function WeaveService() {
65 this.wrappedJSObject = this;
66 this.ready = false;
67 }
68 WeaveService.prototype = {
69 classID: Components.ID("{74b89fb0-f200-4ae8-a3ec-dd164117f6de}"),
71 QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
72 Ci.nsISupportsWeakReference]),
74 ensureLoaded: function () {
75 Components.utils.import("resource://services-sync/main.js");
77 // Side-effect of accessing the service is that it is instantiated.
78 Weave.Service;
79 },
81 whenLoaded: function() {
82 if (this.ready) {
83 return Promise.resolve();
84 }
85 let deferred = Promise.defer();
87 Services.obs.addObserver(function onReady() {
88 Services.obs.removeObserver(onReady, "weave:service:ready");
89 deferred.resolve();
90 }, "weave:service:ready", false);
91 this.ensureLoaded();
92 return deferred.promise;
93 },
95 /**
96 * Whether Firefox Accounts is enabled.
97 *
98 * @return bool
99 */
100 get fxAccountsEnabled() {
101 try {
102 // Old sync guarantees '@' will never appear in the username while FxA
103 // uses the FxA email address - so '@' is the flag we use.
104 let username = Services.prefs.getCharPref(SYNC_PREFS_BRANCH + "username");
105 return !username || username.contains('@');
106 } catch (_) {
107 return true; // No username == only allow FxA to be configured.
108 }
109 },
111 /**
112 * Returns whether the password engine is allowed. We explicitly disallow
113 * the password engine when a master password is used to ensure those can't
114 * be accessed without the master key.
115 */
116 get allowPasswordsEngine() {
117 // This doesn't apply to old-style sync, it's only an issue for FxA.
118 return !this.fxAccountsEnabled || !Utils.mpEnabled();
119 },
121 /**
122 * Whether Sync appears to be enabled.
123 *
124 * This returns true if all the Sync preferences for storing account
125 * and server configuration are populated.
126 *
127 * It does *not* perform a robust check to see if the client is working.
128 * For that, you'll want to check Weave.Status.checkSetup().
129 */
130 get enabled() {
131 let prefs = Services.prefs.getBranch(SYNC_PREFS_BRANCH);
132 return prefs.prefHasUserValue("username") &&
133 prefs.prefHasUserValue("clusterURL");
134 },
136 observe: function (subject, topic, data) {
137 switch (topic) {
138 case "app-startup":
139 let os = Cc["@mozilla.org/observer-service;1"].
140 getService(Ci.nsIObserverService);
141 os.addObserver(this, "final-ui-startup", true);
142 break;
144 case "final-ui-startup":
145 // Force Weave service to load if it hasn't triggered from overlays
146 this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
147 this.timer.initWithCallback({
148 notify: function() {
149 // We only load more if it looks like Sync is configured.
150 let prefs = Services.prefs.getBranch(SYNC_PREFS_BRANCH);
151 if (!prefs.prefHasUserValue("username")) {
152 return;
153 }
155 // We have a username. So, do a more thorough check. This will
156 // import a number of modules and thus increase memory
157 // accordingly. We could potentially copy code performed by
158 // this check into this file if our above code is yielding too
159 // many false positives.
160 Components.utils.import("resource://services-sync/main.js");
161 if (Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED) {
162 this.ensureLoaded();
163 }
164 }.bind(this)
165 }, 10000, Ci.nsITimer.TYPE_ONE_SHOT);
166 break;
167 }
168 }
169 };
171 function AboutWeaveLog() {}
172 AboutWeaveLog.prototype = {
173 classID: Components.ID("{d28f8a0b-95da-48f4-b712-caf37097be41}"),
175 QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule,
176 Ci.nsISupportsWeakReference]),
178 getURIFlags: function(aURI) {
179 return 0;
180 },
182 newChannel: function(aURI) {
183 let dir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
184 let uri = Services.io.newFileURI(dir);
185 let channel = Services.io.newChannelFromURI(uri);
186 channel.originalURI = aURI;
188 // Ensure that the about page has the same privileges as a regular directory
189 // view. That way links to files can be opened.
190 let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
191 .getService(Ci.nsIScriptSecurityManager);
192 let principal = ssm.getNoAppCodebasePrincipal(uri);
193 channel.owner = principal;
194 return channel;
195 }
196 };
198 const components = [WeaveService, AboutWeaveLog];
199 this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);