Weave.js 5.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178
  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/. */
  4. const Cc = Components.classes;
  5. const Ci = Components.interfaces;
  6. const Cu = Components.utils;
  7. Cu.import("resource://gre/modules/XPCOMUtils.jsm");
  8. Cu.import("resource://gre/modules/Services.jsm");
  9. Cu.import("resource://gre/modules/FileUtils.jsm");
  10. Cu.import("resource://gre/modules/Promise.jsm");
  11. Cu.import("resource://services-sync/util.js");
  12. const SYNC_PREFS_BRANCH = "services.sync.";
  13. /**
  14. * Sync's XPCOM service.
  15. *
  16. * It is named "Weave" for historical reasons.
  17. *
  18. * It's worth noting how Sync is lazily loaded. We register a timer that
  19. * loads Sync a few seconds after app startup. This is so Sync does not
  20. * adversely affect application start time.
  21. *
  22. * If Sync is not configured, no extra Sync code is loaded. If an
  23. * external component (say the UI) needs to interact with Sync, it
  24. * should use the promise-base function whenLoaded() - something like the
  25. * following:
  26. *
  27. * // 1. Grab a handle to the Sync XPCOM service.
  28. * let service = Cc["@mozilla.org/weave/service;1"]
  29. * .getService(Components.interfaces.nsISupports)
  30. * .wrappedJSObject;
  31. *
  32. * // 2. Use the .then method of the promise.
  33. * service.whenLoaded().then(() => {
  34. * // You are free to interact with "Weave." objects.
  35. * return;
  36. * });
  37. *
  38. * And that's it! However, if you really want to avoid promises and do it
  39. * old-school, then
  40. *
  41. * // 1. Get a reference to the service as done in (1) above.
  42. *
  43. * // 2. Check if the service has been initialized.
  44. * if (service.ready) {
  45. * // You are free to interact with "Weave." objects.
  46. * return;
  47. * }
  48. *
  49. * // 3. Install "ready" listener.
  50. * Services.obs.addObserver(function onReady() {
  51. * Services.obs.removeObserver(onReady, "weave:service:ready");
  52. *
  53. * // You are free to interact with "Weave." objects.
  54. * }, "weave:service:ready", false);
  55. *
  56. * // 4. Trigger loading of Sync.
  57. * service.ensureLoaded();
  58. */
  59. function WeaveService() {
  60. this.wrappedJSObject = this;
  61. this.ready = false;
  62. }
  63. WeaveService.prototype = {
  64. classID: Components.ID("{74b89fb0-f200-4ae8-a3ec-dd164117f6de}"),
  65. QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver,
  66. Ci.nsISupportsWeakReference]),
  67. ensureLoaded: function () {
  68. Components.utils.import("resource://services-sync/main.js");
  69. // Side-effect of accessing the service is that it is instantiated.
  70. Weave.Service;
  71. },
  72. whenLoaded: function() {
  73. if (this.ready) {
  74. return Promise.resolve();
  75. }
  76. let deferred = Promise.defer();
  77. Services.obs.addObserver(function onReady() {
  78. Services.obs.removeObserver(onReady, "weave:service:ready");
  79. deferred.resolve();
  80. }, "weave:service:ready", false);
  81. this.ensureLoaded();
  82. return deferred.promise;
  83. },
  84. /**
  85. * Whether Sync appears to be enabled.
  86. *
  87. * This returns true if all the Sync preferences for storing account
  88. * and server configuration are populated.
  89. *
  90. * It does *not* perform a robust check to see if the client is working.
  91. * For that, you'll want to check Weave.Status.checkSetup().
  92. */
  93. get enabled() {
  94. let prefs = Services.prefs.getBranch(SYNC_PREFS_BRANCH);
  95. return prefs.prefHasUserValue("username") &&
  96. prefs.prefHasUserValue("clusterURL");
  97. },
  98. observe: function (subject, topic, data) {
  99. switch (topic) {
  100. case "app-startup":
  101. let os = Cc["@mozilla.org/observer-service;1"].
  102. getService(Ci.nsIObserverService);
  103. os.addObserver(this, "final-ui-startup", true);
  104. break;
  105. case "final-ui-startup":
  106. // Force Weave service to load if it hasn't triggered from overlays
  107. this.timer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
  108. this.timer.initWithCallback({
  109. notify: function() {
  110. let isConfigured = false;
  111. // We only load more if it looks like Sync is configured.
  112. let prefs = Services.prefs.getBranch(SYNC_PREFS_BRANCH);
  113. if (prefs.prefHasUserValue("username")) {
  114. // We have a username. So, do a more thorough check. This will
  115. // import a number of modules and thus increase memory
  116. // accordingly. We could potentially copy code performed by
  117. // this check into this file if our above code is yielding too
  118. // many false positives.
  119. Components.utils.import("resource://services-sync/main.js");
  120. isConfigured = Weave.Status.checkSetup() != Weave.CLIENT_NOT_CONFIGURED;
  121. }
  122. if (isConfigured) {
  123. this.ensureLoaded();
  124. }
  125. }.bind(this)
  126. }, 10000, Ci.nsITimer.TYPE_ONE_SHOT);
  127. break;
  128. }
  129. }
  130. };
  131. function AboutWeaveLog() {}
  132. AboutWeaveLog.prototype = {
  133. classID: Components.ID("{d28f8a0b-95da-48f4-b712-caf37097be41}"),
  134. QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule,
  135. Ci.nsISupportsWeakReference]),
  136. getURIFlags: function(aURI) {
  137. return 0;
  138. },
  139. newChannel: function(aURI, aLoadInfo) {
  140. let dir = FileUtils.getDir("ProfD", ["weave", "logs"], true);
  141. let uri = Services.io.newFileURI(dir);
  142. let channel = Services.io.newChannelFromURIWithLoadInfo(uri, aLoadInfo);
  143. channel.originalURI = aURI;
  144. // Ensure that the about page has the same privileges as a regular directory
  145. // view. That way links to files can be opened. make sure we use the correct
  146. // origin attributes when creating the principal for accessing the
  147. // about:sync-log data.
  148. let ssm = Cc["@mozilla.org/scriptsecuritymanager;1"]
  149. .getService(Ci.nsIScriptSecurityManager);
  150. let principal = ssm.createCodebasePrincipal(uri, aLoadInfo.originAttributes);
  151. channel.owner = principal;
  152. return channel;
  153. }
  154. };
  155. const components = [WeaveService, AboutWeaveLog];
  156. this.NSGetFactory = XPCOMUtils.generateNSGetFactory(components);