services/sync/Weave.js

changeset 0
6474c204b198
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/services/sync/Weave.js	Wed Dec 31 06:09:35 2014 +0100
     1.3 @@ -0,0 +1,199 @@
     1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public
     1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this
     1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     1.7 +
     1.8 +const Cc = Components.classes;
     1.9 +const Ci = Components.interfaces;
    1.10 +const Cu = Components.utils;
    1.11 +
    1.12 +Cu.import("resource://gre/modules/XPCOMUtils.jsm");
    1.13 +Cu.import("resource://gre/modules/Services.jsm");
    1.14 +Cu.import("resource://gre/modules/FileUtils.jsm");
    1.15 +Cu.import("resource://gre/modules/Promise.jsm");
    1.16 +Cu.import("resource://services-sync/util.js");
    1.17 +
    1.18 +const SYNC_PREFS_BRANCH = "services.sync.";
    1.19 +
    1.20 +
    1.21 +/**
    1.22 + * Sync's XPCOM service.
    1.23 + *
    1.24 + * It is named "Weave" for historical reasons.
    1.25 + *
    1.26 + * It's worth noting how Sync is lazily loaded. We register a timer that
    1.27 + * loads Sync a few seconds after app startup. This is so Sync does not
    1.28 + * adversely affect application start time.
    1.29 + *
    1.30 + * If Sync is not configured, no extra Sync code is loaded. If an
    1.31 + * external component (say the UI) needs to interact with Sync, it
    1.32 + * should use the promise-base function whenLoaded() - something like the
    1.33 + * following:
    1.34 + *
    1.35 + * // 1. Grab a handle to the Sync XPCOM service.
    1.36 + * let service = Cc["@mozilla.org/weave/service;1"]
    1.37 + *                 .getService(Components.interfaces.nsISupports)
    1.38 + *                 .wrappedJSObject;
    1.39 + *
    1.40 + * // 2. Use the .then method of the promise.
    1.41 + * service.whenLoaded().then(() => {
    1.42 + *   // You are free to interact with "Weave." objects.
    1.43 + *   return;
    1.44 + * });
    1.45 + *
    1.46 + * And that's it!  However, if you really want to avoid promises and do it
    1.47 + * old-school, then
    1.48 + *
    1.49 + * // 1. Get a reference to the service as done in (1) above.
    1.50 + *
    1.51 + * // 2. Check if the service has been initialized.
    1.52 + * if (service.ready) {
    1.53 + *   // You are free to interact with "Weave." objects.
    1.54 + *   return;
    1.55 + * }
    1.56 + *
    1.57 + * // 3. Install "ready" listener.
    1.58 + * Services.obs.addObserver(function onReady() {
    1.59 + *   Services.obs.removeObserver(onReady, "weave:service:ready");
    1.60 + *
    1.61 + *   // You are free to interact with "Weave." objects.
    1.62 + * }, "weave:service:ready", false);
    1.63 + *
    1.64 + * // 4. Trigger loading of Sync.
    1.65 + * service.ensureLoaded();
    1.66 + */
    1.67 +function WeaveService() {
    1.68 +  this.wrappedJSObject = this;
    1.69 +  this.ready = false;
    1.70 +}
    1.71 +WeaveService.prototype = {
    1.72 +  classID: Components.ID("{74b89fb0-f200-4ae8-a3ec-dd164117f6de}"),
    1.73 +
    1.74 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
    1.75 +                                         Ci.nsISupportsWeakReference]),
    1.76 +
    1.77 +  ensureLoaded: function () {
    1.78 +    Components.utils.import("resource://services-sync/main.js");
    1.79 +
    1.80 +    // Side-effect of accessing the service is that it is instantiated.
    1.81 +    Weave.Service;
    1.82 +  },
    1.83 +
    1.84 +  whenLoaded: function() {
    1.85 +    if (this.ready) {
    1.86 +      return Promise.resolve();
    1.87 +    }
    1.88 +    let deferred = Promise.defer();
    1.89 +
    1.90 +    Services.obs.addObserver(function onReady() {
    1.91 +      Services.obs.removeObserver(onReady, "weave:service:ready");
    1.92 +      deferred.resolve();
    1.93 +    }, "weave:service:ready", false);
    1.94 +    this.ensureLoaded();
    1.95 +    return deferred.promise;
    1.96 +  },
    1.97 +
    1.98 +  /**
    1.99 +   * Whether Firefox Accounts is enabled.
   1.100 +   *
   1.101 +   * @return bool
   1.102 +   */
   1.103 +  get fxAccountsEnabled() {
   1.104 +    try {
   1.105 +      // Old sync guarantees '@' will never appear in the username while FxA
   1.106 +      // uses the FxA email address - so '@' is the flag we use.
   1.107 +      let username = Services.prefs.getCharPref(SYNC_PREFS_BRANCH + "username");
   1.108 +      return !username || username.contains('@');
   1.109 +    } catch (_) {
   1.110 +      return true; // No username == only allow FxA to be configured.
   1.111 +    }
   1.112 +  },
   1.113 +
   1.114 +  /**
   1.115 +   * Returns whether the password engine is allowed. We explicitly disallow
   1.116 +   * the password engine when a master password is used to ensure those can't
   1.117 +   * be accessed without the master key.
   1.118 +   */
   1.119 +  get allowPasswordsEngine() {
   1.120 +    // This doesn't apply to old-style sync, it's only an issue for FxA.
   1.121 +    return !this.fxAccountsEnabled || !Utils.mpEnabled();
   1.122 +  },
   1.123 +
   1.124 +  /**
   1.125 +   * Whether Sync appears to be enabled.
   1.126 +   *
   1.127 +   * This returns true if all the Sync preferences for storing account
   1.128 +   * and server configuration are populated.
   1.129 +   *
   1.130 +   * It does *not* perform a robust check to see if the client is working.
   1.131 +   * For that, you'll want to check Weave.Status.checkSetup().
   1.132 +   */
   1.133 +  get enabled() {
   1.134 +    let prefs = Services.prefs.getBranch(SYNC_PREFS_BRANCH);
   1.135 +    return prefs.prefHasUserValue("username") &&
   1.136 +           prefs.prefHasUserValue("clusterURL");
   1.137 +  },
   1.138 +
   1.139 +  observe: function (subject, topic, data) {
   1.140 +    switch (topic) {
   1.141 +    case "app-startup":
   1.142 +      let os = Cc["@mozilla.org/observer-service;1"].
   1.143 +               getService(Ci.nsIObserverService);
   1.144 +      os.addObserver(this, "final-ui-startup", true);
   1.145 +      break;
   1.146 +
   1.147 +    case "final-ui-startup":
   1.148 +      // Force Weave service to load if it hasn't triggered from overlays
   1.149 +      this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   1.150 +      this.timer.initWithCallback({
   1.151 +        notify: function() {
   1.152 +          // We only load more if it looks like Sync is configured.
   1.153 +          let prefs = Services.prefs.getBranch(SYNC_PREFS_BRANCH);
   1.154 +          if (!prefs.prefHasUserValue("username")) {
   1.155 +            return;
   1.156 +          }
   1.157 +
   1.158 +          // We have a username. So, do a more thorough check. This will
   1.159 +          // import a number of modules and thus increase memory
   1.160 +          // accordingly. We could potentially copy code performed by
   1.161 +          // this check into this file if our above code is yielding too
   1.162 +          // many false positives.
   1.163 +          Components.utils.import("resource://services-sync/main.js");
   1.164 +          if (Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED) {
   1.165 +            this.ensureLoaded();
   1.166 +          }
   1.167 +        }.bind(this)
   1.168 +      }, 10000, Ci.nsITimer.TYPE_ONE_SHOT);
   1.169 +      break;
   1.170 +    }
   1.171 +  }
   1.172 +};
   1.173 +
   1.174 +function AboutWeaveLog() {}
   1.175 +AboutWeaveLog.prototype = {
   1.176 +  classID: Components.ID("{d28f8a0b-95da-48f4-b712-caf37097be41}"),
   1.177 +
   1.178 +  QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule,
   1.179 +                                         Ci.nsISupportsWeakReference]),
   1.180 +
   1.181 +  getURIFlags: function(aURI) {
   1.182 +    return 0;
   1.183 +  },
   1.184 +
   1.185 +  newChannel: function(aURI) {
   1.186 +    let dir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
   1.187 +    let uri = Services.io.newFileURI(dir);
   1.188 +    let channel = Services.io.newChannelFromURI(uri);
   1.189 +    channel.originalURI = aURI;
   1.190 +
   1.191 +    // Ensure that the about page has the same privileges as a regular directory
   1.192 +    // view. That way links to files can be opened.
   1.193 +    let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
   1.194 +                .getService(Ci.nsIScriptSecurityManager);
   1.195 +    let principal = ssm.getNoAppCodebasePrincipal(uri);
   1.196 +    channel.owner = principal;
   1.197 +    return channel;
   1.198 +  }
   1.199 +};
   1.200 +
   1.201 +const components = [WeaveService, AboutWeaveLog];
   1.202 +this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);

mercurial