Bug 1088465 - MozLoopService: Use a |mocks| property instead of passing arguments through registration. r=mikedeboer a=loop-only
authorMike de Boer <mdeboer@mozilla.com>
Mon, 27 Oct 2014 11:11:36 +0100
changeset 233773 2f0874bd9c8d7ff85d45e89872922c42a8a01a4a
parent 233772 4f042a59a39ea6a34b8623381f31274f0a273f98
child 233774 97384b6dc451bc8fbd7bfc24a4ca6e8fad5f3c06
push id4187
push userbhearsum@mozilla.com
push dateFri, 28 Nov 2014 15:29:12 +0000
treeherdermozilla-beta@f23cc6a30c11 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikedeboer, loop-only
bugs1088465
milestone35.0a2
Bug 1088465 - MozLoopService: Use a |mocks| property instead of passing arguments through registration. r=mikedeboer a=loop-only
browser/components/loop/LoopCalls.jsm
browser/components/loop/MozLoopService.jsm
browser/components/loop/test/mochitest/browser_fxa_login.js
browser/components/loop/test/xpcshell/head.js
browser/components/loop/test/xpcshell/test_loopservice_busy.js
browser/components/loop/test/xpcshell/test_loopservice_dnd.js
browser/components/loop/test/xpcshell/test_loopservice_notification.js
browser/components/loop/test/xpcshell/test_loopservice_registration.js
browser/components/loop/test/xpcshell/test_loopservice_restart.js
browser/components/loop/test/xpcshell/test_loopservice_token_invalid.js
browser/components/loop/test/xpcshell/test_loopservice_token_save.js
browser/components/loop/test/xpcshell/test_loopservice_token_send.js
browser/components/loop/test/xpcshell/test_loopservice_token_validation.js
browser/components/loop/test/xpcshell/test_rooms_getdata.js
--- a/browser/components/loop/LoopCalls.jsm
+++ b/browser/components/loop/LoopCalls.jsm
@@ -174,18 +174,23 @@ CallProgressSocket.prototype = {
 /**
  * Internal helper methods and state
  *
  * The registration is a two-part process. First we need to connect to
  * and register with the push server. Then we need to take the result of that
  * and register with the Loop server.
  */
 let LoopCallsInternal = {
-  callsData: {inUse: false},
-  _mocks: {webSocket: undefined},
+  callsData: {
+    inUse: false,
+  },
+
+  mocks: {
+    webSocket: undefined,
+  },
 
   /**
    * Callback from MozLoopPushHandler - A push notification has been received from
    * the server.
    *
    * @param {String} version The version information from the server.
    */
   onNotification: function(version, channelID) {
@@ -303,17 +308,19 @@ let LoopCallsInternal = {
    * @param {callData} Must contain the progressURL, callId and websocketToken
    *                   returned by the LoopService.
    */
   _returnBusy: function(callData) {
     let callProgress = new CallProgressSocket(
       callData.progressURL,
       callData.callId,
       callData.websocketToken);
-    callProgress._websocket = this._mocks.webSocket;
+    if (this.mocks.webSocket) {
+      callProgress._websocket = this.mocks.webSocket;
+    }
     // This instance of CallProgressSocket should stay alive until the underlying
     // websocket is closed since it is passed to the websocket as the nsIWebSocketListener.
     callProgress.connect(() => {callProgress.sendBusy();});
   }
 };
 Object.freeze(LoopCallsInternal);
 
 /**
--- a/browser/components/loop/MozLoopService.jsm
+++ b/browser/components/loop/MozLoopService.jsm
@@ -104,34 +104,38 @@ function getJSONPref(aName) {
   let value = Services.prefs.getCharPref(aName);
   return !!value ? JSON.parse(value) : null;
 }
 
 // The current deferred for the registration process. This is set if in progress
 // or the registration was successful. This is null if a registration attempt was
 // unsuccessful.
 let gRegisteredDeferred = null;
-let gPushHandler = null;
 let gHawkClient = null;
 let gLocalizedStrings = null;
 let gInitializeTimer = null;
 let gFxAEnabled = true;
 let gFxAOAuthClientPromise = null;
 let gFxAOAuthClient = null;
 let gErrors = new Map();
 
 /**
  * Internal helper methods and state
  *
  * The registration is a two-part process. First we need to connect to
  * and register with the push server. Then we need to take the result of that
  * and register with the Loop server.
  */
 let MozLoopServiceInternal = {
-  _mocks: {webSocket: undefined},
+  mocks: {
+    pushHandler: undefined,
+    webSocket: undefined,
+  },
+
+  get pushHandler() this.mocks.pushHandler || MozLoopPushHandler,
 
   // The uri of the Loop server.
   get loopServerUri() Services.prefs.getCharPref("loop.server"),
 
   /**
    * The initial delay for push registration. This ensures we don't start
    * kicking off straight after browser startup, just a few seconds later.
    */
@@ -302,71 +306,65 @@ let MozLoopServiceInternal = {
   get errors() {
     return gErrors;
   },
 
   /**
    * Starts registration of Loop with the push server, and then will register
    * with the Loop server. It will return early if already registered.
    *
-   * @param {Object} mockPushHandler Optional, test-only mock push handler. Used
-   *                                 to allow mocking of the MozLoopPushHandler.
-   * @param {Object} mockWebSocket Optional, test-only mock webSocket. To be passed
-   *                               through to MozLoopPushHandler.
    * @returns {Promise} a promise that is resolved with no params on completion, or
    *          rejected with an error code or string.
    */
-  promiseRegisteredWithServers: function(mockPushHandler, mockWebSocket) {
+  promiseRegisteredWithServers: function() {
     if (gRegisteredDeferred) {
       return gRegisteredDeferred.promise;
     }
 
-    this._mocks.webSocket = mockWebSocket;
-    this._mocks.pushHandler = mockPushHandler;
-
     // Wrap push notification registration call-back in a Promise.
     let registerForNotification = function(channelID, onNotification) {
       return new Promise((resolve, reject) => {
         let onRegistered = (error, pushUrl) => {
           if (error) {
             reject(Error(error));
           } else {
             resolve(pushUrl);
           }
         };
-        gPushHandler.register(channelID, onRegistered, onNotification);
+        MozLoopServiceInternal.pushHandler.register(channelID, onRegistered, onNotification);
       });
     };
 
     gRegisteredDeferred = Promise.defer();
     // We grab the promise early in case .initialize or its results sets
     // it back to null on error.
     let result = gRegisteredDeferred.promise;
 
-    gPushHandler = mockPushHandler || MozLoopPushHandler;
-    let options = mockWebSocket ? {mockWebSocket: mockWebSocket} : {};
-    gPushHandler.initialize(options);
+    let options = this.mocks.webSocket ? { mockWebSocket: this.mocks.webSocket } : {};
+    this.pushHandler.initialize(options);
 
     let callsRegGuest = registerForNotification(MozLoopService.channelIDs.callsGuest,
                                                 LoopCalls.onNotification);
- 
+
     let roomsRegGuest = registerForNotification(MozLoopService.channelIDs.roomsGuest,
                                                 roomsPushNotification);
- 
+
     let callsRegFxA = registerForNotification(MozLoopService.channelIDs.callsFxA,
                                               LoopCalls.onNotification);
- 
+
     let roomsRegFxA = registerForNotification(MozLoopService.channelIDs.roomsFxA,
                                               roomsPushNotification);
 
     Promise.all([callsRegGuest, roomsRegGuest, callsRegFxA, roomsRegFxA])
     .then((pushUrls) => {
-      return this.registerWithLoopServer(LOOP_SESSION_TYPE.GUEST,
-                                         {calls: pushUrls[0], rooms: pushUrls[1]}) })
-    .then(() => {
+      return this.registerWithLoopServer(LOOP_SESSION_TYPE.GUEST,{
+        calls: pushUrls[0],
+        rooms: pushUrls[1],
+      });
+    }).then(() => {
       // storeSessionToken could have rejected and nulled the promise if the token was malformed.
       if (!gRegisteredDeferred) {
         return;
       }
       gRegisteredDeferred.resolve("registered to guest status");
       // No need to clear the promise here, everything was good, so we don't need
       // to re-register.
     }, error => {
@@ -868,35 +866,35 @@ let MozLoopServiceInternal = {
       deferred.resolve(result);
     } else {
       deferred.reject("Invalid token data");
     }
   },
 };
 Object.freeze(MozLoopServiceInternal);
 
-let gInitializeTimerFunc = (deferredInitialization, mockPushHandler, mockWebSocket) => {
+let gInitializeTimerFunc = (deferredInitialization) => {
   // Kick off the push notification service into registering after a timeout.
   // This ensures we're not doing too much straight after the browser's finished
   // starting up.
   gInitializeTimer = Cc["@mozilla.org/timer;1"].createInstance(Ci.nsITimer);
   gInitializeTimer.initWithCallback(Task.async(function* initializationCallback() {
-    yield MozLoopService.register(mockPushHandler, mockWebSocket).then(Task.async(function*() {
+    yield MozLoopService.register().then(Task.async(function*() {
       if (!MozLoopServiceInternal.fxAOAuthTokenData) {
         log.debug("MozLoopService: Initialized without an already logged-in account");
         deferredInitialization.resolve("initialized to guest status");
         return;
       }
 
       log.debug("MozLoopService: Initializing with already logged-in account");
       let registeredPromise =
             MozLoopServiceInternal.registerWithLoopServer(
               LOOP_SESSION_TYPE.FXA, {
-                calls: gPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA],
-                rooms: gPushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA]
+                calls: MozLoopServiceInternal.pushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA],
+                rooms: MozLoopServiceInternal.pushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA]
               });
       registeredPromise.then(() => {
         deferredInitialization.resolve("initialized to logged-in status");
       }, error => {
         log.debug("MozLoopService: error logging in using cached auth token");
         MozLoopServiceInternal.setError("login", error);
         deferredInitialization.reject("error logging in using cached auth token");
       });
@@ -931,17 +929,17 @@ this.MozLoopService = {
   },
 
   /**
    * Initialized the loop service, and starts registration with the
    * push and loop servers.
    *
    * @return {Promise}
    */
-  initialize: Task.async(function*(mockPushHandler, mockWebSocket) {
+  initialize: Task.async(function*() {
     // Do this here, rather than immediately after definition, so that we can
     // stub out API functions for unit testing
     Object.freeze(this);
 
     // Clear the old throttling mechanism.
     Services.prefs.clearUserPref("loop.throttled");
 
     // Don't do anything if loop is not enabled.
@@ -960,17 +958,17 @@ this.MozLoopService = {
     // If expiresTime is not in the future and the user hasn't
     // previously authenticated then skip registration.
     if (!MozLoopServiceInternal.urlExpiryTimeIsInFuture() &&
         !MozLoopServiceInternal.fxAOAuthTokenData) {
       return Promise.resolve("registration not needed");
     }
 
     let deferredInitialization = Promise.defer();
-    gInitializeTimerFunc(deferredInitialization, mockPushHandler, mockWebSocket);
+    gInitializeTimerFunc(deferredInitialization);
 
     return deferredInitialization.promise.catch(error => {
       if (typeof(error) == "object") {
         // This never gets cleared since there is no UI to recover. Only restarting will work.
         MozLoopServiceInternal.setError("initialization", error);
       }
       throw error;
     });
@@ -1082,33 +1080,31 @@ this.MozLoopService = {
                                              Services.tm.mainThread);
   },
 
 
   /**
    * Starts registration of Loop with the push server, and then will register
    * with the Loop server. It will return early if already registered.
    *
-   * @param {Object} mockPushHandler Optional, test-only mock push handler. Used
-   *                                 to allow mocking of the MozLoopPushHandler.
    * @returns {Promise} a promise that is resolved with no params on completion, or
    *          rejected with an error code or string.
    */
-  register: function(mockPushHandler, mockWebSocket) {
+  register: function() {
     log.debug("registering");
     // Don't do anything if loop is not enabled.
     if (!Services.prefs.getBoolPref("loop.enabled")) {
       throw new Error("Loop is not enabled");
     }
 
     if (Services.prefs.getBoolPref("loop.throttled2")) {
       throw new Error("Loop is disabled by the soft-start mechanism");
     }
 
-    return MozLoopServiceInternal.promiseRegisteredWithServers(mockPushHandler, mockWebSocket);
+    return MozLoopServiceInternal.promiseRegisteredWithServers();
   },
 
   /**
    * Used to note a call url expiry time. If the time is later than the current
    * latest expiry time, then the stored expiry time is increased. For times
    * sooner, this function is a no-op; this ensures we always have the latest
    * expiry time for a url.
    *
@@ -1295,18 +1291,18 @@ this.MozLoopService = {
     }
     return MozLoopServiceInternal.promiseFxAOAuthAuthorization().then(response => {
       return MozLoopServiceInternal.promiseFxAOAuthToken(response.code, response.state);
     }).then(tokenData => {
       MozLoopServiceInternal.fxAOAuthTokenData = tokenData;
       return tokenData;
     }).then(tokenData => {
       return gRegisteredDeferred.promise.then(Task.async(function*() {
-        let callsUrl = gPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA],
-            roomsUrl = gPushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA];
+        let callsUrl = MozLoopServiceInternal.pushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA],
+            roomsUrl = MozLoopServiceInternal.pushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA];
         if (callsUrl && roomsUrl) {
           yield MozLoopServiceInternal.registerWithLoopServer(
             LOOP_SESSION_TYPE.FXA, {calls: callsUrl, rooms: roomsUrl});
         } else {
           throw new Error("No pushUrls for FxA registration");
         }
         MozLoopServiceInternal.clearError("login");
         MozLoopServiceInternal.clearError("profile");
@@ -1342,33 +1338,29 @@ this.MozLoopService = {
    * Logs the user out from FxA.
    *
    * Gracefully handles if the user is already logged out.
    *
    * @return {Promise} that resolves when the FxA logout flow is complete.
    */
   logOutFromFxA: Task.async(function*() {
     log.debug("logOutFromFxA");
-    let callsPushUrl, roomsPushUrl;
-    if (gPushHandler) {
-      callsPushUrl = gPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA];
-      roomsPushUrl = gPushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA];
-    }
+    let pushHandler = MozLoopServiceInternal.pushHandler;
+    let callsPushUrl = pushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA];
+    let roomsPushUrl = pushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA];
     try {
       if (callsPushUrl) {
-        yield MozLoopServiceInternal.unregisterFromLoopServer(
-          LOOP_SESSION_TYPE.FXA, callsPushUrl);
+        yield MozLoopServiceInternal.unregisterFromLoopServer(LOOP_SESSION_TYPE.FXA, callsPushUrl);
       }
       if (roomsPushUrl) {
-        yield MozLoopServiceInternal.unregisterFromLoopServer(
-          LOOP_SESSION_TYPE.FXA, roomsPushUrl);
+        yield MozLoopServiceInternal.unregisterFromLoopServer(LOOP_SESSION_TYPE.FXA, roomsPushUrl);
       }
-    }
-    catch (error) {throw error}
-    finally {
+    } catch (error) {
+      throw error;
+    } finally {
       MozLoopServiceInternal.clearSessionToken(LOOP_SESSION_TYPE.FXA);
     }
 
     MozLoopServiceInternal.fxAOAuthTokenData = null;
     MozLoopServiceInternal.fxAOAuthProfile = null;
 
     // Reset the client since the initial promiseFxAOAuthParameters() call is
     // what creates a new session.
--- a/browser/components/loop/test/mochitest/browser_fxa_login.js
+++ b/browser/components/loop/test/mochitest/browser_fxa_login.js
@@ -35,21 +35,23 @@ function* checkFxA401() {
      getLoopString("retry_button"),
      "Check error bar details button");
   loopPanel.hidePopup();
 }
 
 add_task(function* setup() {
   Services.prefs.setCharPref("loop.server", BASE_URL);
   Services.prefs.setCharPref("services.push.serverURL", "ws://localhost/");
+  MozLoopServiceInternal.mocks.pushHandler = mockPushHandler;
   registerCleanupFunction(function* () {
     info("cleanup time");
     yield promiseDeletedOAuthParams(BASE_URL);
     Services.prefs.clearUserPref("loop.server");
     Services.prefs.clearUserPref("services.push.serverURL");
+    MozLoopServiceInternal.mocks.pushHandler = undefined;
     yield resetFxA();
     Services.prefs.clearUserPref(MozLoopServiceInternal.getSessionTokenPrefName(LOOP_SESSION_TYPE.GUEST));
   });
 });
 
 add_task(function* checkOAuthParams() {
   let params = {
     client_id: "client_id",
@@ -246,17 +248,17 @@ add_task(function* basicAuthorizationAnd
     state: "state",
   };
   yield promiseOAuthParamsSetup(BASE_URL, params);
 
   info("registering");
   mockPushHandler.registrationPushURL = "https://localhost/pushUrl/guest";
   // Notification observed due to the error being cleared upon successful registration.
   let statusChangedPromise = promiseObserverNotified("loop-status-changed");
-  yield MozLoopService.register(mockPushHandler);
+  yield MozLoopService.register();
   yield statusChangedPromise;
 
   // Normally the same pushUrl would be registered but we change it in the test
   // to be able to check for success on the second registration.
   mockPushHandler.registeredChannels[MozLoopService.channelIDs.callsFxA] = "https://localhost/pushUrl/fxa-calls"; 
   mockPushHandler.registeredChannels[MozLoopService.channelIDs.roomsFxA] = "https://localhost/pushUrl/fxa-rooms"; 
 
   statusChangedPromise = promiseObserverNotified("loop-status-changed");
@@ -311,17 +313,17 @@ add_task(function* loginWithParams401() 
     client_id: "client_id",
     content_uri: BASE_URL + "/content",
     oauth_uri: BASE_URL + "/oauth",
     profile_uri: BASE_URL + "/profile",
     state: "state",
     test_error: "params_401",
   };
   yield promiseOAuthParamsSetup(BASE_URL, params);
-  yield MozLoopService.register(mockPushHandler);
+  yield MozLoopService.register();
 
   let loginPromise = MozLoopService.logInToFxA();
   yield loginPromise.then(tokenData => {
     ok(false, "Promise should have rejected");
   },
   error => {
     ise(error.code, 401, "Check error code");
     checkFxAOAuthTokenData(null);
--- a/browser/components/loop/test/xpcshell/head.js
+++ b/browser/components/loop/test/xpcshell/head.js
@@ -32,18 +32,21 @@ function setupFakeLoopServer() {
   loopServer = new HttpServer();
   loopServer.start(-1);
 
   Services.prefs.setCharPref("services.push.serverURL", kServerPushUrl);
 
   Services.prefs.setCharPref("loop.server",
     "http://localhost:" + loopServer.identity.primaryPort);
 
+  MozLoopServiceInternal.mocks.pushHandler = mockPushHandler;
+
   do_register_cleanup(function() {
     loopServer.stop(function() {});
+    MozLoopServiceInternal.mocks.pushHandler = undefined;
   });
 }
 
 function waitForCondition(aConditionFn, aMaxTries=50, aCheckInterval=100) {
   function tryAgain() {
     function tryNow() {
       tries++;
       if (aConditionFn()) {
--- a/browser/components/loop/test/xpcshell/test_loopservice_busy.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_busy.js
@@ -14,27 +14,22 @@ const secondCallId = 1001100101;
 
 let msgHandler = function(msg) {
   if (msg.messageType &&
       msg.messageType === "action" &&
       msg.event === "terminate" &&
       msg.reason === "busy") {
     actionReceived = true;
   }
-}
-
-let mockWebSocket = new MockWebSocketChannel({defaultMsgHandler: msgHandler});
-LoopCallsInternal._mocks.webSocket = mockWebSocket;
-
-Services.io.offline = false;
+};
 
 add_test(function test_busy_2guest_calls() {
   actionReceived = false;
 
-  MozLoopService.register(mockPushHandler, mockWebSocket).then(() => {
+  MozLoopService.register().then(() => {
     let opened = 0;
     Chat.open = function() {
       opened++;
     };
 
     mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
 
     waitForCondition(() => {return actionReceived && opened > 0}).then(() => {
@@ -47,17 +42,17 @@ add_test(function test_busy_2guest_calls
     });
 
   });
 });
 
 add_test(function test_busy_1fxa_1guest_calls() {
   actionReceived = false;
 
-  MozLoopService.register(mockPushHandler, mockWebSocket).then(() => {
+  MozLoopService.register().then(() => {
     let opened = 0;
     Chat.open = function() {
       opened++;
     };
 
     mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA);
     mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
 
@@ -71,17 +66,17 @@ add_test(function test_busy_1fxa_1guest_
     });
 
   });
 });
 
 add_test(function test_busy_2fxa_calls() {
   actionReceived = false;
 
-  MozLoopService.register(mockPushHandler, mockWebSocket).then(() => {
+  MozLoopService.register().then(() => {
     let opened = 0;
     Chat.open = function() {
       opened++;
     };
 
     mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA);
 
     waitForCondition(() => {return actionReceived && opened > 0}).then(() => {
@@ -94,17 +89,17 @@ add_test(function test_busy_2fxa_calls()
     });
 
   });
 });
 
 add_test(function test_busy_1guest_1fxa_calls() {
   actionReceived = false;
 
-  MozLoopService.register(mockPushHandler, mockWebSocket).then(() => {
+  MozLoopService.register().then(() => {
     let opened = 0;
     Chat.open = function() {
       opened++;
     };
 
     mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
     mockPushHandler.notify(1, MozLoopService.channelIDs.callsFxA);
 
@@ -115,25 +110,29 @@ add_test(function test_busy_1guest_1fxa_
       run_next_test();
     }, () => {
       do_throw("should have opened a chat window for first call and rejected second call");
     });
 
   });
 });
 
-function run_test()
-{
+function run_test() {
   setupFakeLoopServer();
 
   // Setup fake login state so we get FxA requests.
   const MozLoopServiceInternal = Cu.import("resource:///modules/loop/MozLoopService.jsm", {}).MozLoopServiceInternal;
   MozLoopServiceInternal.fxAOAuthTokenData = {token_type:"bearer",access_token:"1bad3e44b12f77a88fe09f016f6a37c42e40f974bc7a8b432bb0d2f0e37e1752",scope:"profile"};
   MozLoopServiceInternal.fxAOAuthProfile = {email: "test@example.com", uid: "abcd1234"};
 
+  let mockWebSocket = new MockWebSocketChannel({defaultMsgHandler: msgHandler});
+  LoopCallsInternal.mocks.webSocket = mockWebSocket;
+
+  Services.io.offline = false;
+
   // For each notification received from the PushServer, MozLoopService will first query
   // for any pending calls on the FxA hawk session and then again using the guest session.
   // A pair of response objects in the callsResponses array will be consumed for each
   // notification. The even calls object is for the FxA session, the odd the Guest session.
 
   let callsRespCount = 0;
   let callsResponses = [
     {calls: [{callId: firstCallId,
@@ -173,13 +172,13 @@ function run_test()
     Chat.open = openChatOrig;
 
     // Revert fake login state
     MozLoopServiceInternal.fxAOAuthTokenData = null;
 
     // clear test pref
     Services.prefs.clearUserPref("loop.seenToS");
 
-    LoopCallsInternal._mocks.webSocket = undefined;
+    LoopCallsInternal.mocks.webSocket = undefined;
   });
 
   run_next_test();
 }
--- a/browser/components/loop/test/xpcshell/test_loopservice_dnd.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_dnd.js
@@ -26,17 +26,17 @@ add_test(function test_set_do_not_distur
   do_check_true(Services.prefs.getBoolPref("loop.do_not_disturb"));
 
   run_next_test();
 });
 
 add_test(function test_do_not_disturb_disabled_should_open_chat_window() {
   MozLoopService.doNotDisturb = false;
 
-  MozLoopService.register(mockPushHandler).then(() => {
+  MozLoopService.register().then(() => {
     let opened = false;
     Chat.open = function() {
       opened = true;
     };
 
     mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
 
     waitForCondition(function() opened).then(() => {
@@ -59,18 +59,17 @@ add_test(function test_do_not_disturb_en
   mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
 
   do_timeout(500, function() {
     do_check_false(opened, "should not open a chat window");
     run_next_test();
   });
 });
 
-function run_test()
-{
+function run_test() {
   setupFakeLoopServer();
 
   loopServer.registerPathHandler("/registration", (request, response) => {
     response.setStatusLine(null, 200, "OK");
     response.processAsync();
     response.finish();
   });
   loopServer.registerPathHandler("/calls", (request, response) => {
--- a/browser/components/loop/test/xpcshell/test_loopservice_notification.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_notification.js
@@ -5,17 +5,17 @@
 XPCOMUtils.defineLazyModuleGetter(this, "Chat",
                                   "resource:///modules/Chat.jsm");
 
 let openChatOrig = Chat.open;
 
 add_test(function test_openChatWindow_on_notification() {
   Services.prefs.setCharPref("loop.seenToS", "unseen");
 
-  MozLoopService.register(mockPushHandler).then(() => {
+  MozLoopService.register().then(() => {
     let opened = false;
     Chat.open = function() {
       opened = true;
     };
 
     mockPushHandler.notify(1, MozLoopService.channelIDs.callsGuest);
 
     waitForCondition(function() opened).then(() => {
@@ -27,18 +27,17 @@ add_test(function test_openChatWindow_on
       run_next_test();
     }, () => {
       do_throw("should have opened a chat window");
     });
 
   });
 });
 
-function run_test()
-{
+function run_test() {
   setupFakeLoopServer();
 
   loopServer.registerPathHandler("/registration", (request, response) => {
     response.setStatusLine(null, 200, "OK");
     response.processAsync();
     response.finish();
   });
   loopServer.registerPathHandler("/calls", (request, response) => {
--- a/browser/components/loop/test/xpcshell/test_loopservice_registration.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_registration.js
@@ -12,17 +12,17 @@ Cu.import("resource://services-common/ut
 
 /**
  * Test that the websocket can be fully registered, and that a Loop server
  * failure is reported.
  */
 add_test(function test_register_websocket_success_loop_server_fail() {
   mockPushHandler.registrationResult = "404";
 
-  MozLoopService.register(mockPushHandler).then(() => {
+  MozLoopService.register().then(() => {
     do_throw("should not succeed when loop server registration fails");
   }, (err) => {
     // 404 is an expected failure indicated by the lack of route being set
     // up on the Loop server mock. This is added in the next test.
     Assert.equal(err.message, "404", "Expected no errors in websocket registration");
 
     run_next_test();
   });
@@ -44,25 +44,24 @@ add_test(function test_register_success(
                  "Should send correct calls push url");
     Assert.equal(data.simplePushURLs.rooms, kEndPointUrl,
                  "Should send correct rooms push url");
 
     response.setStatusLine(null, 200, "OK");
     response.processAsync();
     response.finish();
   });
-  MozLoopService.register(mockPushHandler).then(() => {
+  MozLoopService.register().then(() => {
     run_next_test();
   }, err => {
     do_throw("shouldn't error on a successful request");
   });
 });
 
-function run_test()
-{
+function run_test() {
   setupFakeLoopServer();
 
   do_register_cleanup(function() {
     Services.prefs.clearUserPref("loop.hawk-session-token");
   });
 
   run_next_test();
 }
--- a/browser/components/loop/test/xpcshell/test_loopservice_restart.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_restart.js
@@ -21,33 +21,33 @@ const LOOP_INITIAL_DELAY_PREF = "loop.in
  */
 
 add_task(function test_initialize_with_expired_urls_and_no_auth_token() {
   // Set time to be 2 seconds in the past.
   var nowSeconds = Date.now() / 1000;
   Services.prefs.setIntPref(LOOP_URL_EXPIRY_PREF, nowSeconds - 2);
   Services.prefs.clearUserPref(LOOP_FXA_TOKEN_PREF);
 
-  yield MozLoopService.initialize(mockPushHandler).then((msg) => {
+  yield MozLoopService.initialize().then((msg) => {
     Assert.equal(msg, "registration not needed", "Initialize should not register when the " +
                                                  "URLs are expired and there are no auth tokens");
   }, (error) => {
     Assert.ok(false, error, "should have resolved the promise that initialize returned");
   });
 });
 
 add_task(function test_initialize_with_urls_and_no_auth_token() {
   Services.prefs.setIntPref(LOOP_URL_EXPIRY_PREF, Date.now() / 1000 + 10);
   Services.prefs.clearUserPref(LOOP_FXA_TOKEN_PREF);
 
   loopServer.registerPathHandler("/registration", (request, response) => {
     response.setStatusLine(null, 200, "OK");
   });
 
-  yield MozLoopService.initialize(mockPushHandler).then((msg) => {
+  yield MozLoopService.initialize().then((msg) => {
     Assert.equal(msg, "initialized to guest status", "Initialize should register as a " +
                                                      "guest when no auth tokens but expired URLs");
   }, (error) => {
     Assert.ok(false, error, "should have resolved the promise that initialize returned");
   });
 });
 
 add_task(function test_initialize_with_invalid_fxa_token() {
@@ -61,51 +61,52 @@ add_task(function test_initialize_with_i
     response.write(JSON.stringify({
       code: 401,
       errno: 110,
       error: "Unauthorized",
       message: "Unknown credentials",
     }));
   });
 
-  yield MozLoopService.initialize(mockPushHandler).then(() => {
+  yield MozLoopService.initialize().then(() => {
     Assert.ok(false, "Initializing with an invalid token should reject the promise");
   },
   (error) => {
-    let pushHandler = Cu.import("resource:///modules/loop/MozLoopService.jsm", {}).gPushHandler;
-    Assert.equal(pushHandler.pushUrl, kEndPointUrl, "Push URL should match");
+    Assert.equal(MozLoopServiceInternal.pushHandler.pushUrl, kEndPointUrl, "Push URL should match");
     Assert.equal(Services.prefs.getCharPref(LOOP_FXA_TOKEN_PREF), "",
                  "FXA pref should be cleared if token was invalid");
     Assert.equal(Services.prefs.getCharPref(LOOP_FXA_PROFILE_PREF), "",
                  "FXA profile pref should be cleared if token was invalid");
   });
 });
 
 add_task(function test_initialize_with_fxa_token() {
   Services.prefs.setCharPref(LOOP_FXA_PROFILE_PREF, FAKE_FXA_PROFILE);
   Services.prefs.setCharPref(LOOP_FXA_TOKEN_PREF, FAKE_FXA_TOKEN_DATA);
   loopServer.registerPathHandler("/registration", (request, response) => {
     response.setStatusLine(null, 200, "OK");
   });
 
-  yield MozLoopService.initialize(mockPushHandler).then(() => {
+  yield MozLoopService.initialize().then(() => {
     Assert.equal(Services.prefs.getCharPref(LOOP_FXA_TOKEN_PREF), FAKE_FXA_TOKEN_DATA,
                  "FXA pref should still be set after initialization");
     Assert.equal(Services.prefs.getCharPref(LOOP_FXA_PROFILE_PREF), FAKE_FXA_PROFILE,
                  "FXA profile should still be set after initialization");
   });
 });
 
 function run_test() {
   setupFakeLoopServer();
   // Note, this is just used to speed up the test.
   Services.prefs.setIntPref(LOOP_INITIAL_DELAY_PREF, 0);
+  MozLoopServiceInternal.mocks.pushHandler = mockPushHandler;
   mockPushHandler.pushUrl = kEndPointUrl;
 
   do_register_cleanup(function() {
+    MozLoopServiceInternal.mocks.pushHandler = undefined;
     Services.prefs.clearUserPref(LOOP_INITIAL_DELAY_PREF);
     Services.prefs.clearUserPref(LOOP_FXA_TOKEN_PREF);
     Services.prefs.clearUserPref(LOOP_FXA_PROFILE_PREF);
     Services.prefs.clearUserPref(LOOP_URL_EXPIRY_PREF);
   });
 
   run_next_test();
 };
--- a/browser/components/loop/test/xpcshell/test_loopservice_token_invalid.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_token_invalid.js
@@ -26,30 +26,29 @@ add_test(function test_registration_inva
       Assert.equal(Services.prefs.prefHasUserValue(LOOP_HAWK_PREF), false);
       response.setStatusLine(null, 200, "OK");
       response.setHeader("Hawk-Session-Token", fakeSessionToken2, false);
     }
     response.processAsync();
     response.finish();
   });
 
-  MozLoopService.register(mockPushHandler).then(() => {
+  MozLoopService.register().then(() => {
     // Due to the way the time stamp checking code works in hawkclient, we expect a couple
     // of authorization requests before we reset the token.
     Assert.equal(authorizationAttempts, 2);
     Assert.equal(Services.prefs.getCharPref(LOOP_HAWK_PREF), fakeSessionToken2);
     run_next_test();
   }, err => {
     do_throw("shouldn't be a failure result: " + err);
   });
 });
 
 
-function run_test()
-{
+function run_test() {
   setupFakeLoopServer();
 
   do_register_cleanup(function() {
     Services.prefs.clearUserPref("loop.hawk-session-token");
   });
 
   run_next_test();
 }
--- a/browser/components/loop/test/xpcshell/test_loopservice_token_save.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_token_save.js
@@ -11,33 +11,32 @@ add_test(function test_registration_retu
 
   loopServer.registerPathHandler("/registration", (request, response) => {
     response.setStatusLine(null, 200, "OK");
     response.setHeader("Hawk-Session-Token", fakeSessionToken, false);
     response.processAsync();
     response.finish();
   });
 
-  MozLoopService.register(mockPushHandler).then(() => {
+  MozLoopService.register().then(() => {
     var hawkSessionPref;
     try {
       hawkSessionPref = Services.prefs.getCharPref("loop.hawk-session-token");
     } catch (ex) {
     }
     Assert.equal(hawkSessionPref, fakeSessionToken, "Should store" +
       " Hawk-Session-Token header contents in loop.hawk-session-token pref");
 
     run_next_test();
   }, err => {
     do_throw("shouldn't error on a successful request");
   });
 });
 
-function run_test()
-{
+function run_test() {
   setupFakeLoopServer();
 
   do_register_cleanup(function() {
     Services.prefs.clearUserPref("loop.hawk-session-token");
   });
 
   run_next_test();
 }
--- a/browser/components/loop/test/xpcshell/test_loopservice_token_send.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_token_send.js
@@ -19,26 +19,25 @@ add_test(function test_registration_uses
     Assert.notEqual(header.contains("hash="), -1, "Should contain a hash");
     Assert.notEqual(header.contains("mac="), -1, "Should contain a mac");
 
     response.setStatusLine(null, 200, "OK");
     response.processAsync();
     response.finish();
   });
 
-  MozLoopService.register(mockPushHandler).then(() => {
+  MozLoopService.register().then(() => {
     run_next_test();
   }, err => {
     do_throw("shouldn't error on a succesful request");
   });
 });
 
 
-function run_test()
-{
+function run_test() {
   setupFakeLoopServer();
 
   do_register_cleanup(function() {
     Services.prefs.clearUserPref("loop.hawk-session-token");
   });
 
   run_next_test();
 }
--- a/browser/components/loop/test/xpcshell/test_loopservice_token_validation.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_token_validation.js
@@ -11,17 +11,17 @@ add_test(function test_registration_hand
 
   loopServer.registerPathHandler("/registration", (request, response) => {
     response.setStatusLine(null, 200, "OK");
     response.setHeader("Hawk-Session-Token", wrongSizeToken, false);
     response.processAsync();
     response.finish();
   });
 
-  MozLoopService.register(mockPushHandler).then(() => {
+  MozLoopService.register().then(() => {
     do_throw("should not succeed with a bogus token");
   }, err => {
 
     Assert.equal(err, "session-token-wrong-size", "Should cause an error to be" +
       " called back if the session-token is not 64 characters long");
 
     // for some reason, Assert.throw is misbehaving, so....
     var ex;
@@ -31,19 +31,17 @@ add_test(function test_registration_hand
       ex = e;
     }
     Assert.notEqual(ex, undefined, "Should not set a loop.hawk-session-token pref");
 
     run_next_test();
   });
 });
 
-function run_test()
-{
+function run_test() {
   setupFakeLoopServer();
 
   do_register_cleanup(function() {
     Services.prefs.clearUserPref("loop.hawk-session-token");
   });
 
   run_next_test();
-
 }
--- a/browser/components/loop/test/xpcshell/test_rooms_getdata.js
+++ b/browser/components/loop/test/xpcshell/test_rooms_getdata.js
@@ -78,17 +78,17 @@ add_test(function test_getAllRooms() {
   loopServer.registerPathHandler("/rooms/QzBbvGmIZWU", (request, response) => {
     returnRoomDetails(response, "Second Room Name");
   });
 
   loopServer.registerPathHandler("/rooms/3jKS_Els9IU", (request, response) => {
     returnRoomDetails(response, "Third Room Name");
   });
 
-  MozLoopService.register(mockPushHandler).then(() => {
+  MozLoopService.register().then(() => {
 
     LoopRooms.getAll((error, rooms) => {
       do_check_false(error);
       do_check_true(rooms);
       do_check_eq(rooms.length, 3);
       do_check_eq(rooms[0].roomName, "First Room Name");
       do_check_eq(rooms[1].roomName, "Second Room Name");
       do_check_eq(rooms[2].roomName, "Third Room Name");
@@ -108,18 +108,17 @@ add_test(function test_getAllRooms() {
         do_check_true(hasTheseProps(room, roomData));
 
         run_next_test();
       });
     });
   });
 });
 
-function run_test()
-{
+function run_test() {
   setupFakeLoopServer();
   mockPushHandler.registrationPushURL = kEndPointUrl;
 
   loopServer.registerPathHandler("/registration", (request, response) => {
     response.setStatusLine(null, 200, "OK");
     response.processAsync();
     response.finish();
   });