services/sync/Weave.js

Thu, 22 Jan 2015 13:21:57 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Thu, 22 Jan 2015 13:21:57 +0100
branch
TOR_BUG_9701
changeset 15
b8a032363ba2
permissions
-rw-r--r--

Incorporate requested changes from Mozilla in review:
https://bugzilla.mozilla.org/show_bug.cgi?id=1123480#c6

     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);

mercurial