Backed out 2 changesets (bug 1164821, bug 1152764) for xpcshell failures.
authorRyan VanderMeulen <ryanvm@gmail.com>
Mon, 25 May 2015 15:01:38 -0400
changeset 274772 3caa82a8604dd5c3b21113b6f56e2f6380eb9473
parent 274771 0431d77fe985f2ad318d61a878f6bc8b254d370a
child 274773 9cf746bab00305da76a5b8b3cfd988a10d211b09
push id863
push userraliiev@mozilla.com
push dateMon, 03 Aug 2015 13:22:43 +0000
treeherdermozilla-release@f6321b14228d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
bugs1164821, 1152764
milestone40.0a2
backs outfde399943f32066ae8d3a8d7fbec5f24bc2c4d27
a27ca9fb0b51eb7cd92e345f773ccd7c7a5d405d
Backed out 2 changesets (bug 1164821, bug 1152764) for xpcshell failures. Backed out changeset fde399943f32 (bug 1164821) Backed out changeset a27ca9fb0b51 (bug 1152764)
browser/components/loop/modules/LoopRooms.jsm
browser/components/loop/modules/MozLoopService.jsm
browser/components/loop/test/xpcshell/head.js
browser/components/loop/test/xpcshell/test_looprooms.js
browser/components/loop/test/xpcshell/test_looprooms_encryption_in_fxa.js
browser/components/loop/test/xpcshell/test_looprooms_upgrade_to_encryption.js
browser/components/loop/test/xpcshell/test_loopservice_encryptionkey.js
browser/components/loop/test/xpcshell/xpcshell.ini
--- a/browser/components/loop/modules/LoopRooms.jsm
+++ b/browser/components/loop/modules/LoopRooms.jsm
@@ -3,17 +3,16 @@
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 "use strict";
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
-Cu.import("resource://gre/modules/Timer.jsm");
 
 const {MozLoopService, LOOP_SESSION_TYPE} = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
 XPCOMUtils.defineLazyModuleGetter(this, "Promise",
                                   "resource://gre/modules/Promise.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
                                   "resource://services-common/utils.js");
 XPCOMUtils.defineLazyGetter(this, "eventEmitter", function() {
   const {EventEmitter} = Cu.import("resource://gre/modules/devtools/event-emitter.js", {});
@@ -24,32 +23,23 @@ XPCOMUtils.defineLazyGetter(this, "gLoop
 });
 
 XPCOMUtils.defineLazyModuleGetter(this, "LoopRoomsCache",
   "resource:///modules/loop/LoopRoomsCache.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "loopUtils",
   "resource:///modules/loop/utils.js", "utils");
 XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto",
   "resource:///modules/loop/crypto.js", "LoopCrypto");
-XPCOMUtils.defineLazyModuleGetter(this, "ObjectUtils",
-  "resource://gre/modules/ObjectUtils.jsm");
 
 
 this.EXPORTED_SYMBOLS = ["LoopRooms", "roomsPushNotification"];
 
 // The maximum number of clients that we support currently.
 const CLIENT_MAX_SIZE = 2;
 
-// Wait at least 5 seconds before doing opportunistic encryption.
-const MIN_TIME_BEFORE_ENCRYPTION = 5 * 1000;
-// Wait at maximum of 30 minutes before doing opportunistic encryption.
-const MAX_TIME_BEFORE_ENCRYPTION = 30 * 60 * 1000;
-// Wait time between individual re-encryption cycles (1 second).
-const TIME_BETWEEN_ENCRYPTIONS = 1000;
-
 const roomsPushNotification = function(version, channelID) {
   return LoopRoomsInternal.onNotification(version, channelID);
 };
 
 // Since the LoopRoomsInternal.rooms map as defined below is a local cache of
 // room objects that are retrieved from the server, this is list may become out
 // of date. The Push server may notify us of this event, which will set the global
 // 'dirty' flag to TRUE.
@@ -123,33 +113,16 @@ const checkForParticipantsUpdate = funct
     if (!containsParticipant(updatedRoom, participant)) {
       eventEmitter.emit("left", room, participant);
       eventEmitter.emit("left:" + room.roomToken, participant);
     }
   }
 };
 
 /**
- * These are wrappers which can be overriden by tests to allow us to manually
- * handle the timeouts.
- */
-let timerHandlers = {
-  /**
-   * Wrapper for setTimeout.
-   *
-   * @param  {Function} callback The callback function.
-   * @param  {Number}   delay    The delay in milliseconds.
-   * @return {Number}            The timer identifier.
-   */
-  startTimer(callback, delay) {
-    return setTimeout(callback, delay);
-  }
-};
-
-/**
  * The Rooms class.
  *
  * Each method that is a member of this class requires the last argument to be a
  * callback Function. MozLoopAPI will cause things to break if this invariant is
  * violated. You'll notice this as well in the documentation for each method.
  */
 let LoopRoomsInternal = {
   /**
@@ -160,29 +133,16 @@ let LoopRoomsInternal = {
   get roomsCache() {
     if (!gRoomsCache) {
       gRoomsCache = new LoopRoomsCache();
     }
     return gRoomsCache;
   },
 
   /**
-   * @var {Object} encryptionQueue  This stores the list of rooms awaiting
-   *                                encryption and associated timers.
-   */
-  encryptionQueue: {
-    queue: [],
-    timer: null,
-    reset: function() {
-      this.queue = [];
-      this.timer = null;
-    }
-  },
-
-  /**
    * @var {String} sessionType The type of user session. May be 'FXA' or 'GUEST'.
    */
   get sessionType() {
     return MozLoopService.userProfile ? LOOP_SESSION_TYPE.FXA :
                                         LOOP_SESSION_TYPE.GUEST;
   },
 
   /**
@@ -196,74 +156,16 @@ let LoopRoomsInternal = {
         continue;
       }
       count += room.participants.length;
     }
     return count;
   },
 
   /**
-   * Processes the encryption queue. Takes the next item off the queue,
-   * restarts the timer if necessary.
-   *
-   * Although this is only called from a timer callback, it is an async function
-   * so that tests can call it and be deterministic.
-   */
-  processEncryptionQueue: Task.async(function* () {
-    let roomToken = this.encryptionQueue.queue.shift();
-
-    // Performed in sync fashion so that we don't queue a timer until it has
-    // completed, and to make it easier to run tests.
-    let roomData = this.rooms.get(roomToken);
-
-    if (roomData) {
-      try {
-        // Passing the empty object for roomData is enough for the room to be
-        // re-encrypted.
-        yield LoopRooms.promise("update", roomToken, {});
-      } catch (error) {
-        MozLoopService.log.error("Upgrade encryption of room failed", error);
-        // No need to remove the room from the list as that's done in the shift above.
-      }
-    }
-
-    if (this.encryptionQueue.queue.length) {
-      this.encryptionQueue.timer =
-        timerHandlers.startTimer(this.processEncryptionQueue.bind(this), TIME_BETWEEN_ENCRYPTIONS);
-    } else {
-      this.encryptionQueue.timer = null;
-    }
-  }),
-
-  /**
-   * Queues a room for encryption sometime in the future. This is done so as
-   * not to overload the server or the browser when we initially request the
-   * list of rooms.
-   *
-   * @param {String} roomToken The token for the room that needs encrypting.
-   */
-  queueForEncryption: function(roomToken) {
-    if (!this.encryptionQueue.queue.includes(roomToken)) {
-      this.encryptionQueue.queue.push(roomToken);
-    }
-
-    // Set up encryption to happen at a random time later. There's a minimum
-    // wait time - we don't need to do this straight away, so no need if the user
-    // is starting up. We then add a random factor on top of that. This is to
-    // try and avoid any potential with a set of clients being restarted at the
-    // same time and flooding the server.
-    if (!this.encryptionQueue.timer) {
-      let waitTime = (MAX_TIME_BEFORE_ENCRYPTION - MIN_TIME_BEFORE_ENCRYPTION) *
-        Math.random() + MIN_TIME_BEFORE_ENCRYPTION;
-      this.encryptionQueue.timer =
-        timerHandlers.startTimer(this.processEncryptionQueue.bind(this), waitTime);
-    }
-  },
-
-  /**
    * Gets or creates a room key for a room.
    *
    * It assumes that the room data is decrypted.
    *
    * @param {Object} roomData The roomData to get the key for.
    * @return {Promise} A promise that is resolved whith the room key.
    */
   promiseGetOrCreateRoomKey: Task.async(function* (roomData) {
@@ -307,32 +209,54 @@ let LoopRoomsInternal = {
    *
    * @param  {Object} roomData The room data to encrypt.
    * @return {Promise} A promise that is resolved with an object containing
    *                   two objects:
    *                   - encrypted: The encrypted data to send. This excludes
    *                                any decrypted data.
    *                   - all: The roomData with both encrypted and decrypted
    *                          information.
-   *                   If rejected, encryption has failed. This could be due to
-   *                   missing keys for FxA, which this process can't manage. It
-   *                   is generally expected the panel will prompt the user for
-   *                   re-auth if the FxA keys are missing.
    */
   promiseEncryptRoomData: Task.async(function* (roomData) {
+    // XXX We should only return unencrypted data whilst we're still working
+    // on context. Once bug 1115340 is fixed, this function should no longer be
+    // here.
+    function getUnencryptedData() {
+      var serverRoomData = extend({}, roomData);
+      delete serverRoomData.decryptedContext;
+
+      // We can only save roomName as non-encypted data for now.
+      serverRoomData.roomName = roomData.decryptedContext.roomName;
+
+      return {
+        all: roomData,
+        encrypted: serverRoomData
+      };
+    }
+
     var newRoomData = extend({}, roomData);
 
     if (!newRoomData.context) {
       newRoomData.context = {};
     }
 
     // First get the room key.
     let key = yield this.promiseGetOrCreateRoomKey(newRoomData);
 
-    newRoomData.context.wrappedKey = yield this.promiseEncryptedRoomKey(key);
+    try {
+      newRoomData.context.wrappedKey = yield this.promiseEncryptedRoomKey(key);
+    }
+    catch (ex) {
+      // XXX Bug 1153788 should remove this, then we can remove the whole
+      // try/catch.
+      if (ex.message == "FxA re-register not implemented") {
+        return getUnencryptedData();
+      }
+      return Promise.reject(ex);
+    }
 
     // Now encrypt the actual data.
     newRoomData.context.value = yield loopCrypto.encryptBytes(key,
       JSON.stringify(newRoomData.decryptedContext));
 
     // The algorithm is currently hard-coded as AES-GCM, in case of future
     // changes.
     newRoomData.context.alg = "AES-GCM";
@@ -383,19 +307,17 @@ let LoopRoomsInternal = {
       fallback = true;
     }
 
     let decryptedData = yield loopCrypto.decryptBytes(key, roomData.context.value);
 
     if (fallback) {
       // Fallback decryption succeeded, so we need to re-encrypt the room key and
       // save the data back again.
-      MozLoopService.log.debug("Fell back to saved key, queuing for encryption",
-        roomData.roomToken);
-      this.queueForEncryption(roomData.roomToken);
+      // XXX Bug 1152764 will implement this or make it a separate bug.
     } else if (!savedRoomKey || key != savedRoomKey) {
       // Decryption succeeded, but we don't have the right key saved.
       try {
         yield this.roomsCache.setKey(this.sessionType, roomData.roomToken, key);
       }
       catch (error) {
         MozLoopService.log.error("Failed to save room key:", error);
       }
@@ -436,33 +358,27 @@ let LoopRoomsInternal = {
    * @param {Object}  room     The new room to add.
    * @param {Boolean} isUpdate true if this is an update to an existing room.
    */
   addOrUpdateRoom: Task.async(function* (room, isUpdate) {
     if (!room.context) {
       // We don't do anything with roomUrl here as it doesn't need a key
       // string adding at this stage.
 
-      // No encrypted data yet, use the old roomName field.
+      // No encrypted data, use the old roomName field.
+      // XXX Bug 1152764 will add functions for automatically encrypting the room
+      // name.
       room.decryptedContext = {
         roomName: room.roomName
       };
       delete room.roomName;
 
-      // This room doesn't have context, so we'll save it for a later encryption
-      // cycle.
-      this.queueForEncryption(room.roomToken);
-
       this.saveAndNotifyUpdate(room, isUpdate);
     } else {
-      // We could potentially optimise this later by not decrypting if the
-      // encrypted context hasn't already changed. However perf doesn't seem
-      // to be too bigger an issue at the moment, so we just decrypt for now.
-      // If we do change this, then we need to make sure we get the new room
-      // data setup properly, as happens at the end of promiseDecryptRoomData.
+      // XXX Don't decrypt if same?
       try {
         let roomData = yield this.promiseDecryptRoomData(room);
 
         this.saveAndNotifyUpdate(roomData, isUpdate);
       } catch (error) {
         MozLoopService.log.error("Failed to decrypt room data: ", error);
         // Do what we can to save the room data.
         room.decryptedContext = {};
@@ -804,43 +720,48 @@ let LoopRoomsInternal = {
    *                            will be gone forever.
    * @param {Function} callback Function that will be invoked once the operation
    *                            finished. The first argument passed will be an
    *                            `Error` object or `null`.
    */
   update: function(roomToken, roomData, callback) {
     let room = this.rooms.get(roomToken);
     let url = "/rooms/" + encodeURIComponent(roomToken);
+
     if (!room.decryptedContext) {
       room.decryptedContext = {
         roomName: roomData.roomName || room.roomName
       };
     } else {
-      // room.roomName is the final fallback as this is pre-encryption support.
-      // Bug 1166283 is tracking the removal of the fallback.
-      room.decryptedContext.roomName = roomData.roomName ||
-                                       room.decryptedContext.roomName ||
-                                       room.roomName;
+      room.decryptedContext.roomName = roomData.roomName || room.roomName;
     }
     if (roomData.urls && roomData.urls.length) {
       // For now we only support adding one URL to the room context.
       room.decryptedContext.urls = [roomData.urls[0]];
     }
 
     Task.spawn(function* () {
       let {all, encrypted} = yield this.promiseEncryptRoomData(room);
 
       // For patch, we only send the context data.
       let sendData = {
         context: encrypted.context
       };
 
-      // This might be an upgrade to encrypted rename, so store the key
-      // just in case.
-      yield this.roomsCache.setKey(this.sessionType, all.roomToken, all.roomKey);
+      // If we're not encrypting currently, then only send the roomName.
+      // XXX This should go away once bug 1153788 is fixed.
+      if (!sendData.context) {
+        sendData = {
+          roomName: room.decryptedContext.roomName
+        };
+      } else {
+        // This might be an upgrade to encrypted rename, so store the key
+        // just in case.
+        yield this.roomsCache.setKey(this.sessionType, all.roomToken, all.roomKey);
+      }
 
       let response = yield MozLoopService.hawkRequest(this.sessionType,
           url, "PATCH", sendData);
 
       let newRoomData = all;
 
       extend(newRoomData, JSON.parse(response.body));
       this.rooms.set(roomToken, newRoomData);
--- a/browser/components/loop/modules/MozLoopService.jsm
+++ b/browser/components/loop/modules/MozLoopService.jsm
@@ -1343,20 +1343,19 @@ this.MozLoopService = {
     return new Promise((resolve, reject) => {
       if (this.userProfile) {
         // We're an FxA user.
         if (Services.prefs.prefHasUserValue("loop.key.fxa")) {
           resolve(MozLoopService.getLoopPref("key.fxa"));
           return;
         }
 
-        // This should generally never happen, but its not really possible
-        // for us to force reauth from here in a sensible way for the user.
-        // So we'll just have to flag it the best we can.
-        reject(new Error("No FxA key available"));
+        // XXX If we don't have a key for FxA yet, then simply reject for now.
+        // We'll create some sign-in/sign-out UX in bug 1153788.
+        reject(new Error("FxA re-register not implemented"));
         return;
       }
 
       // XXX Temporarily save in preferences until we've got some
       // extra storage (bug 1152761).
       if (!Services.prefs.prefHasUserValue("loop.key")) {
         // Get a new value.
         loopCrypto.generateKey().then(key => {
--- a/browser/components/loop/test/xpcshell/head.js
+++ b/browser/components/loop/test/xpcshell/head.js
@@ -13,17 +13,17 @@ Cu.import("resource://gre/modules/Servic
 Cu.import("resource://gre/modules/Http.jsm");
 Cu.import("resource://testing-common/httpd.js");
 Cu.import("resource:///modules/loop/MozLoopService.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource:///modules/loop/LoopCalls.jsm");
 Cu.import("resource:///modules/loop/LoopRooms.jsm");
 Cu.import("resource://gre/modules/osfile.jsm");
 const { MozLoopServiceInternal } = Cu.import("resource:///modules/loop/MozLoopService.jsm", {});
-const { LoopRoomsInternal, timerHandlers } = Cu.import("resource:///modules/loop/LoopRooms.jsm", {});
+const { LoopRoomsInternal } = Cu.import("resource:///modules/loop/LoopRooms.jsm", {});
 
 XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler",
                                   "resource:///modules/loop/MozLoopPushHandler.jsm");
 
 const kMockWebSocketChannelName = "Mock WebSocket Channel";
 const kWebSocketChannelContractID = "@mozilla.org/network/protocol;1?name=wss";
 
 const kServerPushUrl = "ws://localhost";
--- a/browser/components/loop/test/xpcshell/test_looprooms.js
+++ b/browser/components/loop/test/xpcshell/test_looprooms.js
@@ -4,28 +4,26 @@
 
 "use strict";
 
 Cu.import("resource://services-common/utils.js");
 Cu.import("resource:///modules/loop/LoopRooms.jsm");
 Cu.import("resource:///modules/Chat.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 
-timerHandlers.startTimer = callback => callback();
-
 let openChatOrig = Chat.open;
 
-const kKey = "uGIs-kGbYt1hBBwjyW7MLQ";
+const kGuestKey = "uGIs-kGbYt1hBBwjyW7MLQ";
 
 // Rooms details as responded by the server.
 const kRoomsResponses = new Map([
   ["_nxD4V4FflQ", {
     roomToken: "_nxD4V4FflQ",
     // Encrypted with roomKey "FliIGLUolW-xkKZVWstqKw".
-    // roomKey is wrapped with kKey.
+    // roomKey is wrapped with kGuestKey.
     context: {
       wrappedKey: "F3V27oPB+FgjFbVPML2PupONYqoIZ53XRU4BqG46Lr3eyIGumgCEqgjSe/MXAXiQ//8=",
       value: "df7B4SNxhOI44eJjQavCevADyCCxz6/DEZbkOkRUMVUxzS42FbzN6C2PqmCKDYUGyCJTwJ0jln8TLw==",
       alg: "AES-GCM"
     },
     roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ",
     maxSize: 2,
     ctime: 1405517546,
@@ -301,17 +299,22 @@ add_task(function* setup_server() {
     } else {
       if (req.queryString) {
         let qs = parseQueryString(req.queryString);
         let room = kRoomsResponses.get("_nxD4V4FflQ");
         room.participants = kRoomUpdates[qs.version].participants;
         room.deleted = kRoomUpdates[qs.version].deleted;
         res.write(JSON.stringify([room]));
       } else {
-        res.write(JSON.stringify([...kRoomsResponses.values()]));
+        // XXX Only return last 2 elements until FxA keys are implemented.
+        if (MozLoopServiceInternal.fxAOAuthTokenData) {
+          res.write(JSON.stringify([...kRoomsResponses.values()].slice(1, 3)));
+        } else {
+          res.write(JSON.stringify([...kRoomsResponses.values()]));
+        }
       }
     }
 
     res.processAsync();
     res.finish();
   });
 
   function returnRoomDetails(res, roomDetail, roomName) {
@@ -423,26 +426,26 @@ add_task(function* test_openRoom() {
   let windowData = MozLoopService.getConversationWindowData(windowId);
 
   Assert.equal(windowData.type, "room", "window data should contain room as the type");
   Assert.equal(windowData.roomToken, "fakeToken", "window data should have the roomToken");
 });
 
 // Test if the rooms cache is refreshed after FxA signin or signout.
 add_task(function* test_refresh() {
-  gExpectedAdds.push(...kExpectedRooms.values());
+  // XXX Temporarily whilst FxA encryption isn't handled (bug 1153788).
+  Array.prototype.push.apply(gExpectedAdds, [...kExpectedRooms.values()].slice(1, 3));
   gExpectedRefresh = true;
 
   // Make the switch.
   MozLoopServiceInternal.fxAOAuthTokenData = { token_type: "bearer" };
   MozLoopServiceInternal.fxAOAuthProfile = {
     email: "fake@invalid.com",
     uid: "fake"
   };
-  Services.prefs.setCharPref("loop.key.fxa", kKey);
 
   yield waitForCondition(() => !gExpectedRefresh);
   yield waitForCondition(() => gExpectedAdds.length === 0);
 
   gExpectedAdds.push(...kExpectedRooms.values());
   gExpectedRefresh = true;
   // Simulate a logout.
   MozLoopServiceInternal.fxAOAuthTokenData = null;
@@ -631,30 +634,29 @@ add_task(function* () {
   Assert.strictEqual(Object.getOwnPropertyNames(gExpectedLeaves).length, 0,
                      "No room leaves should be expected anymore");
   Assert.ok(!gExpectedRefresh, "No refreshes should be expected anymore");
  });
 
 function run_test() {
   setupFakeLoopServer();
 
-  Services.prefs.setCharPref("loop.key", kKey);
+  Services.prefs.setCharPref("loop.key", kGuestKey);
 
   LoopRooms.on("add", onRoomAdded);
   LoopRooms.on("update", onRoomUpdated);
   LoopRooms.on("delete", onRoomDeleted);
   LoopRooms.on("joined", onRoomJoined);
   LoopRooms.on("left", onRoomLeft);
   LoopRooms.on("refresh", onRefresh);
 
   do_register_cleanup(function () {
     // Revert original Chat.open implementation
     Chat.open = openChatOrig;
     Services.prefs.clearUserPref("loop.key");
-    Services.prefs.clearUserPref("loop.key.fxa");
 
     MozLoopServiceInternal.fxAOAuthTokenData = null;
     MozLoopServiceInternal.fxAOAuthProfile = null;
 
     LoopRooms.off("add", onRoomAdded);
     LoopRooms.off("update", onRoomUpdated);
     LoopRooms.off("delete", onRoomDeleted);
     LoopRooms.off("joined", onRoomJoined);
--- a/browser/components/loop/test/xpcshell/test_looprooms_encryption_in_fxa.js
+++ b/browser/components/loop/test/xpcshell/test_looprooms_encryption_in_fxa.js
@@ -1,16 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
  * You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 "use strict";
 
-timerHandlers.startTimer = callback => callback();
-
 Cu.import("resource://services-common/utils.js");
 const { LOOP_ROOMS_CACHE_FILENAME } = Cu.import("resource:///modules/loop/LoopRoomsCache.jsm", {});
 
 const kContextEnabledPref = "loop.contextInConverations.enabled";
 
 const kFxAKey = "uGIs-kGbYt1hBBwjyW7MLQ";
 
 // Rooms details as responded by the server.
deleted file mode 100644
--- a/browser/components/loop/test/xpcshell/test_looprooms_upgrade_to_encryption.js
+++ /dev/null
@@ -1,149 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-Cu.import("resource://services-common/utils.js");
-
-const loopCrypto = Cu.import("resource:///modules/loop/crypto.js", {}).LoopCrypto;
-const { LOOP_ROOMS_CACHE_FILENAME } = Cu.import("resource:///modules/loop/LoopRoomsCache.jsm", {});
-
-let gTimerArgs = [];
-
-timerHandlers.startTimer = function(callback, delay) {
-  gTimerArgs.push({callback, delay});
-  return gTimerArgs.length;
-};
-
-let gRoomPatches = [];
-
-const kContextEnabledPref = "loop.contextInConverations.enabled";
-
-const kFxAKey = "uGIs-kGbYt1hBBwjyW7MLQ";
-
-// Rooms details as responded by the server.
-const kRoomsResponses = new Map([
-  ["_nxD4V4FflQ", {
-    roomToken: "_nxD4V4FflQ",
-    roomName: "First Room Name",
-    roomUrl: "http://localhost:3000/rooms/_nxD4V4FflQ"
-  }],
-  ["QzBbvGmIZWU", {
-    roomToken: "QzBbvGmIZWU",
-    roomName: "Loopy Discussion",
-    roomUrl: "http://localhost:3000/rooms/QzBbvGmIZWU"
-  }]
-]);
-
-// This is a cut-down version of the one in test_looprooms.js.
-add_task(function* setup_server() {
-  loopServer.registerPathHandler("/registration", (req, res) => {
-    res.setStatusLine(null, 200, "OK");
-    res.processAsync();
-    res.finish();
-  });
-
-  loopServer.registerPathHandler("/rooms", (req, res) => {
-    res.setStatusLine(null, 200, "OK");
-
-    res.write(JSON.stringify([...kRoomsResponses.values()]));
-
-    res.processAsync();
-    res.finish();
-  });
-
-  function returnRoomDetails(res, roomName) {
-    roomDetail.roomName = roomName;
-    res.setStatusLine(null, 200, "OK");
-    res.write(JSON.stringify(roomDetail));
-    res.processAsync();
-    res.finish();
-  }
-
-  function getJSONData(body) {
-    return JSON.parse(CommonUtils.readBytesFromInputStream(body));
-  }
-
-  // Add a request handler for each room in the list.
-  [...kRoomsResponses.values()].forEach(function(room) {
-    loopServer.registerPathHandler("/rooms/" + encodeURIComponent(room.roomToken), (req, res) => {
-      let roomDetail = extend({}, room);
-      if (req.method == "PATCH") {
-        let data = getJSONData(req.bodyInputStream);
-        Assert.ok("context" in data, "should have encrypted context");
-        gRoomPatches.push(data);
-        delete roomDetail.roomName;
-        roomDetail.context = data.context;
-        res.setStatusLine(null, 200, "OK");
-        res.write(JSON.stringify(roomDetail));
-        res.processAsync();
-        res.finish();
-      } else {
-        res.setStatusLine(null, 200, "OK");
-        res.write(JSON.stringify(room));
-        res.processAsync();
-        res.finish();
-      }
-    });
-  });
-
-  mockPushHandler.registrationPushURL = kEndPointUrl;
-
-  yield MozLoopService.promiseRegisteredWithServers();
-});
-
-// Test if getting rooms saves unknown keys correctly.
-add_task(function* test_get_rooms_upgrades_to_encryption() {
-  let rooms = yield LoopRooms.promise("getAll");
-
-  // Check that we've saved the encryption keys correctly.
-  Assert.equal(LoopRoomsInternal.encryptionQueue.queue.length, 2, "Should have two rooms queued");
-  Assert.equal(gTimerArgs.length, 1, "Should have started a timer");
-
-  // Now pretend the timer has fired.
-  yield gTimerArgs[0].callback();
-
-  Assert.equal(gRoomPatches.length, 1, "Should have patched one room");
-  Assert.equal(gTimerArgs.length, 2, "Should have started a second timer");
-
-  yield gTimerArgs[1].callback();
-
-  Assert.equal(gRoomPatches.length, 2, "Should have patches a second room");
-  Assert.equal(gTimerArgs.length, 2, "Should not have queued another timer");
-
-  // Now check that we've got the right data stored in the rooms.
-  rooms = yield LoopRooms.promise("getAll");
-
-  Assert.equal(rooms.length, 2, "Should have two rooms");
-
-  // We have to decrypt the info, no other way.
-  for (let room of rooms) {
-    let roomData = yield loopCrypto.decryptBytes(room.roomKey, room.context.value);
-
-    Assert.deepEqual(JSON.parse(roomData),
-      { roomName: kRoomsResponses.get(room.roomToken).roomName },
-      "Should have encrypted the data correctly");
-  }
-});
-
-function run_test() {
-  setupFakeLoopServer();
-
-  Services.prefs.setCharPref("loop.key.fxa", kFxAKey);
-  Services.prefs.setBoolPref(kContextEnabledPref, true);
-
-  // Pretend we're signed into FxA.
-  MozLoopServiceInternal.fxAOAuthTokenData = { token_type: "bearer" };
-  MozLoopServiceInternal.fxAOAuthProfile = { email: "fake@invalid.com" };
-
-  do_register_cleanup(function () {
-    Services.prefs.clearUserPref(kContextEnabledPref);
-    Services.prefs.clearUserPref("loop.key.fxa");
-
-    MozLoopServiceInternal.fxAOAuthTokenData = null;
-    MozLoopServiceInternal.fxAOAuthProfile = null;
-  });
-
-  run_next_test();
-}
--- a/browser/components/loop/test/xpcshell/test_loopservice_encryptionkey.js
+++ b/browser/components/loop/test/xpcshell/test_loopservice_encryptionkey.js
@@ -52,17 +52,17 @@ add_task(function* test_fxaGetKnownKey()
 add_task(function* test_fxaGetKey() {
   // Set the userProfile to look like we're logged into FxA without a key stored.
   MozLoopServiceInternal.fxAOAuthTokenData = { token_type: "bearer" };
   MozLoopServiceInternal.fxAOAuthProfile = { email: "fake@invalid.com" };
   Services.prefs.clearUserPref(kFxAKeyPref);
 
   // Currently unimplemented, add a test when we implement the code.
   yield Assert.rejects(MozLoopService.promiseProfileEncryptionKey(),
-    /No FxA key available/, "should reject as not available");
+    /not implemented/, "should reject as unimplemented");
 });
 
 add_task(function test_hasEncryptionKey() {
   MozLoopServiceInternal.fxAOAuthTokenData = null;
   MozLoopServiceInternal.fxAOAuthProfile = null;
 
   Services.prefs.clearUserPref(kGuestKeyPref);
   Services.prefs.clearUserPref(kFxAKeyPref);
--- a/browser/components/loop/test/xpcshell/xpcshell.ini
+++ b/browser/components/loop/test/xpcshell/xpcshell.ini
@@ -4,17 +4,16 @@ tail =
 firefox-appdir = browser
 skip-if = toolkit == 'gonk'
 
 [test_loopapi_hawk_request.js]
 [test_looppush_initialize.js]
 [test_looprooms.js]
 [test_looprooms_encryption_in_fxa.js]
 [test_looprooms_first_notification.js]
-[test_looprooms_upgrade_to_encryption.js]
 [test_loopservice_directcall.js]
 [test_loopservice_dnd.js]
 [test_loopservice_encryptionkey.js]
 [test_loopservice_hawk_errors.js]
 [test_loopservice_hawk_request.js]
 [test_loopservice_loop_prefs.js]
 [test_loopservice_initialize.js]
 [test_loopservice_locales.js]