Bug 1291703 - Ship 1.4.4 of the Loop system add-on. Include a banner warning about the removal. rs=Standard8 for already reviewed code,a=sledru
authorMark Banner <standard8@mozilla.com>
Tue, 16 Aug 2016 11:14:11 +0100
changeset 407642 d086e0d5681953b69f1186656162fafd1a208f01
parent 407641 4217d21df7061f94061d059c56bcb96d290990f1
child 407643 4cc7ecd49f95a67ccd0335c5e5264501285ca6d4
push id28002
push userfelipc@gmail.com
push dateTue, 30 Aug 2016 18:14:28 +0000
reviewersStandard8, sledru
bugs1291703
milestone48.0.1
Bug 1291703 - Ship 1.4.4 of the Loop system add-on. Include a banner warning about the removal. rs=Standard8 for already reviewed code,a=sledru
browser/extensions/loop/bootstrap.js
browser/extensions/loop/chrome/content/modules/DomainWhitelist.jsm
browser/extensions/loop/chrome/content/modules/LoopRooms.jsm
browser/extensions/loop/chrome/content/modules/LoopRoomsCache.jsm
browser/extensions/loop/chrome/content/modules/MozLoopAPI.jsm
browser/extensions/loop/chrome/content/modules/MozLoopPushHandler.jsm
browser/extensions/loop/chrome/content/modules/MozLoopService.jsm
browser/extensions/loop/chrome/content/modules/MozLoopWorker.js
browser/extensions/loop/chrome/content/modules/tabFrame.js
browser/extensions/loop/chrome/content/panels/css/copy.css
browser/extensions/loop/chrome/content/panels/css/panel.css
browser/extensions/loop/chrome/content/panels/js/conversation.js
browser/extensions/loop/chrome/content/panels/js/conversationAppStore.js
browser/extensions/loop/chrome/content/panels/js/copy.js
browser/extensions/loop/chrome/content/panels/js/desktopViews.js
browser/extensions/loop/chrome/content/panels/js/feedbackViews.js
browser/extensions/loop/chrome/content/panels/js/models.js
browser/extensions/loop/chrome/content/panels/js/otconfig.js
browser/extensions/loop/chrome/content/panels/js/panel.js
browser/extensions/loop/chrome/content/panels/js/roomStore.js
browser/extensions/loop/chrome/content/panels/js/roomViews.js
browser/extensions/loop/chrome/content/panels/js/slideshow.js
browser/extensions/loop/chrome/content/panels/test/conversationAppStore_test.js
browser/extensions/loop/chrome/content/panels/test/conversation_test.js
browser/extensions/loop/chrome/content/panels/test/copy_test.js
browser/extensions/loop/chrome/content/panels/test/desktopViews_test.js
browser/extensions/loop/chrome/content/panels/test/fake-components.js
browser/extensions/loop/chrome/content/panels/test/feedbackViews_test.js
browser/extensions/loop/chrome/content/panels/test/l10n_test.js
browser/extensions/loop/chrome/content/panels/test/panel_test.js
browser/extensions/loop/chrome/content/panels/test/roomStore_test.js
browser/extensions/loop/chrome/content/panels/test/roomViews_test.js
browser/extensions/loop/chrome/content/panels/test/slideshow_test.js
browser/extensions/loop/chrome/content/panels/vendor/simpleSlideshow.js
browser/extensions/loop/chrome/content/preferences/prefs.js
browser/extensions/loop/chrome/content/shared/css/common.css
browser/extensions/loop/chrome/content/shared/js/actions.js
browser/extensions/loop/chrome/content/shared/js/activeRoomStore.js
browser/extensions/loop/chrome/content/shared/js/crypto.js
browser/extensions/loop/chrome/content/shared/js/dispatcher.js
browser/extensions/loop/chrome/content/shared/js/linkifiedTextView.js
browser/extensions/loop/chrome/content/shared/js/loopapi-client.js
browser/extensions/loop/chrome/content/shared/js/mixins.js
browser/extensions/loop/chrome/content/shared/js/otSdkDriver.js
browser/extensions/loop/chrome/content/shared/js/remoteCursorStore.js
browser/extensions/loop/chrome/content/shared/js/store.js
browser/extensions/loop/chrome/content/shared/js/textChatStore.js
browser/extensions/loop/chrome/content/shared/js/textChatView.js
browser/extensions/loop/chrome/content/shared/js/urlRegExps.js
browser/extensions/loop/chrome/content/shared/js/utils.js
browser/extensions/loop/chrome/content/shared/js/validate.js
browser/extensions/loop/chrome/content/shared/js/views.js
browser/extensions/loop/chrome/content/shared/test/activeRoomStore_test.js
browser/extensions/loop/chrome/content/shared/test/crypto_test.js
browser/extensions/loop/chrome/content/shared/test/dispatcher_test.js
browser/extensions/loop/chrome/content/shared/test/linkifiedTextView_test.js
browser/extensions/loop/chrome/content/shared/test/loop_mocha_utils.js
browser/extensions/loop/chrome/content/shared/test/loopapi-client_test.js
browser/extensions/loop/chrome/content/shared/test/mixins_test.js
browser/extensions/loop/chrome/content/shared/test/otSdkDriver_test.js
browser/extensions/loop/chrome/content/shared/test/remoteCursorStore_test.js
browser/extensions/loop/chrome/content/shared/test/sdk_mock.js
browser/extensions/loop/chrome/content/shared/test/store_test.js
browser/extensions/loop/chrome/content/shared/test/textChatStore_test.js
browser/extensions/loop/chrome/content/shared/test/textChatView_test.js
browser/extensions/loop/chrome/content/shared/test/utils_test.js
browser/extensions/loop/chrome/content/shared/test/validate_test.js
browser/extensions/loop/chrome/content/shared/test/views_test.js
browser/extensions/loop/chrome/locale/ast/loop.properties
browser/extensions/loop/chrome/locale/az/loop.properties
browser/extensions/loop/chrome/locale/bg/loop.properties
browser/extensions/loop/chrome/locale/bn-BD/loop.properties
browser/extensions/loop/chrome/locale/cs/loop.properties
browser/extensions/loop/chrome/locale/cy/loop.properties
browser/extensions/loop/chrome/locale/da/loop.properties
browser/extensions/loop/chrome/locale/de/loop.properties
browser/extensions/loop/chrome/locale/dsb/loop.properties
browser/extensions/loop/chrome/locale/en-GB/loop.properties
browser/extensions/loop/chrome/locale/en-US/loop.properties
browser/extensions/loop/chrome/locale/es-CL/loop.properties
browser/extensions/loop/chrome/locale/es-ES/loop.properties
browser/extensions/loop/chrome/locale/es-MX/loop.properties
browser/extensions/loop/chrome/locale/et/loop.properties
browser/extensions/loop/chrome/locale/fi/loop.properties
browser/extensions/loop/chrome/locale/fr/loop.properties
browser/extensions/loop/chrome/locale/hsb/loop.properties
browser/extensions/loop/chrome/locale/hu/loop.properties
browser/extensions/loop/chrome/locale/hy-AM/loop.properties
browser/extensions/loop/chrome/locale/id/loop.properties
browser/extensions/loop/chrome/locale/it/loop.properties
browser/extensions/loop/chrome/locale/ja/loop.properties
browser/extensions/loop/chrome/locale/nl/loop.properties
browser/extensions/loop/chrome/locale/nn-NO/loop.properties
browser/extensions/loop/chrome/locale/pl/loop.properties
browser/extensions/loop/chrome/locale/pt-BR/loop.properties
browser/extensions/loop/chrome/locale/pt-PT/loop.properties
browser/extensions/loop/chrome/locale/ru/loop.properties
browser/extensions/loop/chrome/locale/sk/loop.properties
browser/extensions/loop/chrome/locale/sl/loop.properties
browser/extensions/loop/chrome/locale/sq/loop.properties
browser/extensions/loop/chrome/locale/sr/loop.properties
browser/extensions/loop/chrome/locale/sv-SE/loop.properties
browser/extensions/loop/chrome/locale/te/loop.properties
browser/extensions/loop/chrome/locale/tr/loop.properties
browser/extensions/loop/chrome/locale/uk/loop.properties
browser/extensions/loop/chrome/locale/zh-CN/loop.properties
browser/extensions/loop/chrome/locale/zh-TW/loop.properties
browser/extensions/loop/chrome/skin/linux/panelarrow-vertical-warning.png
browser/extensions/loop/chrome/skin/linux/panelarrow-vertical-warning@2x.png
browser/extensions/loop/chrome/skin/osx/panelarrow-vertical-warning.png
browser/extensions/loop/chrome/skin/osx/panelarrow-vertical-warning@2x.png
browser/extensions/loop/chrome/skin/shared/loop.css
browser/extensions/loop/chrome/skin/windows/panelarrow-vertical-warning.png
browser/extensions/loop/chrome/skin/windows/panelarrow-vertical-warning@2x.png
browser/extensions/loop/chrome/test/mochitest/browser.ini
browser/extensions/loop/install.rdf.in
browser/extensions/loop/test/functional/config.py
browser/extensions/loop/test/functional/loopTestDriver.py
browser/extensions/loop/test/functional/manifest.ini
browser/extensions/loop/test/functional/test_1_browser_call.py
browser/extensions/loop/test/functional/test_2_linkclicker.py
--- a/browser/extensions/loop/bootstrap.js
+++ b/browser/extensions/loop/bootstrap.js
@@ -1,14 +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";
 
-/* exported startup, shutdown, install, uninstall */var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {return typeof obj;} : function (obj) {return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;};function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}}var _Components = 
+/* exported startup, shutdown, install, uninstall */var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {return typeof obj;} : function (obj) {return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;};function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}}var _Components =
 
 Components;var Ci = _Components.interfaces;var Cu = _Components.utils;var Cc = _Components.classes;
 
 var kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 var kBrowserSharingNotificationId = "loop-sharing-notification";
 
 var CURSOR_MIN_DELTA = 3;
 var CURSOR_MIN_INTERVAL = 100;
@@ -16,1263 +16,1263 @@ var CURSOR_CLICK_DELAY = 1000;
 // Due to bug 1051238 frame scripts are cached forever, so we can't update them
 // as a restartless add-on. The Math.random() is the work around for this.
 var FRAME_SCRIPT = "chrome://loop/content/modules/tabFrame.js?" + Math.random();
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/AppConstants.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils", 
+XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
 "resource://gre/modules/PrivateBrowsingUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI", 
+XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI",
 "resource:///modules/CustomizableUI.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Task", 
+XPCOMUtils.defineLazyModuleGetter(this, "Task",
 "resource://gre/modules/Task.jsm");
 
 // See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
 var PREF_LOG_LEVEL = "loop.debug.loglevel";
 
 XPCOMUtils.defineLazyGetter(this, "log", function () {
   var ConsoleAPI = Cu.import("resource://gre/modules/Console.jsm", {}).ConsoleAPI;
-  var consoleOptions = { 
-    maxLogLevelPref: PREF_LOG_LEVEL, 
+  var consoleOptions = {
+    maxLogLevelPref: PREF_LOG_LEVEL,
     prefix: "Loop" };
 
-  return new ConsoleAPI(consoleOptions);});
-
+  return new ConsoleAPI(consoleOptions);
+});
 
 /**
- * This window listener gets loaded into each browser.xul window and is used
- * to provide the required loop functions for the window.
- */
-var WindowListener = { 
+     * This window listener gets loaded into each browser.xul window and is used
+     * to provide the required loop functions for the window.
+     */
+var WindowListener = {
   // Records the add-on version once we know it.
-  addonVersion: "unknown", 
+  addonVersion: "unknown",
 
   /**
-   * Sets up the chrome integration within browser windows for Loop.
-   *
-   * @param {Object} window The window to inject the integration into.
-   */
+                            * Sets up the chrome integration within browser windows for Loop.
+                            *
+                            * @param {Object} window The window to inject the integration into.
+                            */
   setupBrowserUI: function setupBrowserUI(window) {
-    var document = window.document;var 
+    var document = window.document;var
     gBrowser = window.gBrowser;var gURLBar = window.gURLBar;
     var xhrClass = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"];
     var FileReader = window.FileReader;
     var menuItem = null;
     var isSlideshowOpen = false;
     var titleChangedListener = null;
 
     // the "exported" symbols
-    var LoopUI = { 
+    var LoopUI = {
       /**
-       * @var {XULWidgetSingleWrapper} toolbarButton Getter for the Loop toolbarbutton
-       *                                             instance for this window. This should
-       *                                             not be used in the hidden window.
-       */
+                    * @var {XULWidgetSingleWrapper} toolbarButton Getter for the Loop toolbarbutton
+                    *                                             instance for this window. This should
+                    *                                             not be used in the hidden window.
+                    */
       get toolbarButton() {
         delete this.toolbarButton;
-        return this.toolbarButton = CustomizableUI.getWidget("loop-button").forWindow(window);}, 
-
+        return this.toolbarButton = CustomizableUI.getWidget("loop-button").forWindow(window);
+      },
 
       /**
-       * @var {XULElement} panel Getter for the Loop panel element.
-       */
+          * @var {XULElement} panel Getter for the Loop panel element.
+          */
       get panel() {
         delete this.panel;
-        return this.panel = document.getElementById("loop-notification-panel");}, 
-
+        return this.panel = document.getElementById("loop-notification-panel");
+      },
 
       /**
-       * @var {XULElement|null} browser Getter for the Loop panel browser element.
-       *                                Will be NULL if the panel hasn't loaded yet.
-       */
+          * @var {XULElement|null} browser Getter for the Loop panel browser element.
+          *                                Will be NULL if the panel hasn't loaded yet.
+          */
       get browser() {
         var browser = document.querySelector("#loop-notification-panel > #loop-panel-iframe");
         if (browser) {
           delete this.browser;
-          this.browser = browser;}
-
-        return browser;}, 
-
+          this.browser = browser;
+        }
+        return browser;
+      },
 
       get isSlideshowOpen() {
-        return isSlideshowOpen;}, 
-
+        return isSlideshowOpen;
+      },
 
       set isSlideshowOpen(aOpen) {
         isSlideshowOpen = aOpen;
-        this.updateToolbarState();}, 
-
+        this.updateToolbarState();
+      },
       /**
-       * @return {Object} Getter for the Loop constants
-       */
+          * @return {Object} Getter for the Loop constants
+          */
       get constants() {var _this = this;
         if (!this._constants) {
           // GetAllConstants is synchronous even though it's using a callback.
-          this.LoopAPI.sendMessageToHandler({ 
-            name: "GetAllConstants" }, 
+          this.LoopAPI.sendMessageToHandler({
+            name: "GetAllConstants" },
           function (result) {
-            _this._constants = result;});}
+            _this._constants = result;
+          });
+        }
 
-
-
-        return this._constants;}, 
-
+        return this._constants;
+      },
 
       get mm() {
-        return window.getGroupMessageManager("browsers");}, 
-
+        return window.getGroupMessageManager("browsers");
+      },
 
       /**
-       * @return {Promise}
-       */
+          * @return {Promise}
+          */
       promiseDocumentVisible: function promiseDocumentVisible(aDocument) {
         if (!aDocument.hidden) {
-          return Promise.resolve(aDocument);}
-
+          return Promise.resolve(aDocument);
+        }
 
         return new Promise(function (resolve) {
           aDocument.addEventListener("visibilitychange", function onVisibilityChanged() {
             aDocument.removeEventListener("visibilitychange", onVisibilityChanged);
-            resolve(aDocument);});});}, 
-
-
-
+            resolve(aDocument);
+          });
+        });
+      },
 
       /**
-       * Toggle between opening or hiding the Loop panel.
-       *
-       * @param {DOMEvent} [event] Optional event that triggered the call to this
-       *                           function.
-       * @return {Promise}
-       */
+          * Toggle between opening or hiding the Loop panel.
+          *
+          * @param {DOMEvent} [event] Optional event that triggered the call to this
+          *                           function.
+          * @return {Promise}
+          */
       togglePanel: function togglePanel(event) {var _this2 = this;
         if (!this.panel) {var _ret = function () {
             // We're on the hidden window! What fun!
             var obs = function obs(win) {
               Services.obs.removeObserver(obs, "browser-delayed-startup-finished");
-              win.LoopUI.togglePanel(event);};
-
+              win.LoopUI.togglePanel(event);
+            };
             Services.obs.addObserver(obs, "browser-delayed-startup-finished", false);
-            return { v: window.OpenBrowserWindow() };}();if ((typeof _ret === "undefined" ? "undefined" : _typeof(_ret)) === "object") return _ret.v;}
-
+            return { v: window.OpenBrowserWindow() };}();if ((typeof _ret === "undefined" ? "undefined" : _typeof(_ret)) === "object") return _ret.v;
+        }
         if (this.panel.state == "open") {
           return new Promise(function (resolve) {
             _this2.panel.hidePopup();
-            resolve();});}
-
-
+            resolve();
+          });
+        }
 
         if (this.isSlideshowOpen) {
-          return Promise.resolve();}
-
+          return Promise.resolve();
+        }
 
         return this.openPanel(event).then(function (mm) {
           if (mm) {
-            mm.sendAsyncMessage("Social:EnsureFocusElement");}}).
-
-        catch(function (err) {
-          Cu.reportError(err);});}, 
-
-
+            mm.sendAsyncMessage("Social:EnsureFocusElement");
+          }
+        }).catch(function (err) {
+          Cu.reportError(err);
+        });
+      },
 
       /**
-       * Called when a closing room has just been created, so we offer the
-       * user the chance to modify the name. For that we need to open the panel.
-       * Showing the proper layout is done on panel.jsx
-       */
+          * Called when a closing room has just been created, so we offer the
+          * user the chance to modify the name. For that we need to open the panel.
+          * Showing the proper layout is done on panel.jsx
+          */
       renameRoom: function renameRoom() {
-        this.openPanel();}, 
-
+        this.openPanel();
+      },
 
       /**
-       * Opens the panel for Loop and sizes it appropriately.
-       *
-       * @param {event}  event   The event opening the panel, used to anchor
-       *                         the panel to the button which triggers it.
-       * @return {Promise}
-       */
+          * Opens the panel for Loop and sizes it appropriately.
+          *
+          * @param {event}  event   The event opening the panel, used to anchor
+          *                         the panel to the button which triggers it.
+          * @return {Promise}
+          */
       openPanel: function openPanel(event) {var _this3 = this;
         if (PrivateBrowsingUtils.isWindowPrivate(window)) {
-          return Promise.reject();}
-
+          return Promise.reject();
+        }
 
         return new Promise(function (resolve) {
           var callback = function callback(iframe) {
             var mm = iframe.QueryInterface(Ci.nsIFrameLoaderOwner).frameLoader.messageManager;
             if (!("messageManager" in iframe)) {
-              iframe.messageManager = mm;}
-
+              iframe.messageManager = mm;
+            }
 
             if (!_this3._panelInitialized) {
               _this3.hookWindowCloseForPanelClose(iframe);
-              _this3._panelInitialized = true;}
-
+              _this3._panelInitialized = true;
+            }
 
             mm.sendAsyncMessage("Social:WaitForDocumentVisible");
             mm.addMessageListener("Social:DocumentVisible", function onDocumentVisible() {
               mm.removeMessageListener("Social:DocumentVisible", onDocumentVisible);
-              resolve(mm);});
-
+              resolve(mm);
+            });
 
             var buckets = _this3.constants.LOOP_MAU_TYPE;
-            _this3.LoopAPI.sendMessageToHandler({ 
-              name: "TelemetryAddValue", 
-              data: ["LOOP_ACTIVITY_COUNTER", buckets.OPEN_PANEL] });};
+            _this3.LoopAPI.sendMessageToHandler({
+              name: "TelemetryAddValue",
+              data: ["LOOP_ACTIVITY_COUNTER", buckets.OPEN_PANEL] });
 
-
+          };
 
           // Used to clear the temporary "login" state from the button.
           Services.obs.notifyObservers(null, "loop-status-changed", null);
 
           _this3.shouldResumeTour().then(function (resume) {
             if (resume) {
               // Assume the conversation with the visitor wasn't open since we would
               // have resumed the tour as soon as the visitor joined if it was (and
               // the pref would have been set to false already.
               _this3.MozLoopService.resumeTour("waiting");
               resolve(null);
-              return;}
-
+              return;
+            }
 
             _this3.LoopAPI.initialize();
 
             var anchor = event ? event.target : _this3.toolbarButton.anchor;
             _this3.PanelFrame.showPopup(
-            window, 
-            anchor, 
+            window,
+            anchor,
             "loop", // Notification Panel Type
             null, // Origin
             "about:looppanel", // Source
             null, // Size
-            callback);});});}, 
-
-
-
+            callback);
+          });
+        });
+      },
 
       /**
-       * Wrapper for openPanel - to support Firefox 46 and 45.
-       *
-       * @param {event}  event   The event opening the panel, used to anchor
-       *                         the panel to the button which triggers it.
-       * @return {Promise}
-       */
+          * Wrapper for openPanel - to support Firefox 46 and 45.
+          *
+          * @param {event}  event   The event opening the panel, used to anchor
+          *                         the panel to the button which triggers it.
+          * @return {Promise}
+          */
       openCallPanel: function openCallPanel(event) {
-        return this.openPanel(event);}, 
-
+        return this.openPanel(event);
+      },
 
       /**
-       * Method to know whether actions to open the panel should instead resume the tour.
-       *
-       * We need the panel to be opened via UITour so that it gets @noautohide.
-       *
-       * @return {Promise} resolving with a {Boolean} of whether the tour should be resumed instead of
-       *                   opening the panel.
-       */
+          * Method to know whether actions to open the panel should instead resume the tour.
+          *
+          * We need the panel to be opened via UITour so that it gets @noautohide.
+          *
+          * @return {Promise} resolving with a {Boolean} of whether the tour should be resumed instead of
+          *                   opening the panel.
+          */
       shouldResumeTour: Task.async(function* () {
         // Resume the FTU tour if this is the first time a room was joined by
         // someone else since the tour.
         if (!Services.prefs.getBoolPref("loop.gettingStarted.resumeOnFirstJoin")) {
-          return false;}
-
+          return false;
+        }
 
         if (!this.LoopRooms.participantsCount) {
           // Nobody is in the rooms
-          return false;}
-
+          return false;
+        }
 
         var roomsWithNonOwners = yield this.roomsWithNonOwners();
         if (!roomsWithNonOwners.length) {
           // We were the only one in a room but we want to know about someone else joining.
-          return false;}
-
+          return false;
+        }
 
-        return true;}), 
-
+        return true;
+      }),
 
       /**
-       * @return {Promise} resolved with an array of Rooms with participants (excluding owners)
-       */
+           * @return {Promise} resolved with an array of Rooms with participants (excluding owners)
+           */
       roomsWithNonOwners: function roomsWithNonOwners() {var _this4 = this;
         return new Promise(function (resolve) {
           _this4.LoopRooms.getAll(function (error, rooms) {
             var roomsWithNonOwners = [];var _iteratorNormalCompletion = true;var _didIteratorError = false;var _iteratorError = undefined;try {
               for (var _iterator = rooms[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {var room = _step.value;
                 if (!("participants" in room)) {
-                  continue;}
-
+                  continue;
+                }
                 var numNonOwners = room.participants.filter(function (participant) {return !participant.owner;}).length;
                 if (!numNonOwners) {
-                  continue;}
-
-                roomsWithNonOwners.push(room);}} catch (err) {_didIteratorError = true;_iteratorError = err;} finally {try {if (!_iteratorNormalCompletion && _iterator.return) {_iterator.return();}} finally {if (_didIteratorError) {throw _iteratorError;}}}
-
-            resolve(roomsWithNonOwners);});});}, 
-
-
-
+                  continue;
+                }
+                roomsWithNonOwners.push(room);
+              }} catch (err) {_didIteratorError = true;_iteratorError = err;} finally {try {if (!_iteratorNormalCompletion && _iterator.return) {_iterator.return();}} finally {if (_didIteratorError) {throw _iteratorError;}}}
+            resolve(roomsWithNonOwners);
+          });
+        });
+      },
 
       /**
-       * Triggers the initialization of the loop service if necessary.
-       * Also adds appropraite observers for the UI.
-       */
+          * Triggers the initialization of the loop service if necessary.
+          * Also adds appropraite observers for the UI.
+          */
       init: function init() {var _this5 = this;
         // This is a promise for test purposes, but we don't want to be logging
         // expected errors to the console, so we catch them here.
         this.MozLoopService.initialize(WindowListener.addonVersion).catch(function (ex) {
-          if (!ex.message || 
-          !ex.message.contains("not enabled") && 
+          if (!ex.message ||
+          !ex.message.contains("not enabled") &&
           !ex.message.contains("not needed")) {
-            console.error(ex);}});
-
-
+            console.error(ex);
+          }
+        });
 
         // If we're in private browsing mode, then don't add the menu item,
         // also don't add the listeners as we don't want to update the button.
         if (PrivateBrowsingUtils.isWindowPrivate(window)) {
-          return;}
-
+          return;
+        }
 
         this.addMenuItem();
 
         // Don't do the rest if this is for the hidden window - we don't
         // have a toolbar there.
         if (window == Services.appShell.hiddenDOMWindow) {
-          return;}
-
+          return;
+        }
 
         // Load the frame script into any tab, plus any that get created in the
         // future.
         this.mm.loadFrameScript(FRAME_SCRIPT, true);
 
         // Cleanup when the window unloads.
         window.addEventListener("unload", function () {
-          Services.obs.removeObserver(_this5, "loop-status-changed");});
-
+          Services.obs.removeObserver(_this5, "loop-status-changed");
+        });
 
         Services.obs.addObserver(this, "loop-status-changed", false);
 
         this.maybeAddCopyPanel();
-        this.updateToolbarState();}, 
-
+        this.updateToolbarState();
+      },
 
       /**
-       * Adds a menu item to the browsers' Tools menu that open the Loop panel
-       * when selected.
-       */
+          * Adds a menu item to the browsers' Tools menu that open the Loop panel
+          * when selected.
+          */
       addMenuItem: function addMenuItem() {var _this6 = this;
         var menu = document.getElementById("menu_ToolsPopup");
         if (!menu || menuItem) {
-          return;}
-
+          return;
+        }
 
         menuItem = document.createElementNS(kNSXUL, "menuitem");
         menuItem.setAttribute("id", "menu_openLoop");
         menuItem.setAttribute("label", this._getString("loopMenuItem_label"));
         menuItem.setAttribute("accesskey", this._getString("loopMenuItem_accesskey"));
 
         menuItem.addEventListener("command", function () {return _this6.togglePanel();});
 
-        menu.insertBefore(menuItem, document.getElementById("sync-setup"));}, 
-
+        menu.insertBefore(menuItem, document.getElementById("sync-setup"));
+      },
 
       /**
-       * Removes the menu item from the browsers' Tools menu.
-       */
+          * Removes the menu item from the browsers' Tools menu.
+          */
       removeMenuItem: function removeMenuItem() {
         if (menuItem) {
-          menuItem.parentNode.removeChild(menuItem);}}, 
-
-
+          menuItem.parentNode.removeChild(menuItem);
+        }
+      },
 
       /**
-       * Maybe add the copy panel if it's not throttled and passes other checks.
-       * @return {Promise} Resolved when decided and maybe panel-added.
-       */
+          * Maybe add the copy panel if it's not throttled and passes other checks.
+          * @return {Promise} Resolved when decided and maybe panel-added.
+          */
       maybeAddCopyPanel: function maybeAddCopyPanel() {var _this7 = this;
         // Don't bother adding the copy panel if we're in private browsing or
         // the user wants to never see it again or we've shown it enough times.
-        if (PrivateBrowsingUtils.isWindowPrivate(window) || 
-        Services.prefs.getBoolPref("loop.copy.shown") || 
+        if (PrivateBrowsingUtils.isWindowPrivate(window) ||
+        Services.prefs.getBoolPref("loop.copy.shown") ||
         Services.prefs.getIntPref("loop.copy.showLimit") <= 0) {
-          return Promise.resolve();}
-
+          return Promise.resolve();
+        }
 
-        return Throttler.check("loop.copy").then(function () {return _this7.addCopyPanel();});}, 
-
+        return Throttler.check("loop.copy").then(function () {return _this7.addCopyPanel();});
+      },
 
       /**
-       * Hook into the location bar copy command to open up the copy panel.
-       * @param {Function} onClickHandled Optional callback for finished clicks.
-       */
-      addCopyPanel: function addCopyPanel(onClickHandled) {var _this8 = this, _arguments = arguments;
+          * Hook into the location bar copy command to open up the copy panel.
+          * @param {Function} onClickHandled Optional callback for finished clicks.
+          */
+      addCopyPanel: function addCopyPanel(onClickHandled) {var _this8 = this,_arguments = arguments;
         // Make a copy of the loop panel as a starting point for the copy panel.
         var copy = this.panel.cloneNode(false);
         copy.id = "loop-copy-notification-panel";
         this.panel.parentNode.appendChild(copy);
 
         // Record a telemetry copy panel action.
         var addTelemetry = function addTelemetry(bucket) {
-          _this8.LoopAPI.sendMessageToHandler({ 
-            data: ["LOOP_COPY_PANEL_ACTIONS", _this8.constants.COPY_PANEL[bucket]], 
-            name: "TelemetryAddValue" });};
+          _this8.LoopAPI.sendMessageToHandler({
+            data: ["LOOP_COPY_PANEL_ACTIONS", _this8.constants.COPY_PANEL[bucket]],
+            name: "TelemetryAddValue" });
 
-
+        };
 
         // Handle events from the copy panel iframe content.
         var onIframe = function onIframe(iframe) {
           // Watch for events from the copy panel when loaded.
           iframe.addEventListener("DOMContentLoaded", function onLoad() {
             iframe.removeEventListener("DOMContentLoaded", onLoad);
 
             // Size the panel to fit the rendered content adjusting for borders.
             iframe.contentWindow.requestAnimationFrame(function () {
               var height = iframe.contentDocument.documentElement.offsetHeight;
               height += copy.boxObject.height - iframe.boxObject.height;
-              copy.style.height = height + "px";});
-
+              copy.style.height = height + "px";
+            });
 
             // Hide the copy panel then show the loop panel.
             iframe.contentWindow.addEventListener("CopyPanelClick", function (event) {
               iframe.parentNode.hidePopup();
 
               // Show the Loop panel if the user wants it.
               var _event$detail = event.detail;var accept = _event$detail.accept;var stop = _event$detail.stop;
               if (accept) {
-                LoopUI.openPanel();}
-
+                LoopUI.openPanel();
+              }
 
               // Stop showing the panel if the user says so.
               if (stop) {
                 LoopUI.removeCopyPanel();
-                Services.prefs.setBoolPref("loop.copy.shown", true);}
-
+                Services.prefs.setBoolPref("loop.copy.shown", true);
+              }
 
               // Generate the appropriate NO_AGAIN, NO_NEVER, YES_AGAIN,
               // YES_NEVER probe based on the user's action.
               var probe = (accept ? "YES" : "NO") + "_" + (stop ? "NEVER" : "AGAIN");
               addTelemetry(probe);
 
               // For testing, indicate that handling the click has finished.
               try {
-                onClickHandled(event.detail);} 
-              catch (ex) {
+                onClickHandled(event.detail);
+              } catch (ex) {
                 // Do nothing.
-              }});});};
-
-
-
+              }
+            });
+          });
+        };
 
         // Override the default behavior of the copy command.
         var controller = gURLBar._copyCutController;
         controller._doCommand = controller.doCommand;
         controller.doCommand = function () {
           // Do the normal behavior first.
           controller._doCommand.apply(controller, _arguments);
 
           // Remove the panel if the user has seen it enough times.
           var showLimit = Services.prefs.getIntPref("loop.copy.showLimit");
           if (showLimit <= 0) {
             LoopUI.removeCopyPanel();
-            return;}
-
+            return;
+          }
 
           // Don't bother prompting the user if already sharing.
           if (_this8.MozLoopService.screenShareActive) {
-            return;}
-
+            return;
+          }
 
           // Update various counters.
           Services.prefs.setIntPref("loop.copy.showLimit", showLimit - 1);
           addTelemetry("SHOWN");
 
           // Open up the copy panel at the loop button.
-          LoopUI.PanelFrame.showPopup(window, LoopUI.toolbarButton.anchor, "loop-copy", 
-          null, "chrome://loop/content/panels/copy.html", null, onIframe);};}, 
-
-
+          LoopUI.PanelFrame.showPopup(window, LoopUI.toolbarButton.anchor, "loop-copy",
+          null, "chrome://loop/content/panels/copy.html", null, onIframe);
+        };
+      },
 
       /**
-       * Removes the copy panel copy hook and the panel.
-       */
+          * Removes the copy panel copy hook and the panel.
+          */
       removeCopyPanel: function removeCopyPanel() {
         var controller = gURLBar && gURLBar._copyCutController;
         if (controller && controller._doCommand) {
           controller.doCommand = controller._doCommand;
-          delete controller._doCommand;}
-
+          delete controller._doCommand;
+        }
 
         var copy = document.getElementById("loop-copy-notification-panel");
         if (copy) {
-          copy.parentNode.removeChild(copy);}}, 
-
-
+          copy.parentNode.removeChild(copy);
+        }
+      },
 
       // Implements nsIObserver
       observe: function observe(subject, topic, data) {
         if (topic != "loop-status-changed") {
-          return;}
-
-        this.updateToolbarState(data);}, 
-
+          return;
+        }
+        this.updateToolbarState(data);
+      },
 
       /**
-       * Updates the toolbar/menu-button state to reflect Loop status. This should
-       * not be called from the hidden window.
-       *
-       * @param {string} [aReason] Some states are only shown if
-       *                           a related reason is provided.
-       *
-       *                 aReason="login": Used after a login is completed
-       *                   successfully. This is used so the state can be
-       *                   temporarily shown until the next state change.
-       */
+          * Updates the toolbar/menu-button state to reflect Loop status. This should
+          * not be called from the hidden window.
+          *
+          * @param {string} [aReason] Some states are only shown if
+          *                           a related reason is provided.
+          *
+          *                 aReason="login": Used after a login is completed
+          *                   successfully. This is used so the state can be
+          *                   temporarily shown until the next state change.
+          */
       updateToolbarState: function updateToolbarState() {var _this9 = this;var aReason = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0];
         if (!this.toolbarButton.node) {
-          return;}
-
+          return;
+        }
         var state = "";
         var mozL10nId = "loop-call-button3";
         var suffix = ".tooltiptext";
         if (this.MozLoopService.errors.size) {
           state = "error";
-          mozL10nId += "-error";} else 
-        if (this.isSlideshowOpen) {
+          mozL10nId += "-error";
+        } else if (this.isSlideshowOpen) {
           state = "slideshow";
-          suffix = ".label";} else 
-        if (this.MozLoopService.screenShareActive) {
+          suffix = ".label";
+        } else if (this.MozLoopService.screenShareActive) {
           state = "action";
-          mozL10nId += "-screensharing";} else 
-        if (aReason == "login" && this.MozLoopService.userProfile) {
+          mozL10nId += "-screensharing";
+        } else if (aReason == "login" && this.MozLoopService.userProfile) {
           state = "active";
           mozL10nId += "-active";
-          suffix += "2";} else 
-        if (this.MozLoopService.doNotDisturb) {
+          suffix += "2";
+        } else if (this.MozLoopService.doNotDisturb) {
           state = "disabled";
-          mozL10nId += "-donotdisturb";} else 
-        if (this.MozLoopService.roomsParticipantsCount > 0) {
+          mozL10nId += "-donotdisturb";
+        } else if (this.MozLoopService.roomsParticipantsCount > 0) {
           state = "active";
           this.roomsWithNonOwners().then(function (roomsWithNonOwners) {
             if (roomsWithNonOwners.length > 0) {
-              mozL10nId += "-participantswaiting";} else 
-            {
-              mozL10nId += "-active";}
-
+              mozL10nId += "-participantswaiting";
+            } else {
+              mozL10nId += "-active";
+            }
 
             suffix += "2";
             _this9.updateTooltiptext(mozL10nId + suffix);
-            _this9.toolbarButton.node.setAttribute("state", state);});
-
-          return;} else 
-        {
-          suffix += "2";}
-
+            _this9.toolbarButton.node.setAttribute("state", state);
+          });
+          return;
+        } else {
+          suffix += "2";
+        }
 
         this.toolbarButton.node.setAttribute("state", state);
-        this.updateTooltiptext(mozL10nId + suffix);}, 
-
+        this.updateTooltiptext(mozL10nId + suffix);
+      },
 
       /**
-       * Updates the tootltiptext to reflect Loop status. This should not be called
-       * from the hidden window.
-       *
-       * @param {string} [mozL10nId] l10n ID that refelct the current
-       *                           Loop status.
-       */
+          * Updates the tootltiptext to reflect Loop status. This should not be called
+          * from the hidden window.
+          *
+          * @param {string} [mozL10nId] l10n ID that refelct the current
+          *                           Loop status.
+          */
       updateTooltiptext: function updateTooltiptext(mozL10nId) {
         this.toolbarButton.node.setAttribute("tooltiptext", mozL10nId);
         var tooltiptext = CustomizableUI.getLocalizedProperty(this.toolbarButton, "tooltiptext");
-        this.toolbarButton.node.setAttribute("tooltiptext", tooltiptext);}, 
-
+        this.toolbarButton.node.setAttribute("tooltiptext", tooltiptext);
+      },
 
       /**
-       * Show a desktop notification when 'do not disturb' isn't enabled.
-       *
-       * @param {Object} options Set of options that may tweak the appearance and
-       *                         behavior of the notification.
-       *                         Option params:
-       *                         - {String}   title       Notification title message
-       *                         - {String}   [message]   Notification body text
-       *                         - {String}   [icon]      Notification icon
-       *                         - {String}   [sound]     Sound to play
-       *                         - {String}   [selectTab] Tab to select when the panel
-       *                                                  opens
-       *                         - {Function} [onclick]   Callback to invoke when
-       *                                                  the notification is clicked.
-       *                                                  Opens the panel by default.
-       */
+          * Show a desktop notification when 'do not disturb' isn't enabled.
+          *
+          * @param {Object} options Set of options that may tweak the appearance and
+          *                         behavior of the notification.
+          *                         Option params:
+          *                         - {String}   title       Notification title message
+          *                         - {String}   [message]   Notification body text
+          *                         - {String}   [icon]      Notification icon
+          *                         - {String}   [sound]     Sound to play
+          *                         - {String}   [selectTab] Tab to select when the panel
+          *                                                  opens
+          *                         - {Function} [onclick]   Callback to invoke when
+          *                                                  the notification is clicked.
+          *                                                  Opens the panel by default.
+          */
       showNotification: function showNotification(options) {var _this10 = this;
         if (this.MozLoopService.doNotDisturb) {
-          return;}
-
+          return;
+        }
 
         if (!options.title) {
-          throw new Error("Missing title, can not display notification");}
+          throw new Error("Missing title, can not display notification");
+        }
 
-
-        var notificationOptions = { 
+        var notificationOptions = {
           body: options.message || "" };
 
         if (options.icon) {
-          notificationOptions.icon = options.icon;}
-
+          notificationOptions.icon = options.icon;
+        }
         if (options.sound) {
           // This will not do anything, until bug bug 1105222 is resolved.
-          notificationOptions.mozbehavior = { 
+          notificationOptions.mozbehavior = {
             soundFile: "" };
 
-          this.playSound(options.sound);}
-
+          this.playSound(options.sound);
+        }
 
         var notification = new window.Notification(options.title, notificationOptions);
         notification.addEventListener("click", function () {
           if (window.closed) {
-            return;}
-
+            return;
+          }
 
           try {
-            window.focus();} 
-          catch (ex) {}
-          // Do nothing.
+            window.focus();
+          } catch (ex) {
 
+          } // Do nothing.
 
           // We need a setTimeout here, otherwise the panel won't show after the
           // window received focus.
           window.setTimeout(function () {
             if (typeof options.onclick == "function") {
-              options.onclick();} else 
-            {
+              options.onclick();
+            } else {
               // Open the Loop panel as a default action.
-              _this10.openPanel(null, options.selectTab || null);}}, 
-
-          0);});}, 
-
-
+              _this10.openPanel(null, options.selectTab || null);
+            }
+          }, 0);
+        });
+      },
 
       /**
-       * Play a sound in this window IF there's no sound playing yet.
-       *
-       * @param {String} name Name of the sound, like 'ringtone' or 'room-joined'
-       */
+          * Play a sound in this window IF there's no sound playing yet.
+          *
+          * @param {String} name Name of the sound, like 'ringtone' or 'room-joined'
+          */
       playSound: function playSound(name) {var _this11 = this;
         if (this.ActiveSound || this.MozLoopService.doNotDisturb) {
-          return;}
-
+          return;
+        }
 
         this.activeSound = new window.Audio();
         this.activeSound.src = "chrome://loop/content/shared/sounds/" + name + ".ogg";
         this.activeSound.load();
         this.activeSound.play();
 
         this.activeSound.addEventListener("ended", function () {
-          _this11.activeSound = undefined;}, 
-        false);}, 
-
+          _this11.activeSound = undefined;
+        }, false);
+      },
 
       /**
-       * Start listening to selected tab changes and notify any content page that's
-       * listening to 'BrowserSwitch' push messages.  Also sets up a "joined"
-       * and "left" listener for LoopRooms so that we can toggle the infobar
-       * sharing messages when people come and go.
-       *
-       * @param {(String)} roomToken  The current room that the link generator is connecting to.
-       */
+          * Start listening to selected tab changes and notify any content page that's
+          * listening to 'BrowserSwitch' push messages.  Also sets up a "joined"
+          * and "left" listener for LoopRooms so that we can toggle the infobar
+          * sharing messages when people come and go.
+          *
+          * @param {(String)} roomToken  The current room that the link generator is connecting to.
+          */
       startBrowserSharing: function startBrowserSharing(roomToken) {var _this12 = this;
         if (!this._listeningToTabSelect) {
           gBrowser.tabContainer.addEventListener("TabSelect", this);
           this._listeningToTabSelect = true;
 
           titleChangedListener = this.handleDOMTitleChanged.bind(this);
 
           this._roomsListener = this.handleRoomJoinedOrLeft.bind(this);
 
           this.LoopRooms.on("joined", this._roomsListener);
           this.LoopRooms.on("left", this._roomsListener);
 
           // Watch for title changes as opposed to location changes as more
           // metadata about the page is available when this event fires.
-          this.mm.addMessageListener("loop@mozilla.org:DOMTitleChanged", 
+          this.mm.addMessageListener("loop@mozilla.org:DOMTitleChanged",
           titleChangedListener);
 
           this._browserSharePaused = false;
 
           // Add this event to the parent gBrowser to avoid adding and removing
           // it for each individual tab's browsers.
           gBrowser.addEventListener("mousemove", this);
-          gBrowser.addEventListener("click", this);}
-
+          gBrowser.addEventListener("click", this);
+        }
 
         this._currentRoomToken = roomToken;
         this._maybeShowBrowserSharingInfoBar(roomToken);
 
         // Get the first window Id for the listener.
         var browser = gBrowser.selectedBrowser;
         return new Promise(function (resolve) {
           if (browser.outerWindowID) {
             resolve(browser.outerWindowID);
-            return;}
-
+            return;
+          }
 
           browser.messageManager.addMessageListener("Browser:Init", function initListener() {
             browser.messageManager.removeMessageListener("Browser:Init", initListener);
-            resolve(browser.outerWindowID);});}).
-
-        then(function (outerWindowID) {return (
-            _this12.LoopAPI.broadcastPushMessage("BrowserSwitch", outerWindowID));});}, 
-
+            resolve(browser.outerWindowID);
+          });
+        }).then(function (outerWindowID) {return (
+            _this12.LoopAPI.broadcastPushMessage("BrowserSwitch", outerWindowID));});
+      },
 
       /**
-       * Stop listening to selected tab changes.
-       */
+          * Stop listening to selected tab changes.
+          */
       stopBrowserSharing: function stopBrowserSharing() {
         if (!this._listeningToTabSelect) {
-          return;}
-
+          return;
+        }
 
         this._hideBrowserSharingInfoBar();
         gBrowser.tabContainer.removeEventListener("TabSelect", this);
         this.LoopRooms.off("joined", this._roomsListener);
         this.LoopRooms.off("left", this._roomsListener);
 
         if (titleChangedListener) {
-          this.mm.removeMessageListener("loop@mozilla.org:DOMTitleChanged", 
+          this.mm.removeMessageListener("loop@mozilla.org:DOMTitleChanged",
           titleChangedListener);
-          titleChangedListener = null;}
-
+          titleChangedListener = null;
+        }
 
         // Remove shared pointers related events
         gBrowser.removeEventListener("mousemove", this);
         gBrowser.removeEventListener("click", this);
         this.removeRemoteCursor();
 
         this._listeningToTabSelect = false;
         this._browserSharePaused = false;
-        this._currentRoomToken = null;}, 
-
+        this._currentRoomToken = null;
+      },
 
       /**
-       *  If sharing is active, paints and positions the remote cursor
-       *  over the screen
-       *
-       *  @param cursorData Object with the correct position for the cursor
-       *                    {
-       *                      ratioX: position on the X axis (percentage value)
-       *                      ratioY: position on the Y axis (percentage value)
-       *                    }
-       */
+          *  If sharing is active, paints and positions the remote cursor
+          *  over the screen
+          *
+          *  @param cursorData Object with the correct position for the cursor
+          *                    {
+          *                      ratioX: position on the X axis (percentage value)
+          *                      ratioY: position on the Y axis (percentage value)
+          *                    }
+          */
       addRemoteCursor: function addRemoteCursor(cursorData) {
         if (this._browserSharePaused || !this._listeningToTabSelect) {
-          return;}
-
+          return;
+        }
 
         var browser = gBrowser.selectedBrowser;
         var cursor = document.getElementById("loop-remote-cursor");
         if (!cursor) {
           // Create a container to keep the pointer inside.
           // This allows us to hide the overflow when out of bounds.
           var cursorContainer = document.createElement("div");
           cursorContainer.setAttribute("id", "loop-remote-cursor-container");
 
           cursor = document.createElement("img");
           cursor.setAttribute("id", "loop-remote-cursor");
           cursorContainer.appendChild(cursor);
           // Note that browser.parent is a xul:stack so container will use
           // 100% of space if no other constrains added.
-          browser.parentNode.appendChild(cursorContainer);}
-
+          browser.parentNode.appendChild(cursorContainer);
+        }
 
         // Update the cursor's position with CSS.
-        cursor.style.left = 
+        cursor.style.left =
         Math.abs(cursorData.ratioX * browser.boxObject.width) + "px";
-        cursor.style.top = 
-        Math.abs(cursorData.ratioY * browser.boxObject.height) + "px";}, 
-
+        cursor.style.top =
+        Math.abs(cursorData.ratioY * browser.boxObject.height) + "px";
+      },
 
       /**
-       *  Adds the ripple effect animation to the cursor to show a click on the
-       *  remote end of the conversation.
-       *  Will only add it when:
-       *  - A click is received (cursorData = true)
-       *  - Sharing is active (this._listeningToTabSelect = true)
-       *  - Remote cursor is being painted (cursor != undefined)
-       *
-       *  @param clickData bool click event
-       */
+          *  Adds the ripple effect animation to the cursor to show a click on the
+          *  remote end of the conversation.
+          *  Will only add it when:
+          *  - A click is received (cursorData = true)
+          *  - Sharing is active (this._listeningToTabSelect = true)
+          *  - Remote cursor is being painted (cursor != undefined)
+          *
+          *  @param clickData bool click event
+          */
       clickRemoteCursor: function clickRemoteCursor(clickData) {
         if (!clickData || !this._listeningToTabSelect) {
-          return;}
-
+          return;
+        }
 
         var class_name = "clicked";
         var cursor = document.getElementById("loop-remote-cursor");
         if (!cursor) {
-          return;}
-
+          return;
+        }
 
         cursor.classList.add(class_name);
 
         // after the proper time, we get rid of the animation
         window.setTimeout(function () {
-          cursor.classList.remove(class_name);}, 
-        CURSOR_CLICK_DELAY);}, 
-
+          cursor.classList.remove(class_name);
+        }, CURSOR_CLICK_DELAY);
+      },
 
       /**
-       *  Removes the remote cursor from the screen
-       */
+          *  Removes the remote cursor from the screen
+          */
       removeRemoteCursor: function removeRemoteCursor() {
         var cursor = document.getElementById("loop-remote-cursor");
 
         if (cursor) {
-          cursor.parentNode.removeChild(cursor);}}, 
-
-
+          cursor.parentNode.removeChild(cursor);
+        }
+      },
 
       /**
-       * Helper function to fetch a localized string via the MozLoopService API.
-       * It's currently inconveniently wrapped inside a string of stringified JSON.
-       *
-       * @param  {String} key The element id to get strings for.
-       * @return {String}
-       */
+          * Helper function to fetch a localized string via the MozLoopService API.
+          * It's currently inconveniently wrapped inside a string of stringified JSON.
+          *
+          * @param  {String} key The element id to get strings for.
+          * @return {String}
+          */
       _getString: function _getString(key) {
         var str = this.MozLoopService.getStrings(key);
         if (str) {
-          str = JSON.parse(str).textContent;}
-
-        return str;}, 
-
+          str = JSON.parse(str).textContent;
+        }
+        return str;
+      },
 
       /**
-       * Set correct strings for infobar notification based on if paused or empty.
-       */
+          * Set correct strings for infobar notification based on if paused or empty.
+          */
 
       _setInfoBarStrings: function _setInfoBarStrings(nonOwnerParticipants, sharePaused) {
         var message = void 0;
         if (nonOwnerParticipants) {
           // More than just the owner in the room.
           message = this._getString(
-          sharePaused ? "infobar_screenshare_stop_sharing_message2" : 
-          "infobar_screenshare_browser_message3");} else 
+          sharePaused ? "infobar_screenshare_stop_sharing_message2" :
+          "infobar_screenshare_browser_message3");
 
-        {
+        } else {
           // Just the owner in the room.
           message = this._getString(
-          sharePaused ? "infobar_screenshare_stop_no_guest_message" : 
-          "infobar_screenshare_no_guest_message");}
-
+          sharePaused ? "infobar_screenshare_stop_no_guest_message" :
+          "infobar_screenshare_no_guest_message");
+        }
         var label = this._getString(
         sharePaused ? "infobar_button_restart_label2" : "infobar_button_stop_label2");
         var accessKey = this._getString(
         sharePaused ? "infobar_button_restart_accesskey" : "infobar_button_stop_accesskey");
 
-        return { message: message, label: label, accesskey: accessKey };}, 
-
+        return { message: message, label: label, accesskey: accessKey };
+      },
 
       /**
-       * Indicates if tab sharing is paused.
-       * Set by tab pause button, startBrowserSharing and stopBrowserSharing.
-       * Defaults to false as link generator(owner) enters room we are sharing tabs.
-       */
-      _browserSharePaused: false, 
+          * Indicates if tab sharing is paused.
+          * Set by tab pause button, startBrowserSharing and stopBrowserSharing.
+          * Defaults to false as link generator(owner) enters room we are sharing tabs.
+          */
+      _browserSharePaused: false,
 
       /**
-       * Stores details about the last notification.
-       *
-       * @type {Object}
-       */
-      _lastNotification: {}, 
+                                   * Stores details about the last notification.
+                                   *
+                                   * @type {Object}
+                                   */
+      _lastNotification: {},
 
       /**
-       * Used to determine if the browser sharing info bar is currently being
-       * shown or not.
-       */
+                              * Used to determine if the browser sharing info bar is currently being
+                              * shown or not.
+                              */
       _showingBrowserSharingInfoBar: function _showingBrowserSharingInfoBar() {
         var browser = gBrowser.selectedBrowser;
         var box = gBrowser.getNotificationBox(browser);
         var notification = box.getNotificationWithValue(kBrowserSharingNotificationId);
 
-        return !!notification;}, 
-
+        return !!notification;
+      },
 
       /**
-       * Shows an infobar notification at the top of the browser window that warns
-       * the user that their browser tabs are being broadcasted through the current
-       * conversation.
-       * @param  {String} currentRoomToken Room we are currently joined.
-       * @return {void}
-       */
+          * Shows an infobar notification at the top of the browser window that warns
+          * the user that their browser tabs are being broadcasted through the current
+          * conversation.
+          * @param  {String} currentRoomToken Room we are currently joined.
+          * @return {void}
+          */
       _maybeShowBrowserSharingInfoBar: function _maybeShowBrowserSharingInfoBar(currentRoomToken) {var _this13 = this;
         var participantsCount = this.LoopRooms.getNumParticipants(currentRoomToken);
 
         if (this._showingBrowserSharingInfoBar()) {
           // When we first open the room, there will be one or zero partipicants
           // in the room. The notification box changes when there's more than one,
           // so work that out here.
           var notAlone = participantsCount > 1;
           var previousNotAlone = this._lastNotification.participantsCount <= 1;
 
           // If we're not actually changing the notification bar, then don't
           // re-display it. This avoids the bar sliding in twice.
-          if (notAlone !== previousNotAlone && 
+          if (notAlone !== previousNotAlone &&
           this._browserSharePaused === this._lastNotification.paused) {
-            return;}
+            return;
+          }
 
-
-          this._hideBrowserSharingInfoBar();}
-
+          this._hideBrowserSharingInfoBar();
+        }
 
         var initStrings = this._setInfoBarStrings(participantsCount > 1, this._browserSharePaused);
 
         var box = gBrowser.getNotificationBox();
         var bar = box.appendNotification(
         initStrings.message, // label
         kBrowserSharingNotificationId, // value
         // Icon defined in browser theme CSS.
         null, // image
         box.PRIORITY_WARNING_LOW, // priority
         [{ // buttons (Pause, Stop)
-          label: initStrings.label, 
-          accessKey: initStrings.accesskey, 
-          isDefault: false, 
+          label: initStrings.label,
+          accessKey: initStrings.accesskey,
+          isDefault: false,
           callback: function callback(event, buttonInfo, buttonNode) {
             _this13._browserSharePaused = !_this13._browserSharePaused;
             var guestPresent = _this13.LoopRooms.getNumParticipants(_this13._currentRoomToken) > 1;
             var stringObj = _this13._setInfoBarStrings(guestPresent, _this13._browserSharePaused);
             bar.label = stringObj.message;
             bar.classList.toggle("paused", _this13._browserSharePaused);
             buttonNode.label = stringObj.label;
             buttonNode.accessKey = stringObj.accesskey;
             LoopUI.MozLoopService.toggleBrowserSharing(_this13._browserSharePaused);
             if (_this13._browserSharePaused) {
               // if paused we stop sharing remote cursors
-              _this13.removeRemoteCursor();}
-
-            return true;}, 
+              _this13.removeRemoteCursor();
+            }
+            return true;
+          },
+          type: "pause" },
 
-          type: "pause" }, 
-
-        { 
-          label: this._getString("infobar_button_disconnect_label"), 
-          accessKey: this._getString("infobar_button_disconnect_accesskey"), 
-          isDefault: true, 
+        {
+          label: this._getString("infobar_button_disconnect_label"),
+          accessKey: this._getString("infobar_button_disconnect_accesskey"),
+          isDefault: true,
           callback: function callback() {
             _this13.removeRemoteCursor();
             _this13._hideBrowserSharingInfoBar();
-            LoopUI.MozLoopService.hangupAllChatWindows();}, 
-
+            LoopUI.MozLoopService.hangupAllChatWindows();
+          },
           type: "stop" }]);
 
 
 
         // Sets 'paused' class if needed.
         bar.classList.toggle("paused", !!this._browserSharePaused);
 
         // Keep showing the notification bar until the user explicitly closes it.
         bar.persistence = -1;
 
         this._lastNotification.participantsCount = participantsCount;
-        this._lastNotification.paused = this._browserSharePaused;}, 
-
+        this._lastNotification.paused = this._browserSharePaused;
+      },
 
       /**
-       * Hides the infobar, permanantly if requested.
-       *
-       * @param   {Object}  browser Optional link to the browser we want to
-       *                    remove the infobar from. If not present, defaults
-       *                    to current browser instance.
-       * @return  {Boolean} |true| if the infobar was hidden here.
-       */
+          * Hides the infobar, permanantly if requested.
+          *
+          * @param   {Object}  browser Optional link to the browser we want to
+          *                    remove the infobar from. If not present, defaults
+          *                    to current browser instance.
+          * @return  {Boolean} |true| if the infobar was hidden here.
+          */
       _hideBrowserSharingInfoBar: function _hideBrowserSharingInfoBar(browser) {
         browser = browser || gBrowser.selectedBrowser;
         var box = gBrowser.getNotificationBox(browser);
         var notification = box.getNotificationWithValue(kBrowserSharingNotificationId);
         var removed = false;
         if (notification) {
           box.removeNotification(notification);
-          removed = true;}
-
+          removed = true;
+        }
 
-        return removed;}, 
-
+        return removed;
+      },
 
       /**
-       * Broadcast 'BrowserSwitch' event.
-       */
+          * Broadcast 'BrowserSwitch' event.
+          */
       _notifyBrowserSwitch: function _notifyBrowserSwitch() {
         // Get the first window Id for the listener.
-        this.LoopAPI.broadcastPushMessage("BrowserSwitch", 
-        gBrowser.selectedBrowser.outerWindowID);}, 
-
+        this.LoopAPI.broadcastPushMessage("BrowserSwitch",
+        gBrowser.selectedBrowser.outerWindowID);
+      },
 
       /**
-       * Handles updating of the sharing infobar when the room participants
-       * change.
-       */
+          * Handles updating of the sharing infobar when the room participants
+          * change.
+          */
       handleRoomJoinedOrLeft: function handleRoomJoinedOrLeft() {
         // Don't attempt to show it if we're not actively sharing.
         if (!this._listeningToTabSelect) {
-          return;}
-
-        this._maybeShowBrowserSharingInfoBar(this._currentRoomToken);}, 
-
+          return;
+        }
+        this._maybeShowBrowserSharingInfoBar(this._currentRoomToken);
+      },
 
       /**
-       * Handles events from the frame script.
-       *
-       * @param {Object} message The message received from the frame script.
-       */
+          * Handles events from the frame script.
+          *
+          * @param {Object} message The message received from the frame script.
+          */
       handleDOMTitleChanged: function handleDOMTitleChanged(message) {
         if (!this._listeningToTabSelect || this._browserSharePaused) {
-          return;}
-
+          return;
+        }
 
         if (gBrowser.selectedBrowser == message.target) {
           // Get the new title of the shared tab
-          this._notifyBrowserSwitch();}}, 
-
-
+          this._notifyBrowserSwitch();
+        }
+      },
 
       /**
-       * Handles events from gBrowser.
-       */
+          * Handles events from gBrowser.
+          */
       handleEvent: function handleEvent(event) {
 
         switch (event.type) {
           case "TabSelect":{
               var wasVisible = false;
               // Hide the infobar from the previous tab.
               if (event.detail.previousTab) {
                 wasVisible = this._hideBrowserSharingInfoBar(
                 event.detail.previousTab.linkedBrowser);
                 // And remove the cursor.
-                this.removeRemoteCursor();}
-
+                this.removeRemoteCursor();
+              }
 
               // We've changed the tab, so get the new window id.
               this._notifyBrowserSwitch();
 
               if (wasVisible) {
                 // If the infobar was visible before, we should show it again after the
                 // switch.
-                this._maybeShowBrowserSharingInfoBar(this._currentRoomToken);}
-
-              break;}
-
+                this._maybeShowBrowserSharingInfoBar(this._currentRoomToken);
+              }
+              break;
+            }
           case "mousemove":
             this.handleMousemove(event);
             break;
           case "click":
             this.handleMouseClick(event);
-            break;}}, 
+            break;}
 
-
+      },
 
       /**
-       * Handles mousemove events from gBrowser and send a broadcast message
-       * with all the data needed for sending link generator cursor position
-       * through the sdk.
-       */
+          * Handles mousemove events from gBrowser and send a broadcast message
+          * with all the data needed for sending link generator cursor position
+          * through the sdk.
+          */
       handleMousemove: function handleMousemove(event) {
         // Won't send events if not sharing (paused or not started).
         if (this._browserSharePaused || !this._listeningToTabSelect) {
-          return;}
-
+          return;
+        }
 
         // Only update every so often.
         var now = Date.now();
         if (now - this.lastCursorTime < CURSOR_MIN_INTERVAL) {
-          return;}
-
+          return;
+        }
         this.lastCursorTime = now;
 
         // Skip the update if cursor is out of bounds or didn't move much.
         var browserBox = gBrowser.selectedBrowser.boxObject;
         var deltaX = event.screenX - browserBox.screenX;
         var deltaY = event.screenY - browserBox.screenY;
-        if (deltaX < 0 || deltaX > browserBox.width || 
-        deltaY < 0 || deltaY > browserBox.height || 
-        Math.abs(deltaX - this.lastCursorX) < CURSOR_MIN_DELTA && 
+        if (deltaX < 0 || deltaX > browserBox.width ||
+        deltaY < 0 || deltaY > browserBox.height ||
+        Math.abs(deltaX - this.lastCursorX) < CURSOR_MIN_DELTA &&
         Math.abs(deltaY - this.lastCursorY) < CURSOR_MIN_DELTA) {
-          return;}
-
+          return;
+        }
         this.lastCursorX = deltaX;
         this.lastCursorY = deltaY;
 
-        this.LoopAPI.broadcastPushMessage("CursorPositionChange", { 
-          ratioX: deltaX / browserBox.width, 
-          ratioY: deltaY / browserBox.height });}, 
+        this.LoopAPI.broadcastPushMessage("CursorPositionChange", {
+          ratioX: deltaX / browserBox.width,
+          ratioY: deltaY / browserBox.height });
 
-
+      },
 
       /**
-       * Handles mouse click events from gBrowser and send a broadcast message
-       * with all the data needed for sending link generator cursor click position
-       * through the sdk.
-       */
+          * Handles mouse click events from gBrowser and send a broadcast message
+          * with all the data needed for sending link generator cursor click position
+          * through the sdk.
+          */
       handleMouseClick: function handleMouseClick() {
         // We want to stop sending events if sharing is paused.
         if (this._browserSharePaused) {
-          return;}
-
+          return;
+        }
 
-        this.LoopAPI.broadcastPushMessage("CursorClick");}, 
-
+        this.LoopAPI.broadcastPushMessage("CursorClick");
+      },
 
       /**
-       * Fetch the favicon of the currently selected tab in the format of a data-uri.
-       *
-       * @param  {Function} callback Function to be invoked with an error object as
-       *                             its first argument when an error occurred or
-       *                             a string as second argument when the favicon
-       *                             has been fetched.
-       */
+          * Fetch the favicon of the currently selected tab in the format of a data-uri.
+          *
+          * @param  {Function} callback Function to be invoked with an error object as
+          *                             its first argument when an error occurred or
+          *                             a string as second argument when the favicon
+          *                             has been fetched.
+          */
       getFavicon: function getFavicon(callback) {
         var pageURI = gBrowser.selectedTab.linkedBrowser.currentURI.spec;
         // If the tab page’s url starts with http(s), fetch icon.
         if (!/^https?:/.test(pageURI)) {
           callback();
-          return;}
-
+          return;
+        }
 
         this.PlacesUtils.promiseFaviconLinkUrl(pageURI).then(function (uri) {
           // We XHR the favicon to get a File object, which we can pass to the FileReader
           // object. The FileReader turns the File object into a data-uri.
           var xhr = xhrClass.createInstance(Ci.nsIXMLHttpRequest);
           xhr.open("get", uri.spec, true);
           xhr.responseType = "blob";
           xhr.overrideMimeType("image/x-icon");
           xhr.onload = function () {
             if (xhr.status != 200) {
               callback(new Error("Invalid status code received for favicon XHR: " + xhr.status));
-              return;}
-
+              return;
+            }
 
             var reader = new FileReader();
             reader.onload = reader.onload = function () {return callback(null, reader.result);};
             reader.onerror = callback;
-            reader.readAsDataURL(xhr.response);};
-
+            reader.readAsDataURL(xhr.response);
+          };
           xhr.onerror = callback;
-          xhr.send();}).
-        catch(function (err) {
-          callback(err || new Error("No favicon found"));});} };
-
-
+          xhr.send();
+        }).catch(function (err) {
+          callback(err || new Error("No favicon found"));
+        });
+      } };
 
 
     XPCOMUtils.defineLazyModuleGetter(LoopUI, "hookWindowCloseForPanelClose", "resource://gre/modules/MozSocialAPI.jsm");
     XPCOMUtils.defineLazyModuleGetter(LoopUI, "LoopAPI", "chrome://loop/content/modules/MozLoopAPI.jsm");
     XPCOMUtils.defineLazyModuleGetter(LoopUI, "LoopRooms", "chrome://loop/content/modules/LoopRooms.jsm");
     XPCOMUtils.defineLazyModuleGetter(LoopUI, "MozLoopService", "chrome://loop/content/modules/MozLoopService.jsm");
     XPCOMUtils.defineLazyModuleGetter(LoopUI, "PanelFrame", "resource:///modules/PanelFrame.jsm");
     XPCOMUtils.defineLazyModuleGetter(LoopUI, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm");
 
     LoopUI.init();
     window.LoopUI = LoopUI;
 
     // Export the Throttler to allow tests to overwrite parts of it.
-    window.LoopThrottler = Throttler;}, 
-
+    window.LoopThrottler = Throttler;
+  },
 
   /**
-   * Take any steps to remove UI or anything from the browser window
-   * document.getElementById() etc. will work here.
-   *
-   * @param {Object} window The window to remove the integration from.
-   */
+      * Take any steps to remove UI or anything from the browser window
+      * document.getElementById() etc. will work here.
+      *
+      * @param {Object} window The window to remove the integration from.
+      */
   tearDownBrowserUI: function tearDownBrowserUI(window) {
     if (window.LoopUI) {
       window.LoopUI.removeCopyPanel();
       window.LoopUI.removeMenuItem();
 
       // This stops the frame script being loaded to new tabs, but doesn't
       // remove it from existing tabs (there's no way to do that).
       window.LoopUI.mm.removeDelayedFrameScript(FRAME_SCRIPT);
 
       // XXX Bug 1229352 - Add in tear-down of the panel.
-    }}, 
-
+    }
+  },
 
   // nsIWindowMediatorListener functions.
   onOpenWindow: function onOpenWindow(xulWindow) {
     // A new window has opened.
     var domWindow = xulWindow.QueryInterface(Ci.nsIInterfaceRequestor).
     getInterface(Ci.nsIDOMWindow);
 
     // Wait for it to finish loading.
     domWindow.addEventListener("load", function listener() {
       domWindow.removeEventListener("load", listener, false);
 
       // If this is a browser window then setup its UI.
       if (domWindow.document.documentElement.getAttribute("windowtype") == "navigator:browser") {
-        WindowListener.setupBrowserUI(domWindow);}}, 
-
-    false);}, 
-
+        WindowListener.setupBrowserUI(domWindow);
+      }
+    }, false);
+  },
 
-  onCloseWindow: function onCloseWindow() {}, 
-
+  onCloseWindow: function onCloseWindow() {
+  },
 
-  onWindowTitleChange: function onWindowTitleChange() {} };
-
+  onWindowTitleChange: function onWindowTitleChange() {
+  } };
 
 
 /**
- * Provide a way to throttle functionality using DNS to distribute 3 numbers for
- * various distributions channels. DNS is used to scale distribution of the
- * numbers as an A record pointing to a loopback address (127.*.*.*). Prefs are
- * used to control behavior (what domain to check) and keep state (a ticket
- * number to track if it needs to initialize, to wait for its turn, or is
- * completed).
- */
-var Throttler = { 
+        * Provide a way to throttle functionality using DNS to distribute 3 numbers for
+        * various distributions channels. DNS is used to scale distribution of the
+        * numbers as an A record pointing to a loopback address (127.*.*.*). Prefs are
+        * used to control behavior (what domain to check) and keep state (a ticket
+        * number to track if it needs to initialize, to wait for its turn, or is
+        * completed).
+        */
+var Throttler = {
   // Each 8-bit block of the IP address allows for 0% rollout (value 0) to 100%
   // rollout (value 255).
-  TICKET_LIMIT: 255, 
+  TICKET_LIMIT: 255,
 
   // Allow the DNS service to be overwritten for testing.
-  _dns: Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService), 
+  _dns: Cc["@mozilla.org/network/dns-service;1"].getService(Ci.nsIDNSService),
 
   /**
-   * Check if a given feature should be throttled or not.
-   * @param {string} [prefPrefix] Start of the preference name for the feature.
-   * @return {Promise} Resolved on success, and rejected on throttled.
-   */
+                                                                                * Check if a given feature should be throttled or not.
+                                                                                * @param {string} [prefPrefix] Start of the preference name for the feature.
+                                                                                * @return {Promise} Resolved on success, and rejected on throttled.
+                                                                                */
   check: function check(prefPrefix) {var _this14 = this;
     return new Promise(function (resolve, reject) {
       // Initialize the ticket (0-254) if it doesn't have a valid value yet.
       var prefTicket = prefPrefix + ".ticket";
       var ticket = Services.prefs.getIntPref(prefTicket);
       if (ticket < 0) {
         ticket = Math.floor(Math.random() * _this14.TICKET_LIMIT);
-        Services.prefs.setIntPref(prefTicket, ticket);}
-
+        Services.prefs.setIntPref(prefTicket, ticket);
+      }
       // Short circuit if the special ticket value indicates we're good to go.
       else if (ticket >= _this14.TICKET_LIMIT) {
           resolve();
-          return;}
-
+          return;
+        }
 
       // Handle responses from the DNS resolution service request.
       var onDNS = function onDNS(request, record) {
         // Failed to get A-record, so skip for now.
         if (record === null) {
           reject();
-          return;}
-
+          return;
+        }
 
         // Ensure we have a special loopback value before checking other blocks.
         var ipBlocks = record.getNextAddrAsString().split(".");
         if (ipBlocks[0] !== "127") {
           reject();
-          return;}
-
+          return;
+        }
 
         // Use a specific part of the A-record IP address depending on the
         // channel. I.e., 127.[release/other].[beta].[aurora/nightly].
         var index = 1;
         switch (Services.prefs.getCharPref("app.update.channel")) {
           case "beta":
             index = 2;
             break;
@@ -1282,214 +1282,214 @@ var Throttler = {
             break;}
 
 
         // Select the 1 out of 4 parts of the "."-separated IP address to check
         // if the 8-bit threshold (0-255) exceeds the ticket (0-254).
         if (ticket < ipBlocks[index]) {
           // Remember that we're good to go to avoid future DNS checks.
           Services.prefs.setIntPref(prefTicket, _this14.TICKET_LIMIT);
-          resolve();} else 
-
+          resolve();
+        } else
         {
-          reject();}};
-
-
+          reject();
+        }
+      };
 
       // Look up the DNS A-record of a throttler hostname to decide to show.
-      _this14._dns.asyncResolve(Services.prefs.getCharPref(prefPrefix + ".throttler"), 
-      _this14._dns.RESOLVE_DISABLE_IPV6, onDNS, Services.tm.mainThread);});} };
-
-
+      _this14._dns.asyncResolve(Services.prefs.getCharPref(prefPrefix + ".throttler"),
+      _this14._dns.RESOLVE_DISABLE_IPV6, onDNS, Services.tm.mainThread);
+    });
+  } };
 
 
 /**
- * Creates the loop button on the toolbar. Due to loop being a system-addon
- * CustomizableUI already has a placement location for the button, so that
- * we can be on the toolbar.
- */
+        * Creates the loop button on the toolbar. Due to loop being a system-addon
+        * CustomizableUI already has a placement location for the button, so that
+        * we can be on the toolbar.
+        */
 function createLoopButton() {
-  CustomizableUI.createWidget({ 
-    id: "loop-button", 
-    type: "custom", 
-    label: "loop-call-button3.label", 
-    tooltiptext: "loop-call-button3.tooltiptext2", 
-    privateBrowsingTooltiptext: "loop-call-button3-pb.tooltiptext", 
-    defaultArea: CustomizableUI.AREA_NAVBAR, 
-    removable: true, 
+  CustomizableUI.createWidget({
+    id: "loop-button",
+    type: "custom",
+    label: "loop-call-button3.label",
+    tooltiptext: "loop-call-button3.tooltiptext2",
+    privateBrowsingTooltiptext: "loop-call-button3-pb.tooltiptext",
+    defaultArea: CustomizableUI.AREA_NAVBAR,
+    removable: true,
     onBuild: function onBuild(aDocument) {
       // If we're not supposed to see the button, return zip.
       if (!Services.prefs.getBoolPref("loop.enabled")) {
-        return null;}
-
+        return null;
+      }
 
       var isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(aDocument.defaultView);
 
       var node = aDocument.createElementNS(kNSXUL, "toolbarbutton");
       node.setAttribute("id", this.id);
       node.classList.add("toolbarbutton-1");
       node.classList.add("chromeclass-toolbar-additional");
       node.classList.add("badged-button");
       node.setAttribute("label", CustomizableUI.getLocalizedProperty(this, "label"));
       if (isWindowPrivate) {
-        node.setAttribute("disabled", "true");}
-
-      var tooltiptext = isWindowPrivate ? 
-      CustomizableUI.getLocalizedProperty(this, "privateBrowsingTooltiptext", 
-      [CustomizableUI.getLocalizedProperty(this, "label")]) : 
+        node.setAttribute("disabled", "true");
+      }
+      var tooltiptext = isWindowPrivate ?
+      CustomizableUI.getLocalizedProperty(this, "privateBrowsingTooltiptext",
+      [CustomizableUI.getLocalizedProperty(this, "label")]) :
       CustomizableUI.getLocalizedProperty(this, "tooltiptext");
       node.setAttribute("tooltiptext", tooltiptext);
       node.setAttribute("removable", "true");
       node.addEventListener("command", function (event) {
-        aDocument.defaultView.LoopUI.togglePanel(event);});
-
+        aDocument.defaultView.LoopUI.togglePanel(event);
+      });
 
-      return node;} });}
+      return node;
+    } });
 
-
-
+}
 
 /**
- * Loads the default preferences from the prefs file. This loads the preferences
- * into the default branch, so they don't appear as user preferences.
- */
+   * Loads the default preferences from the prefs file. This loads the preferences
+   * into the default branch, so they don't appear as user preferences.
+   */
 function loadDefaultPrefs() {
   var branch = Services.prefs.getDefaultBranch("");
-  Services.scriptloader.loadSubScript("chrome://loop/content/preferences/prefs.js", { 
+  Services.scriptloader.loadSubScript("chrome://loop/content/preferences/prefs.js", {
     pref: function pref(key, val) {
       // If a previously set default pref exists don't overwrite it.  This can
       // happen for ESR or distribution.ini.
       if (branch.getPrefType(key) != branch.PREF_INVALID) {
-        return;}
-
+        return;
+      }
       switch (typeof val === "undefined" ? "undefined" : _typeof(val)) {
         case "boolean":
           branch.setBoolPref(key, val);
           break;
         case "number":
           branch.setIntPref(key, val);
           break;
         case "string":
           branch.setCharPref(key, val);
-          break;}} });
+          break;}
 
-
+    } });
 
 
   if (Services.vc.compare(Services.appinfo.version, "47.0a1") < 0) {
-    branch.setBoolPref("loop.remote.autostart", false);}}
-
-
+    branch.setBoolPref("loop.remote.autostart", false);
+  }
+}
 
 /**
- * Called when the add-on is started, e.g. when installed or when Firefox starts.
- */
+   * Called when the add-on is started, e.g. when installed or when Firefox starts.
+   */
 function startup(data) {
   // Record the add-on version for when the UI is initialised.
   WindowListener.addonVersion = data.version;
 
   loadDefaultPrefs();
   if (!Services.prefs.getBoolPref("loop.enabled")) {
-    return;}
-
+    return;
+  }
 
   createLoopButton();
 
   // Attach to hidden window (for OS X).
   if (AppConstants.platform == "macosx") {
     try {
-      WindowListener.setupBrowserUI(Services.appShell.hiddenDOMWindow);} 
-    catch (ex) {(function () {
+      WindowListener.setupBrowserUI(Services.appShell.hiddenDOMWindow);
+    } catch (ex) {(function () {
         // Hidden window didn't exist, so wait until startup is done.
         var topic = "browser-delayed-startup-finished";
         Services.obs.addObserver(function observer() {
           Services.obs.removeObserver(observer, topic);
-          WindowListener.setupBrowserUI(Services.appShell.hiddenDOMWindow);}, 
-        topic, false);})();}}
-
-
+          WindowListener.setupBrowserUI(Services.appShell.hiddenDOMWindow);
+        }, topic, false);})();
+    }
+  }
 
   // Attach to existing browser windows, for modifying UI.
   var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
   var windows = wm.getEnumerator("navigator:browser");
   while (windows.hasMoreElements()) {
     var domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
-    WindowListener.setupBrowserUI(domWindow);}
-
+    WindowListener.setupBrowserUI(domWindow);
+  }
 
   // Wait for any new browser windows to open.
   wm.addListener(WindowListener);
 
   // Load our stylesheets.
   var styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"].
   getService(Components.interfaces.nsIStyleSheetService);
   var sheets = [
-  "chrome://loop-shared/skin/loop.css", 
+  "chrome://loop-shared/skin/loop.css",
   "chrome://loop/skin/platform.css"];var _iteratorNormalCompletion2 = true;var _didIteratorError2 = false;var _iteratorError2 = undefined;try {
 
 
 
     for (var _iterator2 = sheets[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {var sheet = _step2.value;
       var styleSheetURI = Services.io.newURI(sheet, null, null);
-      styleSheetService.loadAndRegisterSheet(styleSheetURI, 
-      styleSheetService.AUTHOR_SHEET);}} catch (err) {_didIteratorError2 = true;_iteratorError2 = err;} finally {try {if (!_iteratorNormalCompletion2 && _iterator2.return) {_iterator2.return();}} finally {if (_didIteratorError2) {throw _iteratorError2;}}}}
-
-
+      styleSheetService.loadAndRegisterSheet(styleSheetURI,
+      styleSheetService.AUTHOR_SHEET);
+    }} catch (err) {_didIteratorError2 = true;_iteratorError2 = err;} finally {try {if (!_iteratorNormalCompletion2 && _iterator2.return) {_iterator2.return();}} finally {if (_didIteratorError2) {throw _iteratorError2;}}}
+}
 
 /**
- * Called when the add-on is shutting down, could be for re-installation
- * or just uninstall.
- */
+   * Called when the add-on is shutting down, could be for re-installation
+   * or just uninstall.
+   */
 function shutdown(data, reason) {
   // Close any open chat windows
   Cu.import("resource:///modules/Chat.jsm");
   var isLoopURL = function isLoopURL(_ref) {var src = _ref.src;return (/^about:loopconversation#/.test(src));};
   [].concat(_toConsumableArray(Chat.chatboxes)).filter(isLoopURL).forEach(function (chatbox) {
-    chatbox.content.contentWindow.close();});
-
+    chatbox.content.contentWindow.close();
+  });
 
   // Detach from hidden window (for OS X).
   if (AppConstants.platform == "macosx") {
-    WindowListener.tearDownBrowserUI(Services.appShell.hiddenDOMWindow);}
-
+    WindowListener.tearDownBrowserUI(Services.appShell.hiddenDOMWindow);
+  }
 
   // Detach from browser windows.
   var wm = Cc["@mozilla.org/appshell/window-mediator;1"].getService(Ci.nsIWindowMediator);
   var windows = wm.getEnumerator("navigator:browser");
   while (windows.hasMoreElements()) {
     var domWindow = windows.getNext().QueryInterface(Ci.nsIDOMWindow);
-    WindowListener.tearDownBrowserUI(domWindow);}
-
+    WindowListener.tearDownBrowserUI(domWindow);
+  }
 
   // Stop waiting for browser windows to open.
   wm.removeListener(WindowListener);
 
   // If the app is shutting down, don't worry about cleaning up, just let
   // it fade away...
   if (reason == APP_SHUTDOWN) {
-    return;}
-
+    return;
+  }
 
   CustomizableUI.destroyWidget("loop-button");
 
   // Unload stylesheets.
   var styleSheetService = Cc["@mozilla.org/content/style-sheet-service;1"].
   getService(Components.interfaces.nsIStyleSheetService);
-  var sheets = ["chrome://loop/content/addon/css/loop.css", 
+  var sheets = ["chrome://loop/content/addon/css/loop.css",
   "chrome://loop/skin/platform.css"];var _iteratorNormalCompletion3 = true;var _didIteratorError3 = false;var _iteratorError3 = undefined;try {
     for (var _iterator3 = sheets[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {var sheet = _step3.value;
       var styleSheetURI = Services.io.newURI(sheet, null, null);
-      if (styleSheetService.sheetRegistered(styleSheetURI, 
+      if (styleSheetService.sheetRegistered(styleSheetURI,
       styleSheetService.AUTHOR_SHEET)) {
-        styleSheetService.unregisterSheet(styleSheetURI, 
-        styleSheetService.AUTHOR_SHEET);}}
-
-
+        styleSheetService.unregisterSheet(styleSheetURI,
+        styleSheetService.AUTHOR_SHEET);
+      }
+    }
 
     // Unload modules.
   } catch (err) {_didIteratorError3 = true;_iteratorError3 = err;} finally {try {if (!_iteratorNormalCompletion3 && _iterator3.return) {_iterator3.return();}} finally {if (_didIteratorError3) {throw _iteratorError3;}}}Cu.unload("chrome://loop/content/modules/MozLoopAPI.jsm");
   Cu.unload("chrome://loop/content/modules/LoopRooms.jsm");
-  Cu.unload("chrome://loop/content/modules/MozLoopService.jsm");}
-
+  Cu.unload("chrome://loop/content/modules/MozLoopService.jsm");
+}
 
 function install() {}
 
 function uninstall() {}
--- a/browser/extensions/loop/chrome/content/modules/DomainWhitelist.jsm
+++ b/browser/extensions/loop/chrome/content/modules/DomainWhitelist.jsm
@@ -2,20 +2,20 @@
  * 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";
 
 /* exported DomainWhitelist */
 this.EXPORTED_SYMBOLS = ["DomainWhitelist"];
 
-this.DomainWhitelist = Object.freeze({ 
+this.DomainWhitelist = Object.freeze({
   check: function check(domain) {
-    return gWhitelist.has(domain);} });
-
+    return gWhitelist.has(domain);
+  } });
 
 
 // Convert the multiline list of domains into a Set for lookup.
 var gWhitelist = new Set("\n01net.com\n07073.com\n10086.cn\n104.com.tw\n1111.com.tw\n114la.com\n11st.co.kr\n120ask.com\n12306.cn\n123cha.com\n123rf.com\n126.com\n1337x.to\n163.com\n1688.com\n16lao.com\n17173.com\n178.com\n17k.com\n17ok.com\n17track.net\n189.cn\n1905.com\n1and1.com\n1edisource.com\n1tv.ru\n1und1.de\n20minutes.fr\n20minutos.es\n2345.com\n247sports.com\n24h.com.vn\n24hourfitness.com\n28.com\n2ch-c.net\n2ch.net\n2chan.net\n2chblog.jp\n2gis.ru\n315che.com\n360.cn\n360.com\n360doc.com\n39.net\n3dmgame.com\n3m.com\n3tailer.com\n42mr.com\n4399.com\n4chan.org\n4dsply.com\n4gamer.net\n4pda.ru\n4shared.com\n500px.com\n51.la\n51auto.com\n51cto.com\n51sole.com\n51yes.com\n525j.com.cn\n58.com\n58pic.com\n5dcar.com\n6park.com\n6pm.com\n7769domain.com\n99acres.com\n9gag.com\na10.com\naa.com\naafp.org\naamc.org\naao.org\naaos.org\naarp.org\naastocks.com\nabc.es\nabc.net.au\nabchina.com\nabebooks.com\nabercrombie.com\nabout.com\nabplive.in\nabril.com.br\nabs-cbn.com\nabsoluteclickscom.com\nacademia.edu\nacademy.com\naccommodationforstudents.com\naccorhotels.com\naccuweather.com\nacer.com\nacfun.tv\nactiverain.com\nad-tech.com\nad4game.com\nadcash.com\nadditudemag.com\naddthis.com\nadf.ly\nadidas.com\nadk2x.com\nadmaimai.com\nadme.ru\nadnetworkperformance.com\nadobe.com\nadorama.com\nadp.com\nadplxmd.com\nadservingsolutionsinc.com\nadservone.com\nadslgate.com\nae.com\naegeanair.com\naerlingus.com\naeroflot.ru\naeromexico.com\naeroplan.com\naerosoles.com\naftonbladet.se\nagar.io\nagoda.com\nahg.com\nahit.com\nahrq.gov\nairarabia.com\nairasia.com\nairastana.com\nairberlin.com\nairbnb.com\naircanada.com\naireuropa.com\nairfrance.com\nairlinequality.com\nairmiles.ca\nairnewzealand.co.nz\nairtel.in\najanshaber.com\nakamaihd.net\nakb48matomemory.com\nalarabiya.net\nalaskaair.com\nalbawabhnews.com\nalexa.cn\nalexa.com\nalfabank.ru\nalfalfalfa.com\nalfredangelo.com\nali213.net\nalibaba.com\nalicdn.com\nalice.it\naliexpress.com\nalimama.com\nalipay.com\nalitalia.com\naliyun.com\naljaras.com\naljazeera.net\nall-free-download.com\nall2lnk.com\nallabout.co.jp\nallegiantair.com\nallegro.pl\nallmyvideos.net\nallocine.fr\nallrecipes.com\nalmasryalyoum.com\naltervista.org\nalwafd.org\nalz.org\nam15.net\nama-assn.org\namadeus.net\namarujala.com\namazon.ca\namazon.cn\namazon.co.jp\namazon.co.uk\namazon.com\namazon.de\namazon.es\namazon.fr\namazon.in\namazon.it\namazonaws.com\nameba.jp\nameblo.jp\namericanas.com.br\namericanexpress.com\namericanschoolnj.com\namorepacific.com\nampclicks.com\nampxchange.com\nana.co.jp\nancestry.com\nandroid.com\nandroidauthority.com\nandroidcentral.com\nangieslist.com\nanitube.se\nanjuke.com\nannualcreditreport.com\nanswers.com\nanthropologie.com\naol.com\napa.org\napache.org\naparat.com\napartmenttherapy.com\naplaceformom.com\napple.com\nappledaily.com.tw\nappraisalbuzz.com\nappraisalinstitute.org\nappraisers.org\nappraisersforum.com\nappraiserusa.com\narbeitsagentur.de\narcelik.com.tr\narchive.org\narchiveofourown.org\narcot.com\narcteryx.com\narduino.cc\nareaa.org\nargaam.com\nargos.co.uk\nariba.com\narinet.com\narstechnica.com\nas.com\nasahi.com\nasana.com\nascii.jp\nasda.com\nasha.org\nashleyfurniture.com\nasia-lists.com\nasiatravel.com\nasicsamerica.com\nask.com\nask.fm\naskmebazaar.com\naskubuntu.com\nasos.com\nasriran.com\nassetline.com\nasus.com\natkins.com\natlassian.net\natt.com\natt.net\natwiki.jp\naucfan.com\nauction.co.kr\naudible.com\naudio-technica.com\nauntyacid.com\nausopen.com\naustrian.com\nauthoritynutrition.com\nauto.ru\nautoblog.com\nautobytel.com\nautodesk.com\nautohome.com.cn\nautoscout24.de\nautotrader.co.uk\nautotrader.com\navast.com\navclub.com\naveda.com\navery.com\navforums.com\navg.com\navira.com\navito.ma\navito.ru\naweber.com\naxia.com\naxisbank.co.in\naxisbank.com\nazet.sk\nazlyrics.com\nb2btech.com\nb3net.com\nb9dm.com\nbab.la\nbabycenter.com\nbabylon.com\nbabytree.com\nbackcountry.com\nbackpage.com\nbackyardchickens.com\nbadoo.com\nbahn.de\nbaidu.com\nbaike.com\nbaimao.com\nbaixaki.com.br\nbandcamp.com\nbanggood.com\nbanki.ru\nbankmellat.ir\nbankofamerica.com\nbankrate.com\nbarbie.com\nbarbour.com\nbarcelo.com\nbarclaycardus.com\nbarclays.co.uk\nbarnesandnoble.com\nbartarinha.ir\nbasecamp.com\nbassettfurniture.com\nbasspro.com\nbastillepost.com\nbathandbodyworks.com\nbattle.net\nbattlefield.com\nbayt.com\nbb.com.br\nbbb.org\nbbc.co.uk\nbbc.com\nbbt.com\nbbteam.com\nbc.vc\nbedandbreakfast.com\nbedbathandbeyond.com\nbeeline.ru\nbehance.net\nbelkin.com\nbenetton.com\nberetta.com\nberkeley.edu\nbestadbid.com\nbestbuy.com\nbestwestern.com\nbet365.com\nbettycrocker.com\nbeytoote.com\nbgr.com\nbhaskar.com\nbhg.com\nbhphotovideo.com\nbiblegateway.com\nbidvertiser.com\nbig5sportinggoods.com\nbiglike.com\nbiglobe.ne.jp\nbild.de\nbilibili.com\nbillboard.com\nbilldesk.com\nbing.com\nbintang.com\nbiobiochile.cl\nbiomedcentral.com\nbioyun.com\nbirdsallinteractive.com\nbissell.com\nbitauto.com\nbitbucket.org\nbitly.com\nbizjournals.com\nbkstr.com\nblablacar.es\nblackboard.com\nblackhatworld.com\nbleacherreport.com\nblkget.com\nblobla.com\nblocket.se\nblog.com\nblog.ir\nblog.jp\nblog.me\nblogfa.com\nblogger.com\nblogimg.jp\nblogphongthuy.com\nblogsky.com\nblomaga.jp\nbloomberg.com\nblu-ray.com\nbluehost.com\nbmi.ir\nbmj.com\nbobvila.com\nboc.cn\nbodybuilding.com\nbol.com\nbollywoodbubble.com\nbom.gov.au\nboma.org\nbomb01.com\nbonanza.com\nbonappetit.com\nbongda60.net\nbooking.com\nbookmyshow.com\nboredpanda.com\nbose.com\nbottlenose-wine.com\nbox.com\nboxofficemojo.com\nboylesoftware.com\nbp.blogspot.com\nbradesco.com.br\nbrainyquote.com\nbrassring.com\nbraun.com\nbreastcancer.org\nbreitbart.com\nbrides.com.cn\nbridgestreet.com\nbritishairways.com\nbrusselsairlines.com\nbs.to\nbsnl.in\nbt.com\nbtolat.com\nbttiantang.com\nbuffiniandcompany.com\nbukalapak.com\nbullhorn.com\nburton.com\nbuscape.com.br\nbusinessinsider.com\nbusinessol.com\nbusinessweekly.com.tw\nbustle.com\nbuyerzone.com\nbuyreman.com\nbuzzfeed.com\nbuzzfil.net\nbuzzlie.com\nc-loans.com\nc3i-inc.com\nca.gov\ncabelas.com\ncaf.fr\ncafemom.com\ncafepress.com\ncaijing.com.cn\ncaisse-epargne.fr\ncaixa.gov.br\ncaixin.com\ncambridge.org\ncamdenliving.com\ncamelbak.com\ncameloteurope.com\ncancer.gov\ncancer.org\ncankaoxiaoxi.com\ncannondale.com\ncanva.com\ncapitalone.com\ncapitalone360.com\ncarcomplaints.com\ncare.com\ncareerbuilder.com\ncareerwebschool.com\ncarfax.com\ncargurus.com\ncarhartt.com\ncarmax.com\ncarnival.com\ncars.com\ncarsensor.net\ncarters.com\ncartier.com\ncarview.co.jp\ncarwale.com\ncasasbahia.com.br\ncateye.com\ncathaypacific.com\ncb01.co\ncbc.ca\ncbre.com\ncbrehotels.com\ncbs.com\ncbslocal.com\ncbsnews.com\ncbssports.com\ncc.com\nccb.com\nccb.com.cn\nccim.com\nccm.net\ncda.pl\ncdc.gov\ncdiscount.com\ncdstm.cn\nce.cn\ncebupacificair.com\ncecil.de\nceconline.com\ncelebritycruises.com\nceneo.pl\ncentury21.com\ncerner.com\ncesweb.org\nchampionat.com\nchampionsschool.com\nchange.org\ncharitynavigator.org\ncharter.net\nchase.com\nchatwork.com\ncheapflights.co.uk\ncheaptickets.com\ncheezburger.com\nchefkoch.de\nchegg.com\nchekb.com\nchess.com\nchicagotribune.com\nchildrensplace.com\nchina-airlines.com\nchina.com\nchina.com.cn\nchinadaily.com.cn\nchinaso.com\nchinatimes.com\nchinaz.com\nchip.de\nchiphell.com\nchoicehotels.com\nchosun.com\nchouftv.ma\nchristian-dogma.com\nchristianlouboutin.com\nchron.com\nci123.com\ncimls.com\ncinemablend.com\ncisco.com\nciti.com\ncitibank.co.in\ncitibankonline.com\ncitilink.ru\ncitizensadvice.org.uk\ncitrixonline.com\ncity-data.com\ncityadspix.com\ncityheaven.net\nck101.com\nclarin.com\nclarkhoward.com\ncleartrip.com\nclevelandclinic.org\nclickadu.com\nclickbank.com\nclicksvenue.com\nclien.net\ncliftonlabs.com\nclinicaltrials.gov\nclinique.com\nclipconverter.cc\nclixsense.com\ncloudflare.com\ncloudsrvtrk.com\ncms.gov\ncna.com.tw\ncnbc.com\ncnbeta.com\ncnblogs.com\ncnet.com\ncnmo.com\ncnn.com\ncnnic.cn\ncntraveler.com\ncntv.cn\ncnzz.com\ncoccoc.com\ncocolog-nifty.com\ncodecademy.com\ncodecanyon.net\ncodepen.io\ncodeproject.com\ncoldwellbanker.com\ncolgate.com\ncollegeboard.org\ncollegerentals.com\ncolliers.com\ncolumbia.com\ncolumbia.edu\ncomcast.net\ncomenity.net\ncommbank.com.au\ncommentcamarche.net\ncommerx.com\ncomplaintsboard.com\ncomplex.com\ncomputerbild.de\nconcursolutions.com\ncondor.com\nconservativetribune.com\nconstantcontact.com\nconsumeraffairs.com\nconsumercomplaints.in\nconsumerist.com\nconsumerlab.com\nconsumerreports.org\nconsumersearch.com\ncontainerstore.com\ncontentabc.com\ncontinuingedexpress.com\nconvert2mp3.net\ncookinglight.com\ncookpad.com\ncooks.com\ncooksillustrated.com\ncoolmath-games.com\ncopaair.com\ncorelogic.com\ncornell.edu\ncorporatehousingbyowner.com\ncorreios.com.br\ncorriere.it\ncosmopolitan.com\ncostar.com\ncostco.com\ncouchsurfing.com\ncountryliving.com\ncoupons.com\ncoursera.org\ncovalentworks.com\ncox.net\ncpasbien.io\ncpsc.gov\ncqnews.net\ncracked.com\ncraigslist.ca\ncraigslist.org\ncrateandbarrel.com\ncreativemarket.com\ncredai.org\ncredit-agricole.fr\ncreditkarma.com\ncreditmutuel.fr\ncrefcoa.com\ncrewnetwork.org\ncrhoy.com\ncricbuzz.com\ncriteo.com\ncrm-daily.com\ncrmbuyer.com\ncrs.com\ncrunchbase.com\ncrunchyroll.com\ncrutchfield.com\ncsc.com\ncsdn.net\nctitv.com.tw\nctrip.com\ncuisinart.com\ncushwake.com\ncusthelp.com\ncvs.com\ncxml.org\ncygnet-infotech.com\ndafont.com\ndaikynguyenvn.com\ndaily.co.jp\ndailykos.com\ndailymail.co.uk\ndailymotion.com\ndailypakistan.com.pk\ndailysnark.com\ndanawa.com\ndangdang.com\ndantri.com.vn\ndartappraisal.com\ndataart.com\ndaum.net\ndaveramsey.com\ndavidsbridal.com\ndavita.com\ndawn.com\ndeadspin.com\ndealnews.com\ndebate.com.mx\ndecathlon.co.uk\ndeere.com\ndeesign.com\ndeezer.com\ndell.com\ndelta.com\ndemandstar.com\ndemc.com\ndepositphotos.com\ndescartes.com\ndessy.com\ndetik.com\ndeviantart.com\ndeviantart.net\ndhgate.com\ndhl.com\ndhl.de\ndiabetes.co.uk\ndiabetes.org\ndiamondresorts.com\ndianping.com\ndickssportinggoods.com\ndict.cc\ndiesel.com\ndigg.com\ndigikala.com\ndigitalenterprise.org\ndigitalmesh.com\ndigitalocean.com\ndigitalriver.com\ndigitaltrends.com\ndigitas.com\ndillards.com\ndingit.tv\ndiply.com\ndirectrev.com\ndirectv.com\ndiscogs.com\ndiscover.com\ndiscovercard.com\ndiscuss.com.hk\ndish.com\ndisney.com\ndisneystore.com\ndisq.us\ndisqus.com\ndivar.ir\ndiynetwork.com\ndjpunjab.info\ndl-protect.com\ndmm.com\ndmv.org\ndnaindia.com\ndns-shop.ru\ndocin.com\ndoculabs.com\ndocusign.net\ndogfoodadvisor.com\ndoisongphapluat.com\ndomaintools.com\ndominos.com\ndonanimhaber.com\ndonga.com\ndoodle.com\ndoorblog.jp\ndostor.org\ndouban.com\ndoubleclick.net\ndouguo.com\ndouyutv.com\ndpreview.com\ndreamstime.com\ndribbble.com\ndrive2.ru\ndrom.ru\ndropbooks.tv\ndropbox.com\ndropboxusercontent.com\ndrudgereport.com\ndrugabuse.gov\ndrugs.com\ndrugstore.com\ndrweil.com\ndslreports.com\ndsw.com\ndtz.com\nduba.com\nduckduckgo.com\ndummies.com\nduolingo.com\nduowan.com\ndw.com\ndx.com\ndynamicnet.net\ndytt8.net\ne-bizsoft.com\ne-global.es\nea.com\nearthclinic.com\nearthlink.net\nearthwaterfire.com\neastday.com\neastmoney.com\neasyjet.com\neasypano.com\neatingwell.com\nebates.com\nebay-kleinanzeigen.de\nebay.ca\nebay.co.uk\nebay.com\nebay.com.au\nebay.de\nebay.es\nebay.fr\nebay.in\nebay.it\nebookers.com\nebrun.com\necco.com\necho.msk.ru\necnavi.jp\necollege.com\necommerce-digest.com\necommercebytes.com\necommercepartners.net\necommercetimes.com\neconomist.com\ned.gov\neddiebauer.com\nedeal.com\nedmodo.com\nedmunds.com\nedx.org\neenadu.net\negain.com\negou.com\nehow.com\neia.gov\nekantipur.com\neksisozluk.com\nel-nacional.com\nelcomercio.com\nelcomercio.pe\nelconfidencial.com\nelcorteingles.es\neldorado.ru\nelectronicmarkets.org\nelevenia.co.id\nelfagr.org\nelintransigente.com\nelmogaz.com\nelmundo.es\nelpais.com\nelsevier.com\neluniverso.com\nelwatannews.com\nemao.com\nemarketingassociation.com\nemgn.com\nemirates.com\nemol.com\nenet.com.cn\nenews.com.tw\nengadget.com\nengageya.com\nensonhaber.com\nentrepreneur.com\nenvato.com\neonline.com\nepic.com\nepicurious.com\nepochtimes.com\nepweike.com\nera.com\neram.fr\nergotron.com\nernestjones.co.uk\nero-advertising.com\nero-video.net\neroterest.net\nespncricinfo.com\nesquire.com\nesuteru.com\netao.com\nethanallen.com\netrade.com\netsy.com\nettoday.net\neuropa.eu\neventbrite.com\nevernote.com\nevite.com\new.com\nex.ua\nexamine.com\nexblog.jp\nexcite.co.jp\nexecustay.com\nexhentai.org\nexhibitions.co.uk\nexoclick.com\nexpedia.ca\nexpedia.com\nexpress-scripts.com\nexpress.co.uk\nexpress.pk\nextra.com.br\nextratorrent.cc\neyny.com\neztv.ag\nface-masr.com\nfacebook.com\nfacenama.com\nfaithtap.com\nfamilydoctor.com.cn\nfamilydoctor.org\nfamitsu.com\nfanatik.com.tr\nfandango.com\nfanfiction.net\nfang.com\nfanhuan.com\nfanli.com\nfanniemae.com\nfanpage.gr\nfarfesh.com\nfarsnews.com\nfashiongo.net\nfastclass.com\nfastcompany.com\nfatosdesconhecidos.com.br\nfatwallet.com\nfaz.net\nfbcdn.net\nfc2.com\nfda.gov\nfederaltitle.com\nfedex.com\nfeedly.com\nfema.gov\nfeng.com\nfibre2fashion.com\nfidelity.com\nfiducia.de\nfilehippo.com\nfilmesonlinegratis.net\nfilmibeat.com\nfilmon.com\nfilmweb.pl\nfinecooking.com\nfinishclueobscure.info\nfinishline.com\nfinn.no\nfinnair.com\nfirmseek.com\nfirstpost.com\nfisher-price.com\nfitbit.com\nfitnessmagazine.com\nfitpregnancy.com\nfiverr.com\nfivethirtyeight.com\nfixya.com\nflashscore.com\nflashx.tv\nflatmates.com.au\nflickr.com\nflightnetwork.com\nflightradar24.com\nflipboard.com\nflipkart.com\nflirchi.com\nflybe.com\nflyfrontier.com\nflysaa.com\nflyuia.com\nfnac.com\nfnb.co.za\nfntic.com\nfocus.cn\nfocus.de\nfodors.com\nfood.com\nfood52.com\nfoodandwine.com\nfoodnetwork.com\nfool.com\nforbes.com\nforce.com\nford.com\nforestcity.net\nforever21.com\nforgeofempires.com\nforocoches.com\nfortune.com\nfotostrana.ru\nfoursquare.com\nfoxnews.com\nfoxsports.com\nfree.fr\nfreecharge.in\nfreejobalert.com\nfreelancer.com\nfreepeople.com\nfreepik.com\nfrigidaire.com\nfriv.com\nfromdoctopdf.com\nfrommers.com\nfrontpoint.it\nfrys.com\nft.com\nfueleconomy.gov\nfurnishedhousing.com\ng2a.com\ngaana.com\ngalleryofguns.com\ngamefactory.jp\ngamefaqs.com\ngameforge.com\ngamepedia.com\ngamer.com.tw\ngamersky.com\ngamespot.com\ngamestop.com\ngamewith.jp\ngamme.com.tw\ngap.com\ngaranti.com.tr\ngardenweb.com\ngarmin.com\ngasbuddy.com\ngawker.com\ngazeta.pl\ngazeta.ru\ngazetaexpress.com\ngazetevatan.com\ngazzetta.it\nge.com\ngeappliances.com\ngearbest.com\ngeekologie.com\ngeico.com\ngemius.pl\ngenius.com\ngeocities.jp\ngetbootstrap.com\ngethuman.com\ngetpocket.com\ngfycat.com\nghanaweb.com\ngia.edu\ngiant-bicycles.com\ngidonline.club\ngigazine.net\ngiphy.com\ngismeteo.ru\ngithub.com\ngittigidiyor.com\ngivemesport.com\ngizmodo.com\ngizmodo.jp\nglassdoor.com\nglobalpropertyguide.com\nglobalsources.com\nglobaltestmarket.com\nglobaltimes.cn\nglobest.com\nglobo.com\nglock.com\ngmanetwork.com\ngmarket.co.kr\ngmw.cn\ngmx.net\ngnavi.co.jp\ngnc.com\ngo.com\ngo2000.com\ngo2cloud.org\ngoal.com\ngocomics.com\ngodaddy.com\ngofundme.com\ngoibibo.com\ngoldcoastschools.com\ngome.com.cn\ngongchang.com\ngoo-net.com\ngoo.gl\ngoo.ne.jp\ngoodgamestudios.com\ngoodhousekeeping.com\ngoodreads.com\ngoodrx.com\ngoogle-analytics.com\ngoogle.ae\ngoogle.at\ngoogle.az\ngoogle.ba\ngoogle.be\ngoogle.bg\ngoogle.by\ngoogle.ca\ngoogle.ch\ngoogle.cl\ngoogle.cn\ngoogle.co.id\ngoogle.co.il\ngoogle.co.in\ngoogle.co.jp\ngoogle.co.kr\ngoogle.co.ma\ngoogle.co.nz\ngoogle.co.th\ngoogle.co.tz\ngoogle.co.uk\ngoogle.co.ve\ngoogle.co.za\ngoogle.com\ngoogle.com.af\ngoogle.com.ar\ngoogle.com.au\ngoogle.com.bd\ngoogle.com.bo\ngoogle.com.br\ngoogle.com.co\ngoogle.com.do\ngoogle.com.ec\ngoogle.com.eg\ngoogle.com.gh\ngoogle.com.gt\ngoogle.com.hk\ngoogle.com.kw\ngoogle.com.ly\ngoogle.com.mx\ngoogle.com.my\ngoogle.com.ng\ngoogle.com.pe\ngoogle.com.ph\ngoogle.com.pk\ngoogle.com.pr\ngoogle.com.sa\ngoogle.com.sg\ngoogle.com.tr\ngoogle.com.tw\ngoogle.com.ua\ngoogle.com.vn\ngoogle.cz\ngoogle.de\ngoogle.dk\ngoogle.dz\ngoogle.es\ngoogle.fi\ngoogle.fr\ngoogle.gr\ngoogle.hr\ngoogle.hu\ngoogle.ie\ngoogle.iq\ngoogle.it\ngoogle.kz\ngoogle.lk\ngoogle.lt\ngoogle.lv\ngoogle.nl\ngoogle.no\ngoogle.pl\ngoogle.pt\ngoogle.ro\ngoogle.rs\ngoogle.ru\ngoogle.se\ngoogle.si\ngoogle.sk\ngoogle.tn\ngoogleadservices.com\ngoogleusercontent.com\ngorillavid.in\ngotomeeting.com\ngotowebinar.com\ngotporn.com\ngougou.com\ngovome.com\ngracobaby.com\ngrammarly.com\ngraphicriver.net\ngreatandhra.com\ngreatclips.com\ngreatergood.com\ngroupon.com\ngs1.org\ngsmarena.com\ngstatic.com\nguess.com\nguidestar.org\ngulfair.com\ngumtree.co.za\ngumtree.com\ngumtree.com.au\ngumtree.pl\ngunbroker.com\ngutefrage.net\ngyazo.com\ngymboree.com\nhaber7.com\nhaberler.com\nhaberturk.com\nhabrahabr.ru\nhaier.com\nhalifax-online.co.uk\nhamariweb.com\nhamusoku.com\nhanleywood.com\nhao123.com\nhaosou.com\nharborfreight.com\nharmankardon.com\nharrods.com\nharvard.edu\nhasbro.com\nhatena.ne.jp\nhatenablog.com\nhawaiianairlines.com\nhclips.com\nhdfcbank.com\nhdfilmifullizle.com.tr\nhealth.com\nhealthboards.com\nhealthcare.gov\nhealthgrades.com\nhealthline.com\nhealthstream.com\nheart.org\nheise.de\nhellou.co.uk\nhellyhansen.com\nhepsiburada.com\nhere.com\nhermanmiller.com\nhespress.com\nhexun.com\nhfflp.com\nhgtv.com\nhh.ru\nhibapress.com\nhighrisehq.com\nhihi2.com\nhillspet.com\nhilton.com\nhimado.in\nhimasoku.com\nhindustantimes.com\nhines.com\nhistats.com\nhitc.com\nhizliresim.com\nhm.com\nholiday-weather.com\nhollandamerica.com\nhollywoodlife.com\nhollywoodreporter.com\nhomeaway.com\nhomedepot.com\nhomepage-web.com\nhomes.co.jp\nhomesalez.com\nhongkiat.com\nhootsuite.com\nhopkinsmedicine.org\nhorizonhobby.com\nhostelbookers.com\nhostelworld.com\nhostgator.com\nhotel.de\nhotels.com\nhoteltravel.com\nhotnewhiphop.com\nhotpepper.jp\nhotstar.com\nhottopic.com\nhotukdeals.com\nhotwire.com\nhouse365.com\nhousemaster.com\nhouzz.com\nhowardforums.com\nhowstuffworks.com\nhowtogeek.com\nhp.com\nhrblock.com\nhref.li\nhrs.de\nhsbc.co.uk\nhsbc.com.hk\nhse.gov.uk\nhsn.com\nhuaban.com\nhuanqiu.com\nhuawei.com\nhubpages.com\nhubspot.com\nhud.gov\nhuffingtonpost.com\nhulu.com\nhulu.jp\nhumblebundle.com\nhupu.com\nhurriyet.com.tr\nhusqvarna.com\nhuya.com\nhyatt.com\ni.ua\ni2x.net\nibanking-services.com\nibba.org\niberia.com\nibm.com\nibnlive.com\nibtimes.co.in\nibtimes.co.uk\nibtimes.com\nicbc.com.cn\nicc.net\niciba.com\nicicibank.com\nicims.com\nicloud.com\nicolor.com.cn\niconosquare.com\nicook.tw\nid.net\nidata.com\nideafit.com\nidealista.com\nidealo.de\nidnes.cz\nifeng.com\niflscience.com\nifma.org\nig.com.br\nign.com\niheart.com\niherb.com\nihg.com\nihwy.com\nijreview.com\nikea.com\nilfattoquotidiano.it\nilmeteo.it\niltalehti.fi\niltasanomat.fi\nimagebam.com\nimages-amazon.com\nimaging-resource.com\nimamerchants.org\nimdb.com\nimgchili.net\nimgur.com\nimmobilienscout24.de\nimobile.com.cn\nimpress.co.jp\ninc.com\nindeed.co.in\nindeed.co.uk\nindeed.com\nindependent.co.uk\nindex.hu\nindia.com\nindiamart.com\nindianexpress.com\nindianrail.gov.in\nindiatimes.com\nindiegogo.com\ninfoaccess.net\ninfobae.com\ninformaticsinc.com\ninformer.com\ninfoseek.co.jp\ninfusionsoft.com\ning.nl\nink361.com\ninman.com\ninmotionhosting.com\ninnfrad.com\ninnotrac.com\ninnshopper.com\ninquirer.net\ninquisitr.com\ninspectionnews.net\ninspectorsjournal.com\ninspsearch.com\ninstacommerce.net\ninstagram.com\ninstituteonline.com\ninstructables.com\ninstructure.com\nintegrativenutrition.com\nintegro.com\nintel.com\ninteractivesoftware.co.uk\ninteria.pl\nintermountainhealthcare.org\ninternetdownloadmanager.com\ninternethaber.com\ninterpark.com\nintervalworld.com\nintoday.in\nintrabench.com\nintuit.com\ninvaluable.com\ninvesting.com\ninvestopedia.com\nioffer.com\nionidea.com\nipko.pl\niqiyi.com\nirctc.co.in\nirecommend.ru\nirei.com\nirem.org\nironplanet.com\nirpopup.ir\nirs.gov\nissuu.com\nistockphoto.com\nit4profit.com\nitasoftware.com\nitau.com.br\nitelligencegroup.com\nitmedia.co.jp\nivanhoecambridge.com\nivc.cn\nivc.com\nivenue.com\nivi.ru\niwillteachyoutoberich.com\niza.ne.jp\nj-cast.com\njabong.com\njagran.com\njal.co.jp\njalan.net\njalopnik.com\njamieoliver.com\njapanpost.jp\njav68.me\njava.com\njavedch.com\njb51.net\njbl.com\njcpenney.com\njcrew.com\njd.com\njet.com\njetairways.com\njetblue.com\njeuxvideo.com\njezebel.com\njia360.com\njimdo.com\njin115.com\njjwxc.net\njma.go.jp\njnj.com\njoann.com\njobrapido.com\njohnlewis.com\njoins.com\njomashop.com\njoneslanglasalle.com\njournaldesfemmes.com\njquery.com\njqw.com\njrj.com.cn\njsfiddle.net\njugem.jp\njumeirah.com\njumia.com.ng\njunbi-tracker.com\njustdial.com\njw.org\nk618.cn\nkaiserpermanente.org\nkakaku.com\nkana.com\nkao.com\nkapook.com\nkapre.com\nkaskus.co.id\nkaspersky.com\nkat.cr\nkay.com\nkayak.com\nkbb.com\nkddi.com\nkdnet.net\nkeenfootwear.com\nkeepvid.com\nkenh14.vn\nkenwood.com\nkevinmd.com\nkhabaronline.ir\nkhanacademy.org\nkicker.de\nkickstarter.com\nkidshealth.org\nkidspot.com.au\nkienthuc.net.vn\nkijiji.ca\nkimberamerica.com\nkinja.com\nkinogo.co\nkinopoisk.ru\nkinox.to\nkinozal.tv\nkiplinger.com\nkissanime.to\nkizi.com\nkizlarsoruyor.com\nklikbca.com\nklipsch.com\nklm.com\nkmart.com\nkmp.co.uk\nkohls.com\nkompas.com\nkompasiana.com\nkonga.com\nkongregate.com\nkooora.com\nkorabia.com\nkoreanair.com\nkotaku.com\nkouclo.com\nkp.ru\nkraftrecipes.com\nksl.com\nkt9267.com\nkuronekoyamato.co.jp\nkuwo.cn\nkyosho.com\nla-z-boy.com\nlabanquepostale.fr\nlabcorp.com\nlabtestsonline.org\nlacaixa.es\nlady8844.com\nlagaceta.com.ar\nlamoda.ru\nlan.com\nlanacion.com.ar\nlancome-usa.com\nlandcentral.com\nlandflip.com\nlandlords.org.uk\nlandsend.com\nlandwatch.com\nlapatilla.com\nlaposte.net\nlaredoute.fr\nlast.fm\nlastpass.com\nlaterooms.com\nlatimes.com\nlayalina.com\nlazada.co.id\nldblog.jp\nlds.com\nlds.org\nleadzupc.com\nleagueoflegends.com\nleboncoin.fr\nlefigaro.fr\nlegacy.com\nlego.com\nlemonde.fr\nlenovo.com\nlenscrafters.com\nlenta.ru\nleo.org\nlequipe.fr\nletv.com\nlg.com\nlibero.it\nlifebuzz.com\nlifehack.org\nlifehacker.com\nlifenews.ru\nlightinthebox.com\nlightwellinc.com\nlikemag.com\nlikes.com\nlindaikejisblog.com\nline.me\nlinkedin.com\nlinkwithin.com\nlinternaute.com\nliputan6.com\nliquor.com\nlist-manage.com\nlist-manage1.com\nlittlethings.com\nlive.com\nliveadexchanger.com\nlivedoor.biz\nlivedoor.com\nlivedoor.jp\nlivehelper.com\nliveinternet.ru\nlivejournal.com\nliveleak.com\nliveperson.net\nlivescore.com\nlivestrong.com\nlivetv.sx\nlivingsocial.com\nllbean.com\nlloydsbank.co.uk\nloading-delivery2.com\nlockerdome.com\nlogicsoftware.co.uk\nlogitech.com\nlohaco.jp\nlolesports.com\nlonelyplanet.com\nlongchamp.com\nloopnet.com\nlordandtaylor.com\nlorealparisusa.com\nlostfilm.tv\nlot.com\nlotterypost.com\nlowensign.com\nlowes.com\nltn.com.tw\nlufthansa.com\nlululemon.com\nlun.com\nluxtarget.com\nluxuryhomemarketing.com\nluxuryhomes.com\nluxuryrealestate.com\nlvmama.com\nlynda.com\nmackeeper.com\nmackolik.com\nmacromill.com\nmacrumors.com\nmacys.com\nmade-in-china.com\nmail.com\nmail.ru\nmailchimp.com\nmainichi.jp\nmakeleio.gr\nmakemytrip.com\nmakeupalley.com\nmakeuseof.com\nmama.cn\nmangafox.me\nmangahere.co\nmangareader.net\nmango.com\nmanoramaonline.com\nmanta.com\nmanualsonline.com\nmanufacturing.net\nmapquest.com\nmapsofindia.com\nmarc-o-polo.com\nmarca.com\nmarketgid.com\nmarketwatch.com\nmarksandspencer.com\nmarktplaats.nl\nmarmiton.org\nmarmot.com\nmarriott.com\nmarthastewart.com\nmarykay.com\nmashable.com\nmashreghnews.ir\nmasralarabia.com\nmasrawy.com\nmassageenvy.com\nmatch.com\nmattel.com\nmaxtalk.com\nmaybank2u.com.my\nmaybelline.com\nmayoclinic.org\nmbank.pl\nmbc.net\nmcafee.com\nmcfadyen.com\nmckesson.com\nmckissock.com\nmdanderson.org\nmeaww.com\nmeb.gov.tr\nmec.gov.br\nmediafire.com\nmediaplex.com\nmediaset.it\nmedicare.gov\nmedicinenet.com\nmedium.com\nmedscape.com\nmeetup.com\nmega.co.nz\nmega.nz\nmegapopads.com\nmeituan.com\nmelia.com\nmemecats.com\nmensfitness.com\nmenshealth.co.uk\nmenshealth.com\nmentalfloss.com\nmeowshare.com\nmercadolibre.com.ar\nmercadolibre.com.mx\nmercadolibre.com.ve\nmercadolivre.com.br\nmercola.com\nmerdeka.com\nmergent.com\nmerriam-webster.com\nmessenger.com\nmesteel.com\nmetacritic.com\nmeteofrance.com\nmetro.co.uk\nmetroer.com\nmetrolyrics.com\nmetrotvnews.com\nmgid.com\nmheducation.com\nmi.com\nmic.com\nmicrosoft.com\nmicrosoftonline.com\nmicrosoftstore.com\nmidwayusa.com\nmihanblog.com\nmikeferry.com\nmilanuncios.com\nmileroticos.com\nmilitary.com\nmillersamuel.com\nmilliyet.com.tr\nminecraft.net\nminiclip.com\nmint.com\nmirror.co.uk\nmirtesen.ru\nmisr5.com\nmit.edu\nmiui.com\nmixi.jp\nmizuhobank.co.jp\nmlb.com\nmobafire.com\nmobfactory.info\nmobikwik.com\nmobile.de\nmobile01.com\nmobile9.com\nmodcloth.com\nmomoshop.com.tw\nmonarch.co.uk\nmoneycontrol.com\nmoneysavingexpert.com\nmoneytalksnews.com\nmonotaro.com\nmonster.com\nmontblanc.com\nmontgomerycountymd.gov\nmos.ru\nmoseley.org\nmotherearthnews.com\nmotortrend.com\nmoudamepo.com\nmountainhardwear.com\nmouthshut.com\nmoveandstay.com\nmovoto.com\nmoz.com\nmozilla.org\nmr-johal.com\nmskcc.org\nmsn.com\nmsnbc.com\nmts.ru\nmtsindia.in\nmtv.com\nmufg.jp\nmultihousingnews.com\nmundo.com\nmundosexanuncio.com\nmunrvscurlms.com\nmusica.com\nmusiciansfriend.com\nmvideo.ru\nmxttrf.com\nmy-hit.org\nmyanimelist.net\nmydala.com\nmydomainadvisor.com\nmydrivers.com\nmyfico.com\nmyfitnesspal.com\nmynavi.jp\nmynet.com\nmypearson.com\nmyshopify.com\nmysmartprice.com\nmyspace.com\nmysql.com\nmystart.com\nmystartsearch.com\nmyway.com\nn-tv.de\nn11.com\nn121adserv.com\nnaahq.org\nnachi.org\nnacion.com\nnahi.org\nnaiglobal.com\nnaiop.org\nnairaland.com\nnamecheap.com\nnametests.com\nnamu.wiki\nnarod.ru\nnarpm.org\nnasa.gov\nnat.com\nnate.com\nnational-lottery.co.uk\nnationalgeographic.com\nnationalmssociety.org\nnaturallycurly.com\nnature.com\nnaukri.com\nnautica.com\nnaver.com\nnaver.jp\nnavyfederal.org\nnba.com\nnbc.com\nnbcnews.com\nnbcsports.com\nncl.com\nncsha.org\nndtv.com\nneimanmarcus.com\nnejm.org\nneobux.com\nnesn.com\nnespresso.com\nnet-a-porter.com\nnetcasters.com\nnetdna-cdn.com\nnetdoctor.co.uk\nnetflix.com\nnetpartnering.com\nnetshoes.com.br\nnetsuite.com\nnetteller.com\nnetx.net\nnewbalance.com\nnewegg.com\nnewhomesdirectory.com\nnews-us.jp\nnews.com.au\nnews24.com\nnewsmth.net\nnewsnow.co.uk\nnewtab-tv.com\nnewyorker.com\nnextag.com\nnextdoor.com\nnexternal.com\nnextmedia.com\nnexusmods.com\nnfl.com\nngacn.cc\nnguoiduatin.vn\nnguyentandung.org\nnhadatso.com\nnhk.or.jp\nnhl.com\nnicovideo.jp\nnifty.com\nnih.gov\nniiz.info\nnike.com\nnikkansports.com\nnikkei.com\nnikkeibp.co.jp\nning.com\nnipic.com\nnitroflare.com\nniuche.com\nnj.com\nnlihc.org\nnmhc.org\nnmisr.com\nnnm-club.me\nnoaa.gov\nnocookie.net\nnomadicmatt.com\nnordictrack.com\nnordstrom.com\nnorton.com\nnosub.tv\nnouvelobs.com\nnovinky.cz\nnownews.com\nnowtv.de\nnowvideo.sx\nnpr.org\nnreionline.com\nnrk.no\nns5n.com\nnta.go.jp\nntdtv.com\nnttdocomo.co.jp\nnu.nl\nnuance.com\nnur.kz\nnutrition.org\nny.gov\nnyaa.eu\nnyaa.se\nnydailynews.com\nnymag.com\nnypost.com\nnyrei.com\nnytimes.com\no2.pl\noakley.com\noakwood.com\nobeo.com\nocn.ne.jp\noeeee.com\noffice.com\noffice365.com\nofficedepot.com\nok.ru\nokcupid.com\nokezone.com\nokta.com\nokwave.jp\noldnavy.com\noldrepublictitle.com\nolx.co.id\nolx.com.br\nolx.in\nolx.kz\nolx.pl\nolx.ro\nolx.ua\nomegawatches.com\nonclickads.net\nonclicktop.com\nonedio.com\noneindia.com\nonestopclick.com\nonet.pl\nonetravel.com\nonkyo.com\nonline-convert.com\nonlinecreditcenter6.com\nonlinekhabar.com\nonliner.by\nonlinesbi.com\nontests.me\nopencrm.co.uk\nopendns.com\nopenload.co\nopensooq.com\nopensubtitles.org\nopentable.com\noracle.com\norange.fr\norbitz.com\norf.at\norientaltrading.com\norigin.com\noschina.net\nosha.gov\notomoto.pl\notto.de\nouo.io\noutbrain.com\nouteredgeuk.com\nover-blog.com\noverdrive.com\noverstock.com\nownersdirect.co.uk\noyaide.com\nozon.ru\np30download.com\np5w.net\npadsdel.com\npagesjaunes.fr\npaidverts.com\npampers.com\npanasonic.com\npanasonic.jp\npanda.tv\npandora.com\npandora.net\npanet.co.il\npantip.com\npapajohns.com\nparenting.com\nparents.com\npartners.org\npastebin.com\npatagonia.com\npatch.com\npatheos.com\npatient.info\npaulaschoice.com\npayoneer.com\npaypal.com\npayseal.com\npaytm.com\npaytm.in\npbs.org\npcadvisor.co.uk\npcgamer.com\npch.com\npchome.com.tw\npchome.net\npcmag.com\npcworld.com\npearsoncmg.com\npelis24.com\npendleton-usa.com\npeople.com\nperfect.com\nperiscope.tv\npersianblog.ir\npetco.com\npetmd.com\npetsafe.net\npetsmart.com\npex.jp\npeyvandha.ir\npeza.gov.ph\nphilippineairlines.com\nphilips.com\nphoenixads.co.in\nphonearena.com\nphotobucket.com\nphotoplan.co.uk\nphotosigns.com.au\nphp.net\npiac.com.pk\npicmonkey.com\npicofile.com\npier1.com\npikabu.ru\npillsbury.com\npinimg.com\npinterest.com\npioneerelectronics.com\npiriform.com\npissedconsumer.com\npitchfork.com\npixabay.com\npixelplanet.com\npixiv.net\npixlr.com\npixnet.net\npizzahut.com\nplanetecomsolutions.com\nplanetromeo.com\nplannedparenthood.org\nplarium.com\nplay1topgame.com\nplaystation.com\nplurk.com\nplurotech.com\nplymouth.ac.uk\npnc.com\npo.st\npochta.ru\npof.com\npogo.com\npolar.com\npole-emploi.fr\npolitico.com\npolyvore.com\nponparemall.com\npopads.net\npopcash.net\npopmaster.ir\npopmyads.com\npopped.biz\npopsugar.com\npopundertotal.com\nportplus.com\npostbank.de\nposte.it\npostimg.org\npotterybarn.com\npowerball.com\nppomppu.co.kr\npps.tv\nprana.com\npredictivadvertising.com\npremierleague.com\npretty52.com\nprevention.com\nprezi.com\npricegrabber.com\npriceline.com\npriceminister.com\nprimewire.ag\nprincess.com\nprinciplevaluation.com\nprivatbank.ua\nprivateislandsonline.com\nprntscr.com\nproboards.com\nprodapt.com\nprogramme-tv.net\nprojectfreetv.so\nprologis.com\nprom.ua\npronto.com\npropertypanorama.com\nproschools.com\nprospectsoft.com\nprotect0r.com\nprothom-alo.com\nprotothema.gr\nprou.net\nprovidence.org\nprpops.com\npsu.edu\npsychologytoday.com\nptt.cc\npubcon.com\npudelek.pl\npurdue.edu\npureadexchange.com\nputlocker.is\npython.org\nqantas.com.au\nqatarairways.com\nqidian.com\nqingdaonews.com\nqiwi.com\nqq.com\nqualtrics.com\nquanjing.com\nquikr.com\nquiksilver.com\nquizlet.com\nquora.com\nqvc.com\nqz.com\nr10.net\nrabobank.nl\nrackcdn.com\nrackspace.com\nradikal.com.tr\nrakuten-bank.co.jp\nrakuten-card.co.jp\nrakuten.co.jp\nrakuten.com\nrakuten.ne.jp\nralphlauren.com\nrambler.ru\nranker.com\nrapidgator.net\nrappler.com\nrarbg.to\nravelry.com\nrbc.ru\nrbcroyalbank.com\nrci.com\nrdsa2012.com\nrealclearpolitics.com\nrealestate.com.au\nrealestatece.com\nrealestateexpress.com\nrealestatetomato.com\nrealogy.com\nrealsimple.com\nrealstar.ca\nrealtor.com\nrealtourvision.com\nrealtyexecutives.com\nrealtytimes.com\nrebac.net\nreclameaqui.com.br\nredappleapartments.com\nredbox.com\nredbubble.com\nredcrossblood.org\nreddit.com\nredfin.com\nrediff.com\nredirectvoluum.com\nrednet.cn\nreduxmediia.com\nredwingshoes.com\nreference.com\nrefinery29.com\nrei.com\nreimageplus.com\nreis.com\nrejournals.com\nrelated.com\nremax.com\nremedi.com\nremington.com\nremonline.com\nrenren.com\nrentalsite.com\nrepelis.tv\nrepubblica.it\nrepublika.co.id\nresearchgate.net\nresellerratings.com\nresultados-futbol.com\nretailmenot.com\nreuters.com\nrevacomm.com\nreverb.com\nreverso.net\nrfptemplates.org\nria.ru\nricksteves.com\nricoh-usa.com\nrightmove.co.uk\nrimanews.com\nripoffreport.com\nrismedia.com\nrivals.com\nroblox.com\nrockanddirt.com\nrocketnews24.com\nrockport.com\nrockwellinstitute.com\nrodalesorganiclife.com\nroku.com\nrolex.com\nrollingstone.com\nrottentomatoes.com\nroughguides.com\nroyalbank.com\nroyalcaribbean.com\nrozblog.com\nrozetka.com.ua\nrr.com\nrrbonlinereg.in\nrrbonlinereg.net\nrt.com\nruger.com\nrusbiz.com\nrush.edu\nruten.com.tw\nrutracker.org\nrutube.ru\nrxlist.com\nryanair.com\nsabah.com.tr\nsabq.org\nsahibinden.com\nsaisoncard.co.jp\nsaksfifthavenue.com\nsakura.ne.jp\nsalesforce.com\nsalespage.com\nsalon.com\nsamhsa.gov\nsammydress.com\nsamplicio.us\nsamsclub.com\nsamsung.com\nsankei.com\nsanook.com\nsanspo.com\nsantander.co.uk\nsap.com\nsapient.com\nsapo.pt\nsaramin.co.kr\nsasontnwc.net\nsaudiairlines.com\nsavefrom.net\nsaveur.com\nsavills.com\nsavingstar.com\nsberbank.ru\nsbisec.co.jp\nsbnation.com\nscarymommy.com\nscholastic.com\nschwab.com\nsciencedirect.com\nscoop.it\nscoopwhoop.com\nscotiabank.com\nscribd.com\nsdsu.edu\nsearchalgo.com\nsearchengineland.com\nsearchlock.com\nsears.com\nseasonvar.ru\nseatguru.com\nsecureinternetbank.com\nsecureserver.net\nseek.com.au\nseekingalpha.com\nseesaa.net\nselectleaders.com\nself.com\nseniorsrealestate.com\nsennheiser.com\nsephora.com\nserverfault.com\nserving-sys.com\nsesconference.com\nsetn.com\nseznam.cz\nsfgate.com\nsfr.fr\nsh.st\nshaadi.com\nshahrekhabar.com\nshangri-la.com\nshaparak.ir\nshareasale.com\nsharecare.com\nsharepoint.com\nsharpusa.com\nshasha.ps\nshermanstravel.com\nshimano.com\nshine.com\nshiseido.co.jp\nshoecarnival.com\nshop-pro.jp\nshopathome.com\nshopbop.com\nshopclues.com\nshopify.com\nshopping.com\nshoutmeloud.com\nshufoo.net\nshutterfly.com\nshutterstock.com\nsi.com\nsierratradingpost.com\nsigsauer.com\nsimilarweb.com\nsimplyrecipes.com\nsina.com.cn\nsinaimg.cn\nsindonews.com\nsiriusxm.com\nsiteadvisor.com\nsitepoint.com\nskroutz.gr\nsky.com\nskycn.com\nskype.com\nskyscanner.com\nskyscanner.net\nskysports.com\nslack.com\nslashdot.org\nslate.com\nslickdeals.net\nslideshare.net\nslidesharecdn.com\nslimspots.com\nslopeaota.com\nsmallpdf.com\nsmallseotools.com\nsmartnewtab.com\nsmartshopping.com\nsmbc-card.com\nsmh.com.au\nsmi2.ru\nsmith-wesson.com\nsmittenkitchen.com\nsmzdm.com\nsnapdeal.com\nsnopes.com\nso-net.ne.jp\nso.com\nsocialsecurity.gov\nsocietegenerale.fr\nsoftbank.jp\nsoftcare.com\nsoftonic.com\nsoftpedia.com\nsoftwarefolks.com\nsogou.com\nsohu.com\nsolarmovie.ph\nsonos.com\nsony.com\nsony.jp\nsonyentertainmentnetwork.com\nsopitas.com\nsoso.com\nsothebysrealty.com\nsou300.com\nsoundcloud.com\nsouq.com\nsourceforge.net\nsouthernliving.com\nsouthwest.com\nsozcu.com.tr\nsp.gov.br\nspaceshipads.com\nspanishdict.com\nspecialized.com\nspeedtest.net\nspicejet.com\nspiegel.de\nspine-health.com\nspirit.com\nsponichi.co.jp\nsport1.de\nsports.ru\nsportsauthority.com\nsportsdirect.com\nsportsmansguide.com\nspotify.com\nspringer.com\nspringfield-armory.com\nsprint.com\nspscommerce.com\nsputniknews.com\nsq.cn\nsquare-enix.com\nsquarespace.com\nsquaretrade.com\nsquareup.com\nsquiz.net\nsram.com\nsrilankan.com\nsrv2trking.com\nssa.gov\nssisurveys.com\nstackexchange.com\nstackoverflow.com\nstandardmedia.co.ke\nstanford.edu\nstaples.com\nstarbucks.com\nstarsports.com\nstartimes.com\nstarwoodhotels.com\nstatcounter.com\nstate.gov\nstate.tx.us\nstaticflickr.com\nstaticwebdom.com\nsteamcommunity.com\nsteampowered.com\nsterlingcommerce.com\nstjude.org\nstockstar.com\nstokke.com\nstorebuilder.co.uk\nstorefrontconsulting.com\nstraightsell.com.au\nstrava.com\nstreamcloud.eu\nstreamin.to\nstubhub.com\nstudentdoctor.net\nstudentuniverse.com\nstudy.com\nstuff.tv\nstumbleupon.com\nstyleforum.net\nsuara.com\nsubito.it\nsubmarino.com.br\nsubscene.com\nsueddeutsche.de\nsugarcrm.com\nsulekha.com\nsunbeltnetwork.com\nsuning.com\nsunset.com\nsuntrust.com\nsuper.cz\nsuperuser.com\nsurplusglobal.com\nsuruga-ya.jp\nsurveymonkey.com\nsutterhealth.org\nsuumo.jp\nsuunto.com\nsvmsolutions.com\nswagbucks.com\nswarovski.com\nswatch.com\nsweetwater.com\nswiss.com\nsynchronycredit.com\nsyosetu.com\nszn.cz\nsznews.com\nt-mobile.com\nt-online.de\nt.co\nt411.in\ntabelog.com\ntabnak.ir\ntaboola.com\ntagged.com\ntagheuer.com\ntagonline.com\ntahrirnews.com\ntaimienphi.vn\ntakungpao.com\ntaleo.net\ntalk.tw\ntamiya.com\ntaobao.com\ntarget.com\ntaringa.net\ntarladalal.com\ntasify.com\ntattoodo.com\ntaxact.com\ntd.com\ntdbank.com\nteacherspayteachers.com\nteamviewer.com\ntebyan.net\ntechbang.com\ntechcrunch.com\ntechindia.com\ntechradar.com\ntechtarget.com\ntechtudo.com.br\nted.com\nteepr.com\ntelegraaf.nl\ntelegraf.com.ua\ntelegrafi.com\ntelegram.me\ntelegram.org\ntelegraph.co.uk\ntelekom.com\ntemplatemonster.com\ntempo.co\ntenki.jp\nterra.com.br\nterraclicks.com\ntesco.com\ntf1.fr\ntgbus.com\nthaiairways.com\ntheatlantic.com\ntheblaze.com\nthechive.com\nthedailybeast.com\nthefreedictionary.com\ntheguardian.com\nthehill.com\nthehindu.com\nthekitchn.com\nthekrazycouponlady.com\ntheladbible.com\nthelancet.com\nthemeforest.net\nthemoneyconverter.com\nthemovechannel.com\nthenextweb.com\nthenorthface.com\ntheonion.com\nthepennyhoarder.com\nthepiratebay.se\nthesaurus.com\nthesimpledollar.com\nthesportbible.com\nthestreet.com\ntheverge.com\nthevideo.me\nthewatchseries.to\ntheweathernetwork.com\nthewhizmarketing.com\nthisav.com\nthomascook.com\nthriftyfun.com\nthrillist.com\ntianya.cn\nticketmaster.com\nticketmonster.co.kr\ntigerdirect.com\ntilestwra.com\ntim.it\ntimberland.com\ntime.com\ntimeanddate.com\ntimeout.com\ntimewarnercable.com\ntinypic.com\ntirerack.com\ntiscali.it\ntistory.com\ntitleonecorp.com\ntiu.ru\ntlbb8.com\ntmall.com\ntmz.com\nto8to.com\ntoday.com\ntodayhumor.co.kr\ntogetter.com\ntokopedia.com\ntomsguide.com\ntomshardware.com\ntomtop.com\ntonyrobbins.com\ntop10homeremedies.com\ntopix.com\ntoptenreviews.com\ntoranoana.jp\ntorcache.net\ntorrentkim1.net\ntorrentz.com\ntorrentz.eu\ntorrentz.in\ntoshiba.com\ntotalbeauty.com\ntourfactory.com\ntoyokeizai.net\ntoysrus.com\ntpmco.com\ntrackingclick.net\ntrackvoluum.com\ntradeadexchange.com\ntradedoubler.com\ntrademe.co.nz\ntraffichunt.com\ntrafficmonsoon.com\ntrafficserving.com\ntraidnt.net\ntravelandleisure.com\ntravelocity.com\ntravelzoo.com\ntraxxas.com\ntreasury.gov\ntrekbikes.com\ntrello.com\ntribunnews.com\ntrinityinsight.com\ntripadvisor.co.uk\ntripadvisor.com\ntripadvisor.in\ntriseptsolutions.com\ntriumph.com\ntrklnks.com\ntrkute.com\ntruecaller.com\ntrulia.com\ntruste.com\ntrustpilot.com\ntsite.jp\ntubepatrol.net\ntudou.com\ntumblr.com\ntums.ac.ir\ntunein.com\nturbobit.net\nturkishairlines.com\ntut.by\ntutorialspoint.com\ntutsplus.com\ntv.com\ntvguide.com\ntvn24.pl\ntwimg.com\ntwitch.tv\ntwitter.com\ntwoo.com\ntxxx.com\ntypepad.com\nuber.com\nubergizmo.com\nubi.com\nubuntu.com\nucla.edu\nucoz.ru\nudacity.com\nudemy.com\nudn.com\nukr.net\nulmart.ru\nulta.com\nultimate-guitar.com\numblr.com\numich.edu\nunam.mx\nunblocked.li\nunderarmour.com\nunicredit.it\nunikron.com\nunilever.com\nuniqlo.com\nuniquehomes.com\nunited.com\nunity3d.com\nuol.com.br\nuploaded.net\nupmc.com\nupornia.com\nuproxx.com\nups.com\nuptobox.com\nuptodown.com\nupwork.com\nurbandictionary.com\nurbanoutfitters.com\nurdupoint.com\nusaa.com\nusatoday.com\nusbank.com\nuserscloud.com\nusmagazine.com\nusnews.com\nusps.com\nustream.tv\nutexas.edu\nutorrent.com\nuzone.id\nv1.cn\nvacationstogo.com\nvagalume.com.br\nvaned.com\nvanguard.com\nvariety.com\nvarzesh3.com\nvcommission.com\nvector.co.jp\nvegas.com\nvegrecipesofindia.com\nvendormanagedinventory.com\nvenere.com\nvente-privee.com\nventuread.com\nverizon.com\nverizonwireless.com\nvesti.ru\nvetogate.com\nvg.no\nviamichelin.com\nvice.com\nvictoriassecret.com\nvid.me\nvideodownloadconverter.com\nvideomega.tv\nvideoyoum7.com\nvidto.me\nvidzi.tv\nvikingrivercruises.com\nvimeo.com\nvine.co\nvip.com\nviralands.com\nviralthread.com\nvirgilio.it\nvirgin-atlantic.com\nvirginaustralia.com\nvirginmedia.com\nvirtualtourist.com\nvisahq.com\nvistaprint.com\nvisualtour.com\nvitacost.com\nvitals.com\nvitamix.com\nviva.co.id\nviviun.com\nvk.com\nvk.me\nvmware.com\nvnexpress.net\nvoc.com.cn\nvodafone.in\nvodlocker.com\nvoluumtrk.com\nvox.com\nvrbo.com\nvsuch.com\nvulture.com\nw3.org\nw3schools.com\nwalgreens.com\nwalmart.com\nwanyh.com\nwargaming.net\nwarmportrait.com\nwarriorforum.com\nwashington.edu\nwashingtonpost.com\nwatchfree.to\nwatchseries.li\nwattpad.com\nwav.tv\nway2sms.com\nwayfair.com\nwbresearch.com\nwcr.org\nweather.com\nweather.com.cn\nweather.gov\nweathernews.jp\nweb.de\nwebcrawler.com\nweber.com\nwebex.com\nwebjaguar.com\nwebkinz.com\nweblio.jp\nwebmd.com\nwebmoney.ru\nwebmonkey.com\nwebpro.com\nwebssearches.com\nwebsta.me\nwebtretho.com\nweebly.com\nweheartit.com\nweibo.com\nweightwatchers.com\nwellness.com\nwellsfargo.com\nwelt.de\nwestelm.com\nwesternjournalism.com\nwestjet.com\nwestmonroepartners.com\nwetalk.tw\nwetransfer.com\nwetter.com\nwgsn.com\nwhat-character-are-you.com\nwhatsapp.com\nwhfoods.com\nwhirlpool.com\nwhitecapcanada.com\nwhitepages.com\nwho.int\nwho.is\nwholesalesuppliesplus.com\nwikia.com\nwikihow.com\nwikimedia.org\nwikipedia.org\nwikispaces.com\nwikitravel.org\nwikivoyage.org\nwikiwiki.jp\nwiktionary.org\nwildberries.ru\nwiley.com\nwilliamhill.com\nwilliams-sonoma.com\nwindows.com\nwindows.net\nwingtaiasia.com.sg\nwiocha.pl\nwipro.com\nwired.com\nwisc.edu\nwish.com\nwitiger.com\nwittyfeed.com\nwix.com\nwmaraci.com\nwmpoweruser.com\nwnd.com\nwolframalpha.com\nwoot.com\nwordpress.com\nwordpress.org\nwordreference.com\nworkercn.cn\nworkingre.com\nworldfirst.com\nworldlifestyle.com\nworldmarket.com\nworldoftanks.ru\nworldstarhiphop.com\nworldweb.com\nworldwise.net\nwotif.com\nwowhead.com\nwp.com\nwp.pl\nwpbeginner.com\nwsj.com\nwunderground.com\nwunderlist.com\nwuxiaworld.com\nwwe.com\nwww.gov.uk\nwww.nhs.uk\nwyborcza.pl\nwyndham.com\nx-rates.com\nxbox.com\nxda-developers.com\nxe.com\nxerox.com\nxfinity.com\nxiami.com\nxiaomi.com\nxing.com\nxinhuanet.com\nxkcd.com\nxl415.com\nxmediaserve.com\nxn--igbhe7b5a3d5a.com\nxoriant.com\nxuite.net\nxunlei.com\nxywy.com\ny8.com\nyadi.sk\nyahoo-mbga.jp\nyahoo.co.jp\nyahoo.com\nyallakora.com\nyam.com\nyandex.by\nyandex.com\nyandex.com.tr\nyandex.kz\nyandex.ru\nyandex.ua\nyaolan.com\nyaplakal.com\nyaraon-blog.com\nyellowpages.com\nyelp.com\nyenisafak.com\nyesky.com\nyhd.com\nyjc.ir\nynet.co.il\nyodobashi.com\nyomiuri.co.jp\nyoo.com\nyoox.com\nyouboy.com\nyoudao.com\nyouku.com\nyoum7.com\nyouneedabudget.com\nyouradexchange.com\nyourdictionary.com\nyouth.cn\nyoutube-mp3.org\nyoutube.com\nyr.no\nytimg.com\nyts.ag\nzalando.de\nzalukaj.tv\nzaman.com.tr\nzappos.com\nzara.com\nzazzle.com\nzdf.de\nzdnet.com\nzedo.com\nzeit.de\nzendesk.com\nzergnet.com\nzerohedge.com\nzeroredirect1.com\nzhaopin.com\nzhihu.com\nzillow.com\nzimbio.com\nzimuzu.tv\nzing.vn\nzippyshare.com\nzocdoc.com\nzoho.com\nzol.com.cn\nzomato.com\nzone-telechargement.com\nzoopla.co.uk\nzougla.gr\nzozo.jp\nzulily.com\nzwaar.net\nzybang.com\n".
 
 
 
 
--- a/browser/extensions/loop/chrome/content/modules/LoopRooms.jsm
+++ b/browser/extensions/loop/chrome/content/modules/LoopRooms.jsm
@@ -1,42 +1,42 @@
 /* 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";var _slicedToArray = function () {function sliceIterator(arr, i) {var _arr = [];var _n = true;var _d = false;var _e = undefined;try {for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {_arr.push(_s.value);if (i && _arr.length === i) break;}} catch (err) {_d = true;_e = err;} finally {try {if (!_n && _i["return"]) _i["return"]();} finally {if (_d) throw _e;}}return _arr;}return function (arr, i) {if (Array.isArray(arr)) {return arr;} else if (Symbol.iterator in Object(arr)) {return sliceIterator(arr, i);} else {throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}();function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}}var _Components = 
+"use strict";var _slicedToArray = function () {function sliceIterator(arr, i) {var _arr = [];var _n = true;var _d = false;var _e = undefined;try {for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {_arr.push(_s.value);if (i && _arr.length === i) break;}} catch (err) {_d = true;_e = err;} finally {try {if (!_n && _i["return"]) _i["return"]();} finally {if (_d) throw _e;}}return _arr;}return function (arr, i) {if (Array.isArray(arr)) {return arr;} else if (Symbol.iterator in Object(arr)) {return sliceIterator(arr, i);} else {throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}();function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}}var _Components =
 
 Components;var Cu = _Components.utils;
 
 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");var _Cu$import = 
+Cu.import("resource://gre/modules/Timer.jsm");var _Cu$import =
 
 Cu.import("chrome://loop/content/modules/MozLoopService.jsm", {});var MozLoopService = _Cu$import.MozLoopService;var LOOP_SESSION_TYPE = _Cu$import.LOOP_SESSION_TYPE;
-XPCOMUtils.defineLazyModuleGetter(this, "Promise", 
+XPCOMUtils.defineLazyModuleGetter(this, "Promise",
 "resource://gre/modules/Promise.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", 
+XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
 "resource://services-common/utils.js");
-XPCOMUtils.defineLazyModuleGetter(this, "WebChannel", 
+XPCOMUtils.defineLazyModuleGetter(this, "WebChannel",
 "resource://gre/modules/WebChannel.jsm");
 
-XPCOMUtils.defineLazyGetter(this, "eventEmitter", function () {var _Cu$import2 = 
+XPCOMUtils.defineLazyGetter(this, "eventEmitter", function () {var _Cu$import2 =
   Cu.import("resource://devtools/shared/event-emitter.js", {});var EventEmitter = _Cu$import2.EventEmitter;
-  return new EventEmitter();});
+  return new EventEmitter();
+});
 
-
-XPCOMUtils.defineLazyModuleGetter(this, "DomainWhitelist", 
+XPCOMUtils.defineLazyModuleGetter(this, "DomainWhitelist",
 "chrome://loop/content/modules/DomainWhitelist.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "LoopRoomsCache", 
+XPCOMUtils.defineLazyModuleGetter(this, "LoopRoomsCache",
 "chrome://loop/content/modules/LoopRoomsCache.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "loopUtils", 
+XPCOMUtils.defineLazyModuleGetter(this, "loopUtils",
 "chrome://loop/content/modules/utils.js", "utils");
-XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto", 
+XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto",
 "chrome://loop/content/shared/js/crypto.js", "LoopCrypto");
-XPCOMUtils.defineLazyModuleGetter(this, "ObjectUtils", 
+XPCOMUtils.defineLazyModuleGetter(this, "ObjectUtils",
 "resource://gre/modules/ObjectUtils.jsm");
 
 /* exported LoopRooms, roomsPushNotification */
 
 this.EXPORTED_SYMBOLS = ["LoopRooms", "roomsPushNotification"];
 
 // The maximum number of clients that we support currently.
 var CLIENT_MAX_SIZE = 2;
@@ -47,1222 +47,1222 @@ var MIN_TIME_BEFORE_ENCRYPTION = 5 * 100
 var MAX_TIME_BEFORE_ENCRYPTION = 30 * 60 * 1000;
 // Wait time between individual re-encryption cycles (1 second).
 var TIME_BETWEEN_ENCRYPTIONS = 1000;
 
 // This is the pref name for the url of the standalone pages.
 var LINKCLICKER_URL_PREFNAME = "loop.linkClicker.url";
 
 var roomsPushNotification = function roomsPushNotification(version, channelID) {
-  return LoopRoomsInternal.onNotification(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.
 var gDirty = true;
 // Global variable that keeps track of the currently used account.
 var gCurrentUser = null;
 // Global variable that keeps track of the room cache.
 var gRoomsCache = null;
 // Global variable that keeps track of the link clicker channel.
 var gLinkClickerChannel = null;
 // Global variable that keeps track of in-progress getAll requests.
 var gGetAllPromise = null;
 
 /**
- * Extend a `target` object with the properties defined in `source`.
- *
- * @param {Object} target The target object to receive properties defined in `source`
- * @param {Object} source The source object to copy properties from
- */
+                            * Extend a `target` object with the properties defined in `source`.
+                            *
+                            * @param {Object} target The target object to receive properties defined in `source`
+                            * @param {Object} source The source object to copy properties from
+                            */
 var extend = function extend(target, source) {var _iteratorNormalCompletion = true;var _didIteratorError = false;var _iteratorError = undefined;try {
     for (var _iterator = Object.getOwnPropertyNames(source)[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {var key = _step.value;
-      target[key] = source[key];}} catch (err) {_didIteratorError = true;_iteratorError = err;} finally {try {if (!_iteratorNormalCompletion && _iterator.return) {_iterator.return();}} finally {if (_didIteratorError) {throw _iteratorError;}}}
-
-  return target;};
-
+      target[key] = source[key];
+    }} catch (err) {_didIteratorError = true;_iteratorError = err;} finally {try {if (!_iteratorNormalCompletion && _iterator.return) {_iterator.return();}} finally {if (_didIteratorError) {throw _iteratorError;}}}
+  return target;
+};
 
 /**
- * Checks whether a participant is already part of a room.
- *
- * @see https://wiki.mozilla.org/Loop/Architecture/Rooms#User_Identification_in_a_Room
- *
- * @param {Object} room        A room object that contains a list of current participants
- * @param {Object} participant Participant to check if it's already there
- * @returns {Boolean} TRUE when the participant is already a member of the room,
- *                    FALSE when it's not.
- */
+    * Checks whether a participant is already part of a room.
+    *
+    * @see https://wiki.mozilla.org/Loop/Architecture/Rooms#User_Identification_in_a_Room
+    *
+    * @param {Object} room        A room object that contains a list of current participants
+    * @param {Object} participant Participant to check if it's already there
+    * @returns {Boolean} TRUE when the participant is already a member of the room,
+    *                    FALSE when it's not.
+    */
 var containsParticipant = function containsParticipant(room, participant) {var _iteratorNormalCompletion2 = true;var _didIteratorError2 = false;var _iteratorError2 = undefined;try {
     for (var _iterator2 = room.participants[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {var user = _step2.value;
       if (user.roomConnectionId == participant.roomConnectionId) {
-        return true;}}} catch (err) {_didIteratorError2 = true;_iteratorError2 = err;} finally {try {if (!_iteratorNormalCompletion2 && _iterator2.return) {_iterator2.return();}} finally {if (_didIteratorError2) {throw _iteratorError2;}}}
-
-
-  return false;};
-
+        return true;
+      }
+    }} catch (err) {_didIteratorError2 = true;_iteratorError2 = err;} finally {try {if (!_iteratorNormalCompletion2 && _iterator2.return) {_iterator2.return();}} finally {if (_didIteratorError2) {throw _iteratorError2;}}}
+  return false;
+};
 
 /**
- * Compares the list of participants of the room currently in the cache and an
- * updated version of that room. When a new participant is found, the 'joined'
- * event is emitted. When a participant is not found in the update, it emits a
- * 'left' event.
- *
- * @param {Object} room        A room object to compare the participants list
- *                             against
- * @param {Object} updatedRoom A room object that contains the most up-to-date
- *                             list of participants
- */
+    * Compares the list of participants of the room currently in the cache and an
+    * updated version of that room. When a new participant is found, the 'joined'
+    * event is emitted. When a participant is not found in the update, it emits a
+    * 'left' event.
+    *
+    * @param {Object} room        A room object to compare the participants list
+    *                             against
+    * @param {Object} updatedRoom A room object that contains the most up-to-date
+    *                             list of participants
+    */
 var checkForParticipantsUpdate = function checkForParticipantsUpdate(room, updatedRoom) {
   // Partially fetched rooms don't contain the participants list yet. Skip the
   // check for now.
   if (!("participants" in room)) {
-    return;}
-
+    return;
+  }
 
   var participant = void 0;
   // Check for participants that joined.
   var _iteratorNormalCompletion3 = true;var _didIteratorError3 = false;var _iteratorError3 = undefined;try {for (var _iterator3 = updatedRoom.participants[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {participant = _step3.value;
       if (!containsParticipant(room, participant)) {
         eventEmitter.emit("joined", room, participant);
-        eventEmitter.emit("joined:" + room.roomToken, participant);}}
-
-
+        eventEmitter.emit("joined:" + room.roomToken, participant);
+      }
+    }
 
     // Check for participants that left.
   } catch (err) {_didIteratorError3 = true;_iteratorError3 = err;} finally {try {if (!_iteratorNormalCompletion3 && _iterator3.return) {_iterator3.return();}} finally {if (_didIteratorError3) {throw _iteratorError3;}}}var _iteratorNormalCompletion4 = true;var _didIteratorError4 = false;var _iteratorError4 = undefined;try {for (var _iterator4 = room.participants[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {participant = _step4.value;
       if (!containsParticipant(updatedRoom, participant)) {
         eventEmitter.emit("left", room, participant);
-        eventEmitter.emit("left:" + room.roomToken, participant);}}} catch (err) {_didIteratorError4 = true;_iteratorError4 = err;} finally {try {if (!_iteratorNormalCompletion4 && _iterator4.return) {_iterator4.return();}} finally {if (_didIteratorError4) {throw _iteratorError4;}}}};
-
-
-
+        eventEmitter.emit("left:" + room.roomToken, participant);
+      }
+    }} catch (err) {_didIteratorError4 = true;_iteratorError4 = err;} finally {try {if (!_iteratorNormalCompletion4 && _iterator4.return) {_iterator4.return();}} finally {if (_didIteratorError4) {throw _iteratorError4;}}}
+};
 
 /**
- * These are wrappers which can be overriden by tests to allow us to manually
- * handle the timeouts.
- */
-var timerHandlers = { 
+    * These are wrappers which can be overriden by tests to allow us to manually
+    * handle the timeouts.
+    */
+var timerHandlers = {
   /**
-   * Wrapper for setTimeout.
-   *
-   * @param  {Function} callback The callback function.
-   * @param  {Number}   delay    The delay in milliseconds.
-   * @return {Number}            The timer identifier.
-   */
+                       * Wrapper for setTimeout.
+                       *
+                       * @param  {Function} callback The callback function.
+                       * @param  {Number}   delay    The delay in milliseconds.
+                       * @return {Number}            The timer identifier.
+                       */
   startTimer: function startTimer(callback, delay) {
-    return setTimeout(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.
- */
-var LoopRoomsInternal = { 
+        * 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.
+        */
+var LoopRoomsInternal = {
   /**
-   * @var {Map} rooms Collection of rooms currently in cache.
-   */
-  rooms: new Map(), 
+                           * @var {Map} rooms Collection of rooms currently in cache.
+                           */
+  rooms: new Map(),
 
   get roomsCache() {
     if (!gRoomsCache) {
-      gRoomsCache = new LoopRoomsCache();}
+      gRoomsCache = new LoopRoomsCache();
+    }
+    return gRoomsCache;
+  },
 
-    return gRoomsCache;}, 
+  /**
+      * @var {Object} encryptionQueue  This stores the list of rooms awaiting
+      *                                encryption and associated timers.
+      */
+  encryptionQueue: {
+    queue: [],
+    timer: null,
+    reset: function reset() {
+      this.queue = [];
+      this.timer = null;
+    } },
 
 
   /**
-   * @var {Object} encryptionQueue  This stores the list of rooms awaiting
-   *                                encryption and associated timers.
-   */
-  encryptionQueue: { 
-    queue: [], 
-    timer: null, 
-    reset: function reset() {
-      this.queue = [];
-      this.timer = null;} }, 
+          * Initialises the rooms, sets up the link clicker listener.
+          */
+  init: function init() {
+    Services.prefs.addObserver(LINKCLICKER_URL_PREFNAME,
+    this.setupLinkClickerListener.bind(this), false);
 
-
+    this.setupLinkClickerListener();
+  },
 
   /**
-   * Initialises the rooms, sets up the link clicker listener.
-   */
-  init: function init() {
-    Services.prefs.addObserver(LINKCLICKER_URL_PREFNAME, 
-    this.setupLinkClickerListener.bind(this), false);
-
-    this.setupLinkClickerListener();}, 
-
-
-  /**
-   * Sets up a WebChannel listener for the link clicker so that we can open
-   * rooms in the Firefox UI.
-   */
+      * Sets up a WebChannel listener for the link clicker so that we can open
+      * rooms in the Firefox UI.
+      */
   setupLinkClickerListener: function setupLinkClickerListener() {
     // Ensure any existing channel is tidied up.
     if (gLinkClickerChannel) {
       gLinkClickerChannel.stopListening();
-      gLinkClickerChannel = null;}
-
+      gLinkClickerChannel = null;
+    }
 
     var linkClickerUrl = Services.prefs.getCharPref(LINKCLICKER_URL_PREFNAME);
 
     // Don't do anything if there's no url.
     if (!linkClickerUrl) {
-      return;}
-
+      return;
+    }
 
     var uri = Services.io.newURI(linkClickerUrl, null, null);
 
     gLinkClickerChannel = new WebChannel("loop-link-clicker", uri);
-    gLinkClickerChannel.listen(this._handleLinkClickerMessage.bind(this));}, 
-
+    gLinkClickerChannel.listen(this._handleLinkClickerMessage.bind(this));
+  },
 
   /**
-   * @var {String} sessionType The type of user session. May be 'FXA' or 'GUEST'.
-   */
+      * @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;}, 
-
+    return MozLoopService.userProfile ? LOOP_SESSION_TYPE.FXA :
+    LOOP_SESSION_TYPE.GUEST;
+  },
 
   /**
-   * @var {Number} participantsCount The total amount of participants currently
-   *                                 inside all rooms.
-   */
+      * @var {Number} participantsCount The total amount of participants currently
+      *                                 inside all rooms.
+      */
   get participantsCount() {
     var count = 0;var _iteratorNormalCompletion5 = true;var _didIteratorError5 = false;var _iteratorError5 = undefined;try {
       for (var _iterator5 = this.rooms.values()[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {var room = _step5.value;
         if (room.deleted || !("participants" in room)) {
-          continue;}
-
-        count += room.participants.length;}} catch (err) {_didIteratorError5 = true;_iteratorError5 = err;} finally {try {if (!_iteratorNormalCompletion5 && _iterator5.return) {_iterator5.return();}} finally {if (_didIteratorError5) {throw _iteratorError5;}}}
-
-    return count;}, 
-
+          continue;
+        }
+        count += room.participants.length;
+      }} catch (err) {_didIteratorError5 = true;_iteratorError5 = err;} finally {try {if (!_iteratorNormalCompletion5 && _iterator5.return) {_iterator5.return();}} finally {if (_didIteratorError5) {throw _iteratorError5;}}}
+    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.
-   */
+      * 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* () {
     var 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.
     var 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) {
+        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;}}), 
-
-
+      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.
-   */
+       * 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 queueForEncryption(roomToken) {
     if (this.encryptionQueue.queue.indexOf(roomToken) == -1) {
-      this.encryptionQueue.queue.push(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) {
-      var waitTime = (MAX_TIME_BEFORE_ENCRYPTION - MIN_TIME_BEFORE_ENCRYPTION) * 
+      var 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);}}, 
-
-
+      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.
-   */
+      * 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) {
     if (roomData.roomKey) {
-      return roomData.roomKey;}
-
+      return roomData.roomKey;
+    }
 
-    return yield loopCrypto.generateKey();}), 
-
+    return yield loopCrypto.generateKey();
+  }),
 
   /**
-   * Encrypts a room key for sending to the server using the profile encryption
-   * key.
-   *
-   * @param {String} key The JSON web key to encrypt.
-   * @return {Promise} A promise that is resolved with the encrypted room key.
-   */
+       * Encrypts a room key for sending to the server using the profile encryption
+       * key.
+       *
+       * @param {String} key The JSON web key to encrypt.
+       * @return {Promise} A promise that is resolved with the encrypted room key.
+       */
   promiseEncryptedRoomKey: Task.async(function* (key) {
     var profileKey = yield MozLoopService.promiseProfileEncryptionKey();
 
     var encryptedRoomKey = yield loopCrypto.encryptBytes(profileKey, key);
-    return encryptedRoomKey;}), 
-
+    return encryptedRoomKey;
+  }),
 
   /**
-   * Decryptes a room key from the server using the profile encryption key.
-   *
-   * @param  {String} encryptedKey The room key to decrypt.
-   * @return {Promise} A promise that is resolved with the decrypted room key.
-   */
+       * Decryptes a room key from the server using the profile encryption key.
+       *
+       * @param  {String} encryptedKey The room key to decrypt.
+       * @return {Promise} A promise that is resolved with the decrypted room key.
+       */
   promiseDecryptRoomKey: Task.async(function* (encryptedKey) {
     var profileKey = yield MozLoopService.promiseProfileEncryptionKey();
 
     var decryptedRoomKey = yield loopCrypto.decryptBytes(profileKey, encryptedKey);
-    return decryptedRoomKey;}), 
-
+    return decryptedRoomKey;
+  }),
 
   /**
-   * Updates a roomUrl to add a new key onto the end of the url.
-   *
-   * @param  {String} roomUrl The existing url that may or may not have a key
-   *                          on the end.
-   * @param  {String} roomKey The new key to put on the url.
-   * @return {String}         The revised url.
-   */
+       * Updates a roomUrl to add a new key onto the end of the url.
+       *
+       * @param  {String} roomUrl The existing url that may or may not have a key
+       *                          on the end.
+       * @param  {String} roomKey The new key to put on the url.
+       * @return {String}         The revised url.
+       */
   refreshRoomUrlWithNewKey: function refreshRoomUrlWithNewKey(roomUrl, roomKey) {
     // Strip any existing key from the url.
     roomUrl = roomUrl.split("#")[0];
     // Now add the key to the url.
-    return roomUrl + "#" + roomKey;}, 
-
+    return roomUrl + "#" + roomKey;
+  },
 
   /**
-   * Encrypts room data in a format appropriate to sending to the loop
-   * server.
-   *
-   * @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.
-   */
+      * Encrypts room data in a format appropriate to sending to the loop
+      * server.
+      *
+      * @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) {
     var newRoomData = extend({}, roomData);
 
     if (!newRoomData.context) {
-      newRoomData.context = {};}
-
+      newRoomData.context = {};
+    }
 
     // First get the room key.
     var key = yield this.promiseGetOrCreateRoomKey(newRoomData);
 
     newRoomData.context.wrappedKey = yield this.promiseEncryptedRoomKey(key);
 
     // Now encrypt the actual data.
-    newRoomData.context.value = yield loopCrypto.encryptBytes(key, 
+    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";
     newRoomData.roomKey = key;
 
     var serverRoomData = extend({}, newRoomData);
 
     // We must not send these items to the server.
     delete serverRoomData.decryptedContext;
     delete serverRoomData.roomKey;
 
-    return { 
-      encrypted: serverRoomData, 
-      all: newRoomData };}), 
+    return {
+      encrypted: serverRoomData,
+      all: newRoomData };
 
-
+  }),
 
   /**
-   * Decrypts room data recevied from the server.
-   *
-   * @param  {Object} roomData The roomData with encrypted context.
-   * @return {Promise} A promise that is resolved with the decrypted room data.
-   */
+       * Decrypts room data recevied from the server.
+       *
+       * @param  {Object} roomData The roomData with encrypted context.
+       * @return {Promise} A promise that is resolved with the decrypted room data.
+       */
   promiseDecryptRoomData: Task.async(function* (roomData) {
     if (!roomData.context) {
-      return roomData;}
-
+      return roomData;
+    }
 
     if (!roomData.context.wrappedKey) {
-      throw new Error("Missing wrappedKey");}
-
+      throw new Error("Missing wrappedKey");
+    }
 
     var savedRoomKey = yield this.roomsCache.getKey(this.sessionType, roomData.roomToken);
     var fallback = false;
     var key = void 0;
 
     try {
-      key = yield this.promiseDecryptRoomKey(roomData.context.wrappedKey);} 
-    catch (error) {
+      key = yield this.promiseDecryptRoomKey(roomData.context.wrappedKey);
+    } catch (error) {
       // If we don't have a key saved, then we can't do anything.
       if (!savedRoomKey) {
-        throw error;}
-
+        throw error;
+      }
 
       // We failed to decrypt the room key, so has our FxA key changed?
       // If so, we fall-back to the saved room key.
       key = savedRoomKey;
-      fallback = true;}
-
+      fallback = true;
+    }
 
     var 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", 
+      MozLoopService.log.debug("Fell back to saved key, queuing for encryption",
       roomData.roomToken);
-      this.queueForEncryption(roomData.roomToken);} else 
-    if (!savedRoomKey || key != savedRoomKey) {
+      this.queueForEncryption(roomData.roomToken);
+    } 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);} 
-
+        yield this.roomsCache.setKey(this.sessionType, roomData.roomToken, key);
+      }
       catch (error) {
-        MozLoopService.log.error("Failed to save room key:", error);}}
-
-
+        MozLoopService.log.error("Failed to save room key:", error);
+      }
+    }
 
     roomData.roomKey = key;
     roomData.decryptedContext = JSON.parse(decryptedData);
 
     roomData.roomUrl = this.refreshRoomUrlWithNewKey(roomData.roomUrl, roomData.roomKey);
 
-    return roomData;}), 
-
+    return roomData;
+  }),
 
   /**
-   * Saves room information and notifies updates to any listeners.
-   *
-   * @param {Object}  roomData The new room data to save.
-   * @param {Boolean} isUpdate true if this is an update, false if its an add.
-   */
+       * Saves room information and notifies updates to any listeners.
+       *
+       * @param {Object}  roomData The new room data to save.
+       * @param {Boolean} isUpdate true if this is an update, false if its an add.
+       */
   saveAndNotifyUpdate: function saveAndNotifyUpdate(roomData, isUpdate) {
     this.rooms.set(roomData.roomToken, roomData);
 
     var eventName = isUpdate ? "update" : "add";
     eventEmitter.emit(eventName, roomData);
-    eventEmitter.emit(eventName + ":" + roomData.roomToken, roomData);}, 
-
+    eventEmitter.emit(eventName + ":" + roomData.roomToken, roomData);
+  },
 
   /**
-   * Either adds or updates the room to the room store and notifies to any
-   * listeners.
-   *
-   * This will decrypt information if necessary, and adjust for the legacy
-   * "roomName" field.
-   *
-   * @param {Object}  room     The new room to add.
-   * @param {Boolean} isUpdate true if this is an update to an existing room.
-   */
+      * Either adds or updates the room to the room store and notifies to any
+      * listeners.
+      *
+      * This will decrypt information if necessary, and adjust for the legacy
+      * "roomName" field.
+      *
+      * @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.
-      room.decryptedContext = { 
+      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 
-    {
+      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.
       try {
         var roomData = yield this.promiseDecryptRoomData(room);
 
-        this.saveAndNotifyUpdate(roomData, isUpdate);} 
-      catch (error) {
+        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 = {};
-        this.saveAndNotifyUpdate(room, isUpdate);}}}), 
-
-
-
+        this.saveAndNotifyUpdate(room, isUpdate);
+      }
+    }
+  }),
 
   /**
-   * Fetch a list of rooms that the currently registered user is a member of.
-   *
-   * @param {String}   [version] If set, we will fetch a list of changed rooms since
-   *                             `version`. Optional.
-   * @return {Promise}           A promise that is resolved with a list of rooms
-   *                             on success, or rejected with an error if it fails.
-   */
+       * Fetch a list of rooms that the currently registered user is a member of.
+       *
+       * @param {String}   [version] If set, we will fetch a list of changed rooms since
+       *                             `version`. Optional.
+       * @return {Promise}           A promise that is resolved with a list of rooms
+       *                             on success, or rejected with an error if it fails.
+       */
   getAll: function getAll(version) {
     if (gGetAllPromise && !version) {
-      return gGetAllPromise;}
-
+      return gGetAllPromise;
+    }
 
     if (!gDirty) {
-      return Promise.resolve([].concat(_toConsumableArray(this.rooms.values())));}
-
+      return Promise.resolve([].concat(_toConsumableArray(this.rooms.values())));
+    }
 
     gGetAllPromise = Task.spawn(function* () {
       // Fetch the rooms from the server.
       var url = "/rooms" + (version ? "?version=" + encodeURIComponent(version) : "");
       var response = yield MozLoopService.hawkRequest(this.sessionType, url, "GET");
       var roomsList = JSON.parse(response.body);
       if (!Array.isArray(roomsList)) {
-        throw new Error("Missing array of rooms in response.");}var _iteratorNormalCompletion6 = true;var _didIteratorError6 = false;var _iteratorError6 = undefined;try {
-
+        throw new Error("Missing array of rooms in response.");
+      }var _iteratorNormalCompletion6 = true;var _didIteratorError6 = false;var _iteratorError6 = undefined;try {
 
         for (var _iterator6 = roomsList[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {var room = _step6.value;
           // See if we already have this room in our cache.
           var orig = this.rooms.get(room.roomToken);
 
           if (room.deleted) {
             // If this client deleted the room, then we'll already have
             // deleted the room in the function below.
             if (orig) {
-              this.rooms.delete(room.roomToken);}
-
+              this.rooms.delete(room.roomToken);
+            }
 
             eventEmitter.emit("delete", room);
-            eventEmitter.emit("delete:" + room.roomToken, room);} else 
-          {
+            eventEmitter.emit("delete:" + room.roomToken, room);
+          } else {
             yield this.addOrUpdateRoom(room, !!orig);
 
             if (orig) {
-              checkForParticipantsUpdate(orig, room);}}}
-
-
-
+              checkForParticipantsUpdate(orig, room);
+            }
+          }
+        }
 
         // If there's no rooms in the list, remove the guest created room flag, so that
         // we don't keep registering for guest when we don't need to.
       } catch (err) {_didIteratorError6 = true;_iteratorError6 = err;} finally {try {if (!_iteratorNormalCompletion6 && _iterator6.return) {_iterator6.return();}} finally {if (_didIteratorError6) {throw _iteratorError6;}}}if (this.sessionType == LOOP_SESSION_TYPE.GUEST && !this.rooms.size) {
-        this.setGuestCreatedRoom(false);}
-
+        this.setGuestCreatedRoom(false);
+      }
 
       // Set the 'dirty' flag back to FALSE, since the list is as fresh as can be now.
       gDirty = false;
       gGetAllPromise = null;
-      return [].concat(_toConsumableArray(this.rooms.values()));}.
-    bind(this)).catch(function (error) {
+      return [].concat(_toConsumableArray(this.rooms.values()));
+    }.bind(this)).catch(function (error) {
       gGetAllPromise = null;
       // Re-throw error so callers get notified.
-      throw error;});
-
+      throw error;
+    });
 
-    return gGetAllPromise;}, 
-
+    return gGetAllPromise;
+  },
 
   /**
-   * Request information about number of participants joined to a specific room from the server.
-   * Used to determine infobar message state on the number of participants in the room.
-   *
-   * @param {String}  roomToken Room identifier
-   * @return {Number} Count of participants in the room.
-   */
+      * Request information about number of participants joined to a specific room from the server.
+      * Used to determine infobar message state on the number of participants in the room.
+      *
+      * @param {String}  roomToken Room identifier
+      * @return {Number} Count of participants in the room.
+      */
   getNumParticipants: function getNumParticipants(roomToken) {
     try {
       if (this.rooms && this.rooms.has(roomToken)) {
-        return this.rooms.get(roomToken).participants.length;}
-
-      return 0;} 
-
+        return this.rooms.get(roomToken).participants.length;
+      }
+      return 0;
+    }
     catch (ex) {
       // No room, log error and send back 0 to indicate none in room.
       MozLoopService.log.error("No room found in current session: ", ex);
-      return 0;}}, 
-
-
+      return 0;
+    }
+  },
 
   /**
-   * Request information about a specific room from the server. It will be
-   * returned from the cache if it's already in it.
-   *
-   * @param {String}   roomToken Room identifier
-   * @param {Function} callback  Function that will be invoked once the operation
-   *                             finished. The first argument passed will be an
-   *                             `Error` object or `null`. The second argument will
-   *                             be the list of rooms, if it was fetched successfully.
-   */
+      * Request information about a specific room from the server. It will be
+      * returned from the cache if it's already in it.
+      *
+      * @param {String}   roomToken Room identifier
+      * @param {Function} callback  Function that will be invoked once the operation
+      *                             finished. The first argument passed will be an
+      *                             `Error` object or `null`. The second argument will
+      *                             be the list of rooms, if it was fetched successfully.
+      */
   get: function get(roomToken, callback) {
     var room = this.rooms.has(roomToken) ? this.rooms.get(roomToken) : {};
     // Check if we need to make a request to the server to collect more room data.
     var needsUpdate = !("participants" in room);
     if (!gDirty && !needsUpdate) {
       // Dirty flag is not set AND the necessary data is available, so we can
       // simply return the room.
       callback(null, room);
-      return;}
-
+      return;
+    }
 
     Task.spawn(function* () {
-      var response = yield MozLoopService.hawkRequest(this.sessionType, 
+      var response = yield MozLoopService.hawkRequest(this.sessionType,
       "/rooms/" + encodeURIComponent(roomToken), "GET");
 
       var data = JSON.parse(response.body);
 
       room.roomToken = roomToken;
 
       if (data.deleted) {
         this.rooms.delete(room.roomToken);
 
         extend(room, data);
         eventEmitter.emit("delete", room);
-        eventEmitter.emit("delete:" + room.roomToken, room);} else 
-      {
+        eventEmitter.emit("delete:" + room.roomToken, room);
+      } else {
         yield this.addOrUpdateRoom(data, !needsUpdate);
 
-        checkForParticipantsUpdate(room, data);}
-
-      callback(null, room);}.
-    bind(this)).catch(callback);}, 
-
+        checkForParticipantsUpdate(room, data);
+      }
+      callback(null, room);
+    }.bind(this)).catch(callback);
+  },
 
   /**
-   * Create a room.
-   *
-   * @param {Object}   room     Properties to be sent to the LoopServer
-   * @param {Function} callback Function that will be invoked once the operation
-   *                            finished. The first argument passed will be an
-   *                            `Error` object or `null`. The second argument will
-   *                            be the room, if it was created successfully.
-   */
+      * Create a room.
+      *
+      * @param {Object}   room     Properties to be sent to the LoopServer
+      * @param {Function} callback Function that will be invoked once the operation
+      *                            finished. The first argument passed will be an
+      *                            `Error` object or `null`. The second argument will
+      *                            be the room, if it was created successfully.
+      */
   create: function create(room, callback) {
     if (!("decryptedContext" in room) || !("maxSize" in room)) {
       callback(new Error("Missing required property to create a room"));
-      return;}
-
+      return;
+    }
 
     if (!("roomOwner" in room)) {
-      room.roomOwner = "-";}
+      room.roomOwner = "-";
+    }
 
-
-    Task.spawn(function* () {var _ref = 
+    Task.spawn(function* () {var _ref =
       yield this.promiseEncryptRoomData(room);var all = _ref.all;var encrypted = _ref.encrypted;
 
       // Save both sets of data...
       room = all;
       // ...but only send the encrypted data.
-      var response = yield MozLoopService.hawkRequest(this.sessionType, "/rooms", 
+      var response = yield MozLoopService.hawkRequest(this.sessionType, "/rooms",
       "POST", encrypted);
 
       extend(room, JSON.parse(response.body));
       // Do not keep this value - it is a request to the server.
       delete room.expiresIn;
       // Make sure the url has the key on it.
       room.roomUrl = this.refreshRoomUrlWithNewKey(room.roomUrl, room.roomKey);
       this.rooms.set(room.roomToken, room);
 
       if (this.sessionType == LOOP_SESSION_TYPE.GUEST) {
-        this.setGuestCreatedRoom(true);}
-
+        this.setGuestCreatedRoom(true);
+      }
 
       // Now we've got the room token, we can save the key to disk.
       yield this.roomsCache.setKey(this.sessionType, room.roomToken, room.roomKey);
 
       eventEmitter.emit("add", room);
-      callback(null, room);}.
-    bind(this)).catch(callback);}, 
-
+      callback(null, room);
+    }.bind(this)).catch(callback);
+  },
 
   /**
-   * Sets whether or not the user has created a room in guest mode.
-   *
-   * @param {Boolean} created If the user has created the room.
-   */
+      * Sets whether or not the user has created a room in guest mode.
+      *
+      * @param {Boolean} created If the user has created the room.
+      */
   setGuestCreatedRoom: function setGuestCreatedRoom(created) {
     if (created) {
-      Services.prefs.setBoolPref("loop.createdRoom", created);} else 
-    {
-      Services.prefs.clearUserPref("loop.createdRoom");}}, 
-
-
+      Services.prefs.setBoolPref("loop.createdRoom", created);
+    } else {
+      Services.prefs.clearUserPref("loop.createdRoom");
+    }
+  },
 
   /**
-   * Returns true if the user has a created room in guest mode.
-   */
+      * Returns true if the user has a created room in guest mode.
+      */
   getGuestCreatedRoom: function getGuestCreatedRoom() {
     try {
-      return Services.prefs.getBoolPref("loop.createdRoom");} 
-    catch (x) {
-      return false;}}, 
-
-
+      return Services.prefs.getBoolPref("loop.createdRoom");
+    } catch (x) {
+      return false;
+    }
+  },
 
   open: function open(roomToken) {
-    var windowData = { 
-      roomToken: roomToken, 
+    var windowData = {
+      roomToken: roomToken,
       type: "room" };
 
 
     eventEmitter.emit("open", roomToken);
 
     return MozLoopService.openChatWindow(windowData, function () {
-      eventEmitter.emit("close");});}, 
-
-
+      eventEmitter.emit("close");
+    });
+  },
 
   /**
-   * Deletes a room.
-   *
-   * @param {String}   roomToken The room token.
-   * @param {Function} callback  Function that will be invoked once the operation
-   *                             finished. The first argument passed will be an
-   *                             `Error` object or `null`.
-   */
+      * Deletes a room.
+      *
+      * @param {String}   roomToken The room token.
+      * @param {Function} callback  Function that will be invoked once the operation
+      *                             finished. The first argument passed will be an
+      *                             `Error` object or `null`.
+      */
   delete: function _delete(roomToken, callback) {var _this = this;
     // XXX bug 1092954: Before deleting a room, the client should check room
     //     membership and forceDisconnect() all current participants.
     var room = this.rooms.get(roomToken);
     var url = "/rooms/" + encodeURIComponent(roomToken);
     MozLoopService.hawkRequest(this.sessionType, url, "DELETE").
     then(function () {
       _this.rooms.delete(roomToken);
       eventEmitter.emit("delete", room);
       eventEmitter.emit("delete:" + room.roomToken, room);
-      callback(null, room);}, 
-    function (error) {return callback(error);}).catch(function (error) {return callback(error);});}, 
-
+      callback(null, room);
+    }, function (error) {return callback(error);}).catch(function (error) {return callback(error);});
+  },
 
   /**
-   * Internal function to handle POSTs to a room.
-   *
-   * @param {String} roomToken  The room token.
-   * @param {Object} postData   The data to post to the room.
-   * @param {Function} callback Function that will be invoked once the operation
-   *                            finished. The first argument passed will be an
-   *                            `Error` object or `null`.
-   */
+      * Internal function to handle POSTs to a room.
+      *
+      * @param {String} roomToken  The room token.
+      * @param {Object} postData   The data to post to the room.
+      * @param {Function} callback Function that will be invoked once the operation
+      *                            finished. The first argument passed will be an
+      *                            `Error` object or `null`.
+      */
   _postToRoom: function _postToRoom(roomToken, postData, callback) {var _this2 = this;
     var url = "/rooms/" + encodeURIComponent(roomToken);
     MozLoopService.hawkRequest(this.sessionType, url, "POST", postData).then(function (response) {
       // Delete doesn't have a body return.
       var joinData = response.body ? JSON.parse(response.body) : {};
       if ("sessionToken" in joinData) {
         var room = _this2.rooms.get(roomToken);
-        room.sessionToken = joinData.sessionToken;}
-
-      callback(null, joinData);}, 
-    function (error) {return callback(error);}).catch(function (error) {return callback(error);});}, 
-
+        room.sessionToken = joinData.sessionToken;
+      }
+      callback(null, joinData);
+    }, function (error) {return callback(error);}).catch(function (error) {return callback(error);});
+  },
 
   /**
-   * Joins a room. The sessionToken that is returned by the server will be stored
-   * locally, for future use.
-   *
-   * @param {String} roomToken   The room token.
-   * @param {String} displayName The user's display name.
-   * @param {Function} callback  Function that will be invoked once the operation
-   *                             finished. The first argument passed will be an
-   *                             `Error` object or `null`.
-   */
+      * Joins a room. The sessionToken that is returned by the server will be stored
+      * locally, for future use.
+      *
+      * @param {String} roomToken   The room token.
+      * @param {String} displayName The user's display name.
+      * @param {Function} callback  Function that will be invoked once the operation
+      *                             finished. The first argument passed will be an
+      *                             `Error` object or `null`.
+      */
   join: function join(roomToken, displayName, callback) {
-    this._postToRoom(roomToken, { 
-      action: "join", 
-      displayName: displayName, 
-      clientMaxSize: CLIENT_MAX_SIZE }, 
-    callback);}, 
-
+    this._postToRoom(roomToken, {
+      action: "join",
+      displayName: displayName,
+      clientMaxSize: CLIENT_MAX_SIZE },
+    callback);
+  },
 
   /**
-   * Refreshes a room
-   *
-   * @param {String} roomToken    The room token.
-   * @param {String} sessionToken The session token for the session that has been
-   *                              joined.
-   * @param {Function} callback   Function that will be invoked once the operation
-   *                              finished. The first argument passed will be an
-   *                              `Error` object or `null`.
-   */
+      * Refreshes a room
+      *
+      * @param {String} roomToken    The room token.
+      * @param {String} sessionToken The session token for the session that has been
+      *                              joined.
+      * @param {Function} callback   Function that will be invoked once the operation
+      *                              finished. The first argument passed will be an
+      *                              `Error` object or `null`.
+      */
   refreshMembership: function refreshMembership(roomToken, sessionToken, callback) {
-    this._postToRoom(roomToken, { 
-      action: "refresh", 
-      sessionToken: sessionToken }, 
-    callback);}, 
-
+    this._postToRoom(roomToken, {
+      action: "refresh",
+      sessionToken: sessionToken },
+    callback);
+  },
 
   /**
-   * Leaves a room. Although this is an sync function, no data is returned
-   * from the server.
-   *
-   * @param {String} roomToken    The room token.
-   * @param {String} sessionToken The session token for the session that has been
-   *                              joined
-   * @param {Function} callback   Optional. Function that will be invoked once the operation
-   *                              finished. The first argument passed will be an
-   *                              `Error` object or `null`.
-   */
+      * Leaves a room. Although this is an sync function, no data is returned
+      * from the server.
+      *
+      * @param {String} roomToken    The room token.
+      * @param {String} sessionToken The session token for the session that has been
+      *                              joined
+      * @param {Function} callback   Optional. Function that will be invoked once the operation
+      *                              finished. The first argument passed will be an
+      *                              `Error` object or `null`.
+      */
   leave: function leave(roomToken, sessionToken, callback) {
     if (!callback) {
       callback = function callback(error) {
         if (error) {
-          MozLoopService.log.error(error);}};}
-
-
-
+          MozLoopService.log.error(error);
+        }
+      };
+    }
     var room = this.rooms.get(roomToken);
     if (!sessionToken && room && room.sessionToken) {
       if (!room || !room.sessionToken) {
-        return;}
-
+        return;
+      }
       sessionToken = room.sessionToken;
-      delete room.sessionToken;}
-
-    this._postToRoom(roomToken, { 
-      action: "leave", 
-      sessionToken: sessionToken }, 
-    callback);}, 
-
+      delete room.sessionToken;
+    }
+    this._postToRoom(roomToken, {
+      action: "leave",
+      sessionToken: sessionToken },
+    callback);
+  },
 
   /**
-   * Forwards connection status to the server.
-   *
-   * @param {String}                  roomToken The room token.
-   * @param {String}                  sessionToken The session token for the
-   *                                               session that has been
-   *                                               joined.
-   * @param {sharedActions.SdkStatus} status The connection status.
-   * @param {Function} callback Optional. Function that will be invoked once
-   *                            the operation finished. The first argument
-   *                            passed will be an `Error` object or `null`.
-   */
+      * Forwards connection status to the server.
+      *
+      * @param {String}                  roomToken The room token.
+      * @param {String}                  sessionToken The session token for the
+      *                                               session that has been
+      *                                               joined.
+      * @param {sharedActions.SdkStatus} status The connection status.
+      * @param {Function} callback Optional. Function that will be invoked once
+      *                            the operation finished. The first argument
+      *                            passed will be an `Error` object or `null`.
+      */
   sendConnectionStatus: function sendConnectionStatus(roomToken, sessionToken, status, callback) {
     if (!callback) {
       callback = function callback(error) {
         if (error) {
-          MozLoopService.log.error(error);}};}
-
-
+          MozLoopService.log.error(error);
+        }
+      };
+    }
+    this._postToRoom(roomToken, {
+      action: "status",
+      event: status.event,
+      state: status.state,
+      connections: status.connections,
+      sendStreams: status.sendStreams,
+      recvStreams: status.recvStreams,
+      sessionToken: sessionToken },
+    callback);
+  },
 
-    this._postToRoom(roomToken, { 
-      action: "status", 
-      event: status.event, 
-      state: status.state, 
-      connections: status.connections, 
-      sendStreams: status.sendStreams, 
-      recvStreams: status.recvStreams, 
-      sessionToken: sessionToken }, 
-    callback);}, 
-
-
-  _domainLog: { 
-    domainMap: new Map(), 
-    roomToken: null }, 
+  _domainLog: {
+    domainMap: new Map(),
+    roomToken: null },
 
 
   /**
-   * Record a url associated to a room for batch submission if whitelisted.
-   *
-   * @param {String} roomToken The room token
-   * @param {String} url       Url with the domain to record
-   */
+                        * Record a url associated to a room for batch submission if whitelisted.
+                        *
+                        * @param {String} roomToken The room token
+                        * @param {String} url       Url with the domain to record
+                        */
   _recordUrl: function _recordUrl(roomToken, url) {
     // Reset the log of domains if somehow we changed room tokens.
     if (this._domainLog.roomToken !== roomToken) {
       this._domainLog.roomToken = roomToken;
-      this._domainLog.domainMap.clear();}
-
+      this._domainLog.domainMap.clear();
+    }
 
     var domain = void 0;
     try {
-      domain = Services.eTLD.getBaseDomain(Services.io.newURI(url, null, null));} 
-
+      domain = Services.eTLD.getBaseDomain(Services.io.newURI(url, null, null));
+    }
     catch (ex) {
       // Failed to extract domain, so don't record it.
-      return;}
-
+      return;
+    }
 
     // Only record domains that are whitelisted.
     if (!DomainWhitelist.check(domain)) {
-      return;}
-
+      return;
+    }
 
     // Increment the count for previously recorded domains.
     if (this._domainLog.domainMap.has(domain)) {
-      this._domainLog.domainMap.get(domain).count++;}
-
+      this._domainLog.domainMap.get(domain).count++;
+    }
     // Initialize the map for the domain with a value that can be submitted.
     else {
-        this._domainLog.domainMap.set(domain, { count: 1, domain: domain });}}, 
-
-
+        this._domainLog.domainMap.set(domain, { count: 1, domain: domain });
+      }
+  },
 
   /**
-   * Log the domains associated to a room token.
-   *
-   * @param {String} roomToken  The room token
-   * @param {Function} callback Function that will be invoked once the operation
-   *                            finished. The first argument passed will be an
-   *                            `Error` object or `null`.
-   */
+      * Log the domains associated to a room token.
+      *
+      * @param {String} roomToken  The room token
+      * @param {Function} callback Function that will be invoked once the operation
+      *                            finished. The first argument passed will be an
+      *                            `Error` object or `null`.
+      */
   logDomains: function logDomains(roomToken, callback) {
     if (!callback) {
       callback = function callback(error) {
         if (error) {
-          MozLoopService.log.error(error);}};}
-
-
-
+          MozLoopService.log.error(error);
+        }
+      };
+    }
 
     // Submit the domains that have been collected so far.
-    if (this._domainLog.roomToken === roomToken && 
+    if (this._domainLog.roomToken === roomToken &&
     this._domainLog.domainMap.size > 0) {
-      this._postToRoom(roomToken, { 
-        action: "logDomain", 
-        domains: [].concat(_toConsumableArray(this._domainLog.domainMap.values())) }, 
+      this._postToRoom(roomToken, {
+        action: "logDomain",
+        domains: [].concat(_toConsumableArray(this._domainLog.domainMap.values())) },
       callback);
-      this._domainLog.domainMap.clear();}
-
+      this._domainLog.domainMap.clear();
+    }
     // Indicate that nothing was logged.
     else {
-        callback(null);}}, 
-
-
+        callback(null);
+      }
+  },
 
   /**
-   * Updates a room.
-   *
-   * @param {String} roomToken  The room token
-   * @param {Object} roomData   Updated context data for the room. The following
-   *                            properties are expected: `roomName` and `urls`.
-   *                            IMPORTANT: Data in the `roomData::urls` array
-   *                            will be stored as-is, so any data omitted therein
-   *                            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`.
-   */
+      * Updates a room.
+      *
+      * @param {String} roomToken  The room token
+      * @param {Object} roomData   Updated context data for the room. The following
+      *                            properties are expected: `roomName` and `urls`.
+      *                            IMPORTANT: Data in the `roomData::urls` array
+      *                            will be stored as-is, so any data omitted therein
+      *                            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 update(roomToken, roomData, callback) {
     var room = this.rooms.get(roomToken);
     var url = "/rooms/" + encodeURIComponent(roomToken);
     if (!room.decryptedContext) {
-      room.decryptedContext = { 
-        roomName: roomData.roomName || room.roomName };} else 
+      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.decryptedContext.roomName ||
+      room.roomName;
+    }
     if (roomData.urls && roomData.urls.length) {
       // For now we only support adding one URL to the room context.
       var context = roomData.urls[0];
       room.decryptedContext.urls = [context];
 
       // Record the url for reporting if enabled.
       if (Services.prefs.getBoolPref("loop.logDomains")) {
-        this._recordUrl(roomToken, context.location);}}
-
+        this._recordUrl(roomToken, context.location);
+      }
+    }
 
-
-    Task.spawn(function* () {var _ref2 = 
+    Task.spawn(function* () {var _ref2 =
       yield this.promiseEncryptRoomData(room);var all = _ref2.all;var encrypted = _ref2.encrypted;
 
       // For patch, we only send the context data.
-      var sendData = { 
+      var 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);
 
-      var response = yield MozLoopService.hawkRequest(this.sessionType, 
+      var response = yield MozLoopService.hawkRequest(this.sessionType,
       url, "PATCH", sendData);
 
       var newRoomData = all;
 
       extend(newRoomData, JSON.parse(response.body));
       this.rooms.set(roomToken, newRoomData);
-      callback(null, newRoomData);}.
-    bind(this)).catch(callback);}, 
-
+      callback(null, newRoomData);
+    }.bind(this)).catch(callback);
+  },
 
   /**
-   * Callback used to indicate changes to rooms data on the LoopServer.
-   *
-   * @param {String} version   Version number assigned to this change set.
-   * @param {String} channelID Notification channel identifier.
-   */
+      * Callback used to indicate changes to rooms data on the LoopServer.
+      *
+      * @param {String} version   Version number assigned to this change set.
+      * @param {String} channelID Notification channel identifier.
+      */
   onNotification: function onNotification(version, channelID) {
     // See if we received a notification for the channel that's currently active:
     var channelIDs = MozLoopService.channelIDs;
-    if (this.sessionType == LOOP_SESSION_TYPE.GUEST && channelID != channelIDs.roomsGuest || 
+    if (this.sessionType == LOOP_SESSION_TYPE.GUEST && channelID != channelIDs.roomsGuest ||
     this.sessionType == LOOP_SESSION_TYPE.FXA && channelID != channelIDs.roomsFxA) {
-      return;}
-
+      return;
+    }
 
     var oldDirty = gDirty;
     gDirty = true;
 
     // If we were already dirty, then get the full set of rooms. For example,
     // we'd already be dirty if we had started up but not got the list of rooms
     // yet.
-    this.getAll(oldDirty ? null : version, function () {});}, 
-
+    this.getAll(oldDirty ? null : version, function () {});
+  },
 
   /**
-   * When a user logs in or out, this method should be invoked to check whether
-   * the rooms cache needs to be refreshed.
-   *
-   * @param {String|null} user The FxA userID or NULL
-   */
+      * When a user logs in or out, this method should be invoked to check whether
+      * the rooms cache needs to be refreshed.
+      *
+      * @param {String|null} user The FxA userID or NULL
+      */
   maybeRefresh: function maybeRefresh() {var user = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0];
     if (gCurrentUser == user) {
-      return;}
-
+      return;
+    }
 
     gCurrentUser = user;
     if (!gDirty) {
       gDirty = true;
       this.rooms.clear();
       eventEmitter.emit("refresh");
-      this.getAll(null, function () {});}}, 
-
-
+      this.getAll(null, function () {});
+    }
+  },
 
   /**
-   * Handles a message received from the content channel.
-   *
-   * @param {String} id              The channel id.
-   * @param {Object} message         The message received.
-   * @param {Object} sendingContext  The context for the sending location.
-   */
+      * Handles a message received from the content channel.
+      *
+      * @param {String} id              The channel id.
+      * @param {Object} message         The message received.
+      * @param {Object} sendingContext  The context for the sending location.
+      */
   _handleLinkClickerMessage: function _handleLinkClickerMessage(id, message, sendingContext) {
     if (!message) {
-      return;}
-
+      return;
+    }
 
     var sendResponse = function sendResponse(response, alreadyOpen) {
-      gLinkClickerChannel.send({ 
-        response: response, 
-        alreadyOpen: alreadyOpen }, 
-      sendingContext);};
-
+      gLinkClickerChannel.send({
+        response: response,
+        alreadyOpen: alreadyOpen },
+      sendingContext);
+    };
 
     var hasRoom = this.rooms.has(message.roomToken);
 
     switch (message.command) {
       case "checkWillOpenRoom":
         sendResponse(hasRoom, false);
         break;
       case "openRoom":
         if (hasRoom) {
           if (MozLoopService.isChatWindowOpen(message.roomToken)) {
-            sendResponse(hasRoom, true);} else 
-          {
+            sendResponse(hasRoom, true);
+          } else {
             this.open(message.roomToken);
-            sendResponse(hasRoom, false);}} else 
-
-        {
-          sendResponse(hasRoom, false);}
-
+            sendResponse(hasRoom, false);
+          }
+        } else {
+          sendResponse(hasRoom, false);
+        }
         break;
       default:
         sendResponse(false, false);
-        break;}} };
+        break;}
 
-
+  } };
 
 Object.freeze(LoopRoomsInternal);
 
 /**
- * Public Loop Rooms API.
- *
- * LoopRooms implements the EventEmitter interface by exposing three methods -
- * `on`, `once` and `off` - to subscribe to events.
- * At this point the following events may be subscribed to:
- *  - 'add[:{room-id}]':    A new room object was successfully added to the data
- *                          store.
- *  - 'delete[:{room-id}]': A room was successfully removed from the data store.
- *  - 'update[:{room-id}]': A room object was successfully updated with changed
- *                          properties in the data store.
- *  - 'joined[:{room-id}]': A participant joined a room.
- *  - 'left[:{room-id}]':   A participant left a room.
- *
- * See the internal code for the API documentation.
- */
-this.LoopRooms = { 
+                                   * Public Loop Rooms API.
+                                   *
+                                   * LoopRooms implements the EventEmitter interface by exposing three methods -
+                                   * `on`, `once` and `off` - to subscribe to events.
+                                   * At this point the following events may be subscribed to:
+                                   *  - 'add[:{room-id}]':    A new room object was successfully added to the data
+                                   *                          store.
+                                   *  - 'delete[:{room-id}]': A room was successfully removed from the data store.
+                                   *  - 'update[:{room-id}]': A room object was successfully updated with changed
+                                   *                          properties in the data store.
+                                   *  - 'joined[:{room-id}]': A participant joined a room.
+                                   *  - 'left[:{room-id}]':   A participant left a room.
+                                   *
+                                   * See the internal code for the API documentation.
+                                   */
+this.LoopRooms = {
   init: function init() {
-    LoopRoomsInternal.init();}, 
-
+    LoopRoomsInternal.init();
+  },
 
   get participantsCount() {
-    return LoopRoomsInternal.participantsCount;}, 
-
+    return LoopRoomsInternal.participantsCount;
+  },
 
   getAll: function getAll(version, callback) {
     if (!callback) {
       callback = version;
-      version = null;}
-
+      version = null;
+    }
 
     LoopRoomsInternal.getAll(version).then(function (result) {return callback(null, result);}).
-    catch(function (error) {return callback(error);});}, 
-
+    catch(function (error) {return callback(error);});
+  },
 
   get: function get(roomToken, callback) {
-    return LoopRoomsInternal.get(roomToken, callback);}, 
-
+    return LoopRoomsInternal.get(roomToken, callback);
+  },
 
   create: function create(options, callback) {
-    return LoopRoomsInternal.create(options, callback);}, 
-
+    return LoopRoomsInternal.create(options, callback);
+  },
 
   open: function open(roomToken) {
-    return LoopRoomsInternal.open(roomToken);}, 
-
+    return LoopRoomsInternal.open(roomToken);
+  },
 
   delete: function _delete(roomToken, callback) {
-    return LoopRoomsInternal.delete(roomToken, callback);}, 
-
+    return LoopRoomsInternal.delete(roomToken, callback);
+  },
 
   join: function join(roomToken, displayName, callback) {
-    return LoopRoomsInternal.join(roomToken, displayName, callback);}, 
-
+    return LoopRoomsInternal.join(roomToken, displayName, callback);
+  },
 
   refreshMembership: function refreshMembership(roomToken, sessionToken, callback) {
-    return LoopRoomsInternal.refreshMembership(roomToken, sessionToken, 
-    callback);}, 
-
+    return LoopRoomsInternal.refreshMembership(roomToken, sessionToken,
+    callback);
+  },
 
   leave: function leave(roomToken, sessionToken, callback) {
-    return LoopRoomsInternal.leave(roomToken, sessionToken, callback);}, 
-
+    return LoopRoomsInternal.leave(roomToken, sessionToken, callback);
+  },
 
   sendConnectionStatus: function sendConnectionStatus(roomToken, sessionToken, status, callback) {
-    return LoopRoomsInternal.sendConnectionStatus(roomToken, sessionToken, status, callback);}, 
-
+    return LoopRoomsInternal.sendConnectionStatus(roomToken, sessionToken, status, callback);
+  },
 
   logDomains: function logDomains(roomToken, callback) {
-    return LoopRoomsInternal.logDomains(roomToken, callback);}, 
-
+    return LoopRoomsInternal.logDomains(roomToken, callback);
+  },
 
   update: function update(roomToken, roomData, callback) {
-    return LoopRoomsInternal.update(roomToken, roomData, callback);}, 
-
+    return LoopRoomsInternal.update(roomToken, roomData, callback);
+  },
 
   getGuestCreatedRoom: function getGuestCreatedRoom() {
-    return LoopRoomsInternal.getGuestCreatedRoom();}, 
-
+    return LoopRoomsInternal.getGuestCreatedRoom();
+  },
 
   maybeRefresh: function maybeRefresh(user) {
-    return LoopRoomsInternal.maybeRefresh(user);}, 
-
+    return LoopRoomsInternal.maybeRefresh(user);
+  },
 
   getNumParticipants: function getNumParticipants(roomToken) {
-    return LoopRoomsInternal.getNumParticipants(roomToken);}, 
-
+    return LoopRoomsInternal.getNumParticipants(roomToken);
+  },
 
   /**
-   * This method is only useful for unit tests to set the rooms cache to contain
-   * a list of fake room data that can be asserted in tests.
-   *
-   * @param {Map} stub Stub cache containing fake rooms data
-   */
+      * This method is only useful for unit tests to set the rooms cache to contain
+      * a list of fake room data that can be asserted in tests.
+      *
+      * @param {Map} stub Stub cache containing fake rooms data
+      */
   stubCache: function stubCache(stub) {
     LoopRoomsInternal.rooms.clear();
     if (stub) {
       // Fill up the rooms cache with room objects provided in the `stub` Map.
       var _iteratorNormalCompletion7 = true;var _didIteratorError7 = false;var _iteratorError7 = undefined;try {for (var _iterator7 = stub.entries()[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {var _ref3 = _step7.value;var _ref4 = _slicedToArray(_ref3, 2);var key = _ref4[0];var value = _ref4[1];
-          LoopRoomsInternal.rooms.set(key, value);}} catch (err) {_didIteratorError7 = true;_iteratorError7 = err;} finally {try {if (!_iteratorNormalCompletion7 && _iterator7.return) {_iterator7.return();}} finally {if (_didIteratorError7) {throw _iteratorError7;}}}
-
-      gDirty = false;} else 
-    {
+          LoopRoomsInternal.rooms.set(key, value);
+        }} catch (err) {_didIteratorError7 = true;_iteratorError7 = err;} finally {try {if (!_iteratorNormalCompletion7 && _iterator7.return) {_iterator7.return();}} finally {if (_didIteratorError7) {throw _iteratorError7;}}}
+      gDirty = false;
+    } else {
       // Restore the cache to not be stubbed anymore, but it'll need a refresh
       // from the server for sure.
-      gDirty = true;}}, 
-
-
+      gDirty = true;
+    }
+  },
 
   promise: function promise(method) {var _this3 = this;for (var _len = arguments.length, params = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {params[_key - 1] = arguments[_key];}
     if (method == "getAll") {
-      return LoopRoomsInternal.getAll.apply(LoopRoomsInternal, params);}
-
+      return LoopRoomsInternal.getAll.apply(LoopRoomsInternal, params);
+    }
 
     return new Promise(function (resolve, reject) {
       _this3[method].apply(_this3, params.concat([function (error, result) {
         if (error) {
-          reject(error);} else 
-        {
-          resolve(result);}}]));});}, 
-
-
-
+          reject(error);
+        } else {
+          resolve(result);
+        }
+      }]));
+    });
+  },
 
-
-  on: function on() {var _eventEmitter;return (_eventEmitter = eventEmitter).on.apply(_eventEmitter, arguments);}, 
+  on: function on() {var _eventEmitter;return (_eventEmitter = eventEmitter).on.apply(_eventEmitter, arguments);},
 
-  once: function once() {var _eventEmitter2;return (_eventEmitter2 = eventEmitter).once.apply(_eventEmitter2, arguments);}, 
+  once: function once() {var _eventEmitter2;return (_eventEmitter2 = eventEmitter).once.apply(_eventEmitter2, arguments);},
 
-  off: function off() {var _eventEmitter3;return (_eventEmitter3 = eventEmitter).off.apply(_eventEmitter3, arguments);}, 
+  off: function off() {var _eventEmitter3;return (_eventEmitter3 = eventEmitter).off.apply(_eventEmitter3, arguments);},
 
   /**
-   * Expose the internal rooms map for testing purposes only. This avoids
-   * needing to mock the server interfaces.
-   *
-   * @param {Map} roomsCache The new cache data to set for testing purposes. If
-   *                         not specified, it will reset the cache.
-   */
+                                                                                                                          * Expose the internal rooms map for testing purposes only. This avoids
+                                                                                                                          * needing to mock the server interfaces.
+                                                                                                                          *
+                                                                                                                          * @param {Map} roomsCache The new cache data to set for testing purposes. If
+                                                                                                                          *                         not specified, it will reset the cache.
+                                                                                                                          */
   _setRoomsCache: function _setRoomsCache(roomsCache, orig) {
     LoopRoomsInternal.rooms.clear();
     gDirty = true;
 
     if (roomsCache) {
       // Need a clone as the internal map is read-only.
       var _iteratorNormalCompletion8 = true;var _didIteratorError8 = false;var _iteratorError8 = undefined;try {for (var _iterator8 = roomsCache[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {var _ref5 = _step8.value;var _ref6 = _slicedToArray(_ref5, 2);var key = _ref6[0];var value = _ref6[1];
 
           LoopRoomsInternal.rooms.set(key, value);
           if (orig) {
-            checkForParticipantsUpdate(orig, value);}}} catch (err) {_didIteratorError8 = true;_iteratorError8 = err;} finally {try {if (!_iteratorNormalCompletion8 && _iterator8.return) {_iterator8.return();}} finally {if (_didIteratorError8) {throw _iteratorError8;}}}
-
-
+            checkForParticipantsUpdate(orig, value);
+          }
+        }} catch (err) {_didIteratorError8 = true;_iteratorError8 = err;} finally {try {if (!_iteratorNormalCompletion8 && _iterator8.return) {_iterator8.return();}} finally {if (_didIteratorError8) {throw _iteratorError8;}}}
       gGetAllPromise = null;
-      gDirty = false;}} };
-
-
+      gDirty = false;
+    }
+  } };
 
 Object.freeze(this.LoopRooms);
--- a/browser/extensions/loop/chrome/content/modules/LoopRoomsCache.jsm
+++ b/browser/extensions/loop/chrome/content/modules/LoopRoomsCache.jsm
@@ -1,157 +1,158 @@
 /* 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";var _Components = 
+"use strict";var _Components =
 
 Components;var Cu = _Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
-Cu.import("resource://gre/modules/Task.jsm");var _Cu$import = 
+Cu.import("resource://gre/modules/Task.jsm");var _Cu$import =
 
 Cu.import("chrome://loop/content/modules/MozLoopService.jsm", {});var MozLoopService = _Cu$import.MozLoopService;var LOOP_SESSION_TYPE = _Cu$import.LOOP_SESSION_TYPE;
-XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", 
+XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
 "resource://services-common/utils.js");
 XPCOMUtils.defineLazyModuleGetter(this, "OS", "resource://gre/modules/osfile.jsm");
 
 this.EXPORTED_SYMBOLS = ["LoopRoomsCache"];
 
 var LOOP_ROOMS_CACHE_FILENAME = "loopRoomsCache.json";
 XPCOMUtils.defineConstant(this, "LOOP_ROOMS_CACHE_FILENAME", LOOP_ROOMS_CACHE_FILENAME);
 
 /**
- * RoomsCache is a cache for saving simple rooms data to the disk in case we
- * need it for back-up purposes, e.g. recording room keys for FxA if the user
- * changes their password.
- *
- * The format of the data is:
- *
- * {
- *   <sessionType>: {
- *     <roomToken>: {
- *       "key": <roomKey>
- *     }
- *   }
- * }
- *
- * It is intended to try and keep the data forward and backwards compatible in
- * a reasonable manner, hence why the structure is more complex than it needs
- * to be to store tokens and keys.
- *
- * @param {Object} options The options for the RoomsCache, containing:
- *   - {String} baseDir   The base directory in which to save the file.
- *   - {String} filename  The filename for the cache file.
- */
+                                                                                          * RoomsCache is a cache for saving simple rooms data to the disk in case we
+                                                                                          * need it for back-up purposes, e.g. recording room keys for FxA if the user
+                                                                                          * changes their password.
+                                                                                          *
+                                                                                          * The format of the data is:
+                                                                                          *
+                                                                                          * {
+                                                                                          *   <sessionType>: {
+                                                                                          *     <roomToken>: {
+                                                                                          *       "key": <roomKey>
+                                                                                          *     }
+                                                                                          *   }
+                                                                                          * }
+                                                                                          *
+                                                                                          * It is intended to try and keep the data forward and backwards compatible in
+                                                                                          * a reasonable manner, hence why the structure is more complex than it needs
+                                                                                          * to be to store tokens and keys.
+                                                                                          *
+                                                                                          * @param {Object} options The options for the RoomsCache, containing:
+                                                                                          *   - {String} baseDir   The base directory in which to save the file.
+                                                                                          *   - {String} filename  The filename for the cache file.
+                                                                                          */
 function LoopRoomsCache(options) {
   options = options || {};
 
   this.baseDir = options.baseDir || OS.Constants.Path.profileDir;
   this.path = OS.Path.join(
-  this.baseDir, 
+  this.baseDir,
   options.filename || LOOP_ROOMS_CACHE_FILENAME);
 
-  this._cache = null;}
+  this._cache = null;
+}
 
-
-LoopRoomsCache.prototype = { 
+LoopRoomsCache.prototype = {
   /**
-   * Updates the local copy of the cache and saves it to disk.
-   *
-   * @param  {Object} contents An object to be saved in json format.
-   * @return {Promise} A promise that is resolved once the save is complete.
-   */
+                              * Updates the local copy of the cache and saves it to disk.
+                              *
+                              * @param  {Object} contents An object to be saved in json format.
+                              * @return {Promise} A promise that is resolved once the save is complete.
+                              */
   _setCache: function _setCache(contents) {var _this = this;
     this._cache = contents;
 
     return OS.File.makeDir(this.baseDir, { ignoreExisting: true }).then(function () {return (
-        CommonUtils.writeJSON(contents, _this.path));});}, 
-
+        CommonUtils.writeJSON(contents, _this.path));});
+  },
 
   /**
-   * Returns the local copy of the cache if there is one, otherwise it reads
-   * it from the disk.
-   *
-   * @return {Promise} A promise that is resolved once the read is complete.
-   */
+      * Returns the local copy of the cache if there is one, otherwise it reads
+      * it from the disk.
+      *
+      * @return {Promise} A promise that is resolved once the read is complete.
+      */
   _getCache: Task.async(function* () {
     if (this._cache) {
-      return this._cache;}
-
+      return this._cache;
+    }
 
     try {
-      return this._cache = yield CommonUtils.readJSON(this.path);} 
-    catch (error) {
+      return this._cache = yield CommonUtils.readJSON(this.path);
+    } catch (error) {
       if (!error.becauseNoSuchFile) {
-        MozLoopService.log.debug("Error reading the cache:", error);}
-
-      return this._cache = {};}}), 
-
-
+        MozLoopService.log.debug("Error reading the cache:", error);
+      }
+      return this._cache = {};
+    }
+  }),
 
   /**
-   * Function for testability purposes. Clears the cache.
-   *
-   * @return {Promise} A promise that is resolved once the clear is complete.
-   */
+       * Function for testability purposes. Clears the cache.
+       *
+       * @return {Promise} A promise that is resolved once the clear is complete.
+       */
   clear: function clear() {
     this._cache = null;
-    return OS.File.remove(this.path);}, 
-
+    return OS.File.remove(this.path);
+  },
 
   /**
-   * Gets a room key from the cache.
-   *
-   * @param {LOOP_SESSION_TYPE} sessionType  The session type for the room.
-   * @param {String}            roomToken    The token for the room.
-   * @return {Promise} A promise that is resolved when the data has been read
-   *                   with the value of the key, or null if it isn't present.
-   */
+      * Gets a room key from the cache.
+      *
+      * @param {LOOP_SESSION_TYPE} sessionType  The session type for the room.
+      * @param {String}            roomToken    The token for the room.
+      * @return {Promise} A promise that is resolved when the data has been read
+      *                   with the value of the key, or null if it isn't present.
+      */
   getKey: Task.async(function* (sessionType, roomToken) {
     if (sessionType != LOOP_SESSION_TYPE.FXA) {
-      return null;}
-
+      return null;
+    }
 
     var sessionData = (yield this._getCache())[sessionType];
 
     if (!sessionData || !sessionData[roomToken]) {
-      return null;}
-
-    return sessionData[roomToken].key;}), 
-
+      return null;
+    }
+    return sessionData[roomToken].key;
+  }),
 
   /**
-   * Stores a room key into the cache. Note, if the key has not changed,
-   * the store will not be re-written.
-   *
-   * @param {LOOP_SESSION_TYPE} sessionType  The session type for the room.
-   * @param {String}            roomToken    The token for the room.
-   * @param {String}            roomKey      The encryption key for the room.
-   * @return {Promise} A promise that is resolved when the data has been stored.
-   */
+       * Stores a room key into the cache. Note, if the key has not changed,
+       * the store will not be re-written.
+       *
+       * @param {LOOP_SESSION_TYPE} sessionType  The session type for the room.
+       * @param {String}            roomToken    The token for the room.
+       * @param {String}            roomKey      The encryption key for the room.
+       * @return {Promise} A promise that is resolved when the data has been stored.
+       */
   setKey: Task.async(function* (sessionType, roomToken, roomKey) {
     if (sessionType != LOOP_SESSION_TYPE.FXA) {
-      return Promise.resolve();}
-
+      return Promise.resolve();
+    }
 
     var cache = yield this._getCache();
 
     // Create these objects if they don't exist.
     // We aim to do this creation and setting of the room key in a
     // forwards-compatible way so that if new fields are added to rooms later
     // then we don't mess them up (if there's no keys).
     if (!cache[sessionType]) {
-      cache[sessionType] = {};}
-
+      cache[sessionType] = {};
+    }
 
     if (!cache[sessionType][roomToken]) {
-      cache[sessionType][roomToken] = {};}
-
+      cache[sessionType][roomToken] = {};
+    }
 
     // Only save it if there's no key, or it is different.
-    if (!cache[sessionType][roomToken].key || 
+    if (!cache[sessionType][roomToken].key ||
     cache[sessionType][roomToken].key != roomKey) {
       cache[sessionType][roomToken].key = roomKey;
-      return yield this._setCache(cache);}
+      return yield this._setCache(cache);
+    }
 
-
-    return Promise.resolve();}) };
+    return Promise.resolve();
+  }) };
--- a/browser/extensions/loop/chrome/content/modules/MozLoopAPI.jsm
+++ b/browser/extensions/loop/chrome/content/modules/MozLoopAPI.jsm
@@ -1,102 +1,102 @@
 /* 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";var _slicedToArray = function () {function sliceIterator(arr, i) {var _arr = [];var _n = true;var _d = false;var _e = undefined;try {for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {_arr.push(_s.value);if (i && _arr.length === i) break;}} catch (err) {_d = true;_e = err;} finally {try {if (!_n && _i["return"]) _i["return"]();} finally {if (_d) throw _e;}}return _arr;}return function (arr, i) {if (Array.isArray(arr)) {return arr;} else if (Symbol.iterator in Object(arr)) {return sliceIterator(arr, i);} else {throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}();var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {return typeof obj;} : function (obj) {return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;};function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}}var _Components = 
+"use strict";var _slicedToArray = function () {function sliceIterator(arr, i) {var _arr = [];var _n = true;var _d = false;var _e = undefined;try {for (var _i = arr[Symbol.iterator](), _s; !(_n = (_s = _i.next()).done); _n = true) {_arr.push(_s.value);if (i && _arr.length === i) break;}} catch (err) {_d = true;_e = err;} finally {try {if (!_n && _i["return"]) _i["return"]();} finally {if (_d) throw _e;}}return _arr;}return function (arr, i) {if (Array.isArray(arr)) {return arr;} else if (Symbol.iterator in Object(arr)) {return sliceIterator(arr, i);} else {throw new TypeError("Invalid attempt to destructure non-iterable instance");}};}();var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {return typeof obj;} : function (obj) {return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;};function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}}var _Components =
 
 Components;var Cc = _Components.classes;var Ci = _Components.interfaces;var Cu = _Components.utils;
 
 Cu.import("resource://services-common/utils.js");
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("chrome://loop/content/modules/MozLoopService.jsm");
 Cu.import("chrome://loop/content/modules/LoopRooms.jsm");
 Cu.importGlobalProperties(["Blob"]);
 
-XPCOMUtils.defineLazyModuleGetter(this, "NewTabURL", 
+XPCOMUtils.defineLazyModuleGetter(this, "NewTabURL",
 "resource:///modules/NewTabURL.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PageMetadata", 
+XPCOMUtils.defineLazyModuleGetter(this, "PageMetadata",
 "resource://gre/modules/PageMetadata.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", 
+XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
 "resource://gre/modules/PluralForm.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", 
+XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
 "resource://gre/modules/UpdateUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "UITour", 
+XPCOMUtils.defineLazyModuleGetter(this, "UITour",
 "resource:///modules/UITour.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Social", 
+XPCOMUtils.defineLazyModuleGetter(this, "Social",
 "resource:///modules/Social.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Promise", 
+XPCOMUtils.defineLazyModuleGetter(this, "Promise",
 "resource://gre/modules/Promise.jsm");
 XPCOMUtils.defineLazyGetter(this, "appInfo", function () {
   return Cc["@mozilla.org/xre/app-info;1"].
   getService(Ci.nsIXULAppInfo).
-  QueryInterface(Ci.nsIXULRuntime);});
-
-XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper", 
-"@mozilla.org/widget/clipboardhelper;1", 
+  QueryInterface(Ci.nsIXULRuntime);
+});
+XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
+"@mozilla.org/widget/clipboardhelper;1",
 "nsIClipboardHelper");
-XPCOMUtils.defineLazyServiceGetter(this, "extProtocolSvc", 
-"@mozilla.org/uriloader/external-protocol-service;1", 
+XPCOMUtils.defineLazyServiceGetter(this, "extProtocolSvc",
+"@mozilla.org/uriloader/external-protocol-service;1",
 "nsIExternalProtocolService");
 this.EXPORTED_SYMBOLS = ["LoopAPI"];
 
 var cloneableError = function cloneableError(source) {
   // Simple Object that can be cloned over.
   var error = {};
   if (typeof source == "string") {
-    source = new Error(source);}
-
+    source = new Error(source);
+  }
 
   var props = Object.getOwnPropertyNames(source);
   // nsIException properties are not enumerable, so we'll try to copy the most
   // common and useful ones.
   if (!props.length) {
-    props.push("message", "filename", "lineNumber", "columnNumber", "stack");}var _iteratorNormalCompletion = true;var _didIteratorError = false;var _iteratorError = undefined;try {
-
+    props.push("message", "filename", "lineNumber", "columnNumber", "stack");
+  }var _iteratorNormalCompletion = true;var _didIteratorError = false;var _iteratorError = undefined;try {
     for (var _iterator = props[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {var prop = _step.value;
       var value = source[prop];
       var type = typeof value === "undefined" ? "undefined" : _typeof(value);
 
       // Functions can't be cloned. Period.
       // For nsIException objects, the property may not be defined.
       if (type == "function" || type == "undefined") {
-        continue;}
-
+        continue;
+      }
       // Don't do anything to members that are already cloneable.
       if (/boolean|number|string/.test(type)) {
-        error[prop] = value;} else 
-      {
+        error[prop] = value;
+      } else {
         // Convert non-compatible types to a String.
-        error[prop] = "" + value;}}
-
-
+        error[prop] = "" + value;
+      }
+    }
 
     // Mark the object as an Error, otherwise it won't be discernable from other,
     // regular objects.
   } catch (err) {_didIteratorError = true;_iteratorError = err;} finally {try {if (!_iteratorNormalCompletion && _iterator.return) {_iterator.return();}} finally {if (_didIteratorError) {throw _iteratorError;}}}error.isError = true;
 
-  return error;};
-
+  return error;
+};
 
 var getObjectAPIFunctionName = function getObjectAPIFunctionName(action) {
   var funcName = action.split(":").pop();
-  return funcName.charAt(0).toLowerCase() + funcName.substr(1);};
-
+  return funcName.charAt(0).toLowerCase() + funcName.substr(1);
+};
 
 /**
- *  Checks that [browser.js]'s global variable `gMultiProcessBrowser` is active,
- *  instead of checking on first available browser element.
- *  :see bug 1257243 comment 5:
- */
+    *  Checks that [browser.js]'s global variable `gMultiProcessBrowser` is active,
+    *  instead of checking on first available browser element.
+    *  :see bug 1257243 comment 5:
+    */
 var isMultiProcessActive = function isMultiProcessActive() {
   var win = Services.wm.getMostRecentWindow("navigator:browser");
-  return !!win.gMultiProcessBrowser;};
-
+  return !!win.gMultiProcessBrowser;
+};
 
 var gAppVersionInfo = null;
 var gBrowserSharingListeners = new Set();
 var gBrowserSharingWindows = new Set();
 var gPageListeners = null;
 var gOriginalPageListeners = null;
 var gStringBundle = null;
 var gStubbedMessageHandlers = null;
@@ -104,1270 +104,1280 @@ var kBatchMessage = "Batch";
 var kMaxLoopCount = 10;
 var kMessageName = "Loop:Message";
 var kPushMessageName = "Loop:Message:Push";
 var kPushSubscription = "pushSubscription";
 var kRoomsPushPrefix = "Rooms:";
 var kMauPrefMap = new Map(
 Object.getOwnPropertyNames(LOOP_MAU_TYPE).map(function (name) {
   var parts = name.toLowerCase().split("_");
-  return [LOOP_MAU_TYPE[name], parts[0] + parts[1].charAt(0).toUpperCase() + parts[1].substr(1)];}));
-
+  return [LOOP_MAU_TYPE[name], parts[0] + parts[1].charAt(0).toUpperCase() + parts[1].substr(1)];
+}));
 
 
 /**
- * WARNING: Every function in kMessageHandlers must call the reply() function,
- * as otherwise the content requesters can be left hanging.
- *
- * Ideally, we should rewrite them to handle failure/long times better, at which
- * point this could be relaxed slightly.
- */
-var kMessageHandlers = { 
+      * WARNING: Every function in kMessageHandlers must call the reply() function,
+      * as otherwise the content requesters can be left hanging.
+      *
+      * Ideally, we should rewrite them to handle failure/long times better, at which
+      * point this could be relaxed slightly.
+      */
+var kMessageHandlers = {
   /**
-   * Start browser sharing, which basically means to start listening for tab
-   * switches and passing the new window ID to the sender whenever that happens.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} roomToken The room ID to start browser sharing and listeners.
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+                          * Start browser sharing, which basically means to start listening for tab
+                          * switches and passing the new window ID to the sender whenever that happens.
+                          *
+                          * @param {Object}   message Message meant for the handler function, containing
+                          *                           the following parameters in its `data` property:
+                          *                           [
+                          *                             {String} roomToken The room ID to start browser sharing and listeners.
+                          *                           ]
+                          * @param {Function} reply   Callback function, invoked with the result of this
+                          *                           message handler. The result will be sent back to
+                          *                           the senders' channel.
+                          */
   AddBrowserSharingListener: function AddBrowserSharingListener(message, reply) {
     var win = Services.wm.getMostRecentWindow("navigator:browser");
     var browser = win && win.gBrowser.selectedBrowser;
     if (!win || !browser) {
       // This may happen when an undocked conversation window is the only
       // window left.
       var err = new Error("No tabs available to share.");
       MozLoopService.log.error(err);
       reply(cloneableError(err));
-      return;}
-
+      return;
+    }
 
     var autoStart = MozLoopService.getLoopPref("remote.autostart");
     if (!autoStart && browser.getAttribute("remote") == "true") {
       // Tab sharing might not be supported yet for e10s-enabled browsers.
       var _err = new Error("Tab sharing is not supported for e10s-enabled browsers");
       MozLoopService.log.error(_err);
       reply(cloneableError(_err));
-      return;}
-
+      return;
+    }
 
     // get room token from message
     var _message$data = _slicedToArray(message.data, 1);var windowId = _message$data[0];
     // For rooms, the windowId === roomToken. If we change the type of place we're
     // sharing from in the future, we may need to change this.
     win.LoopUI.startBrowserSharing(windowId);
 
     // Point new tab to load about:home to avoid accidentally sharing top sites.
     NewTabURL.override("about:home");
 
     gBrowserSharingWindows.add(Cu.getWeakReference(win));
     gBrowserSharingListeners.add(windowId);
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Creates a layout for the remote cursor on the browser chrome,
-   * and positions it on the received coordinates.
-   *
-   * @param {Object}  message Message meant for the handler function, contains
-   *                          the following parameters in its 'data' property:
-   *                          {
-   *                            ratioX: cursor's X position (between 0-1)
-   *                            ratioY: cursor's Y position (between 0-1)
-   *                          }
-   *
-   * @param {Function} reply  Callback function, invoked with the result of the
-   *                          message handler. The result will be sent back to
-   *                          the senders' channel.
-   */
+      * Creates a layout for the remote cursor on the browser chrome,
+      * and positions it on the received coordinates.
+      *
+      * @param {Object}  message Message meant for the handler function, contains
+      *                          the following parameters in its 'data' property:
+      *                          {
+      *                            ratioX: cursor's X position (between 0-1)
+      *                            ratioY: cursor's Y position (between 0-1)
+      *                          }
+      *
+      * @param {Function} reply  Callback function, invoked with the result of the
+      *                          message handler. The result will be sent back to
+      *                          the senders' channel.
+      */
   AddRemoteCursorOverlay: function AddRemoteCursorOverlay(message, reply) {
     var win = Services.wm.getMostRecentWindow("navigator:browser");
     if (win) {
-      win.LoopUI.addRemoteCursor(message.data[0]);}
-
+      win.LoopUI.addRemoteCursor(message.data[0]);
+    }
 
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Shows the click event on the remote cursor.
-   *
-   * @param {Object}  message Message meant for the handler function, contains
-   *                          a boolean for the click event in its 'data' prop.
-   *
-   * @param {Function} reply  Callback function, invoked with the result of the
-   *                          message handler. The result will be sent back to
-   *                          the senders' channel.
-   */
+      * Shows the click event on the remote cursor.
+      *
+      * @param {Object}  message Message meant for the handler function, contains
+      *                          a boolean for the click event in its 'data' prop.
+      *
+      * @param {Function} reply  Callback function, invoked with the result of the
+      *                          message handler. The result will be sent back to
+      *                          the senders' channel.
+      */
   ClickRemoteCursor: function ClickRemoteCursor(message, reply) {
     var win = Services.wm.getMostRecentWindow("navigator:browser");
     if (win) {
-      win.LoopUI.clickRemoteCursor(message.data[0]);}
-
+      win.LoopUI.clickRemoteCursor(message.data[0]);
+    }
 
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Associates a session-id and a call-id with a window for debugging.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} windowId  The window id.
-   *                             {String} sessionId OT session id.
-   *                             {String} callId    The callId on the server.
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Associates a session-id and a call-id with a window for debugging.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} windowId  The window id.
+      *                             {String} sessionId OT session id.
+      *                             {String} callId    The callId on the server.
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   AddConversationContext: function AddConversationContext(message, reply) {var _message$data2 = _slicedToArray(
     message.data, 3);var windowId = _message$data2[0];var sessionId = _message$data2[1];var callid = _message$data2[2];
-    MozLoopService.addConversationContext(windowId, { 
-      sessionId: sessionId, 
+    MozLoopService.addConversationContext(windowId, {
+      sessionId: sessionId,
       callId: callid });
 
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Composes an email via the external protocol service.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} subject   Subject of the email to send
-   *                             {String} body      Body message of the email to send
-   *                             {String} recipient Recipient email address (optional)
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Composes an email via the external protocol service.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} subject   Subject of the email to send
+      *                             {String} body      Body message of the email to send
+      *                             {String} recipient Recipient email address (optional)
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   ComposeEmail: function ComposeEmail(message, reply) {var _message$data3 = _slicedToArray(
     message.data, 3);var subject = _message$data3[0];var body = _message$data3[1];var recipient = _message$data3[2];
     recipient = recipient || "";
-    var mailtoURL = "mailto:" + encodeURIComponent(recipient) + 
-    "?subject=" + encodeURIComponent(subject) + 
+    var mailtoURL = "mailto:" + encodeURIComponent(recipient) +
+    "?subject=" + encodeURIComponent(subject) +
     "&body=" + encodeURIComponent(body);
     extProtocolSvc.loadURI(CommonUtils.makeURI(mailtoURL));
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Show a confirmation dialog with the standard - localized - 'Yes'/ 'No'
-   * buttons or custom labels.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {Object} options Options for the confirm dialog:
-   *                               - {String} message        Message body for the dialog
-   *                               - {String} [okButton]     Label for the OK button
-   *                               - {String} [cancelButton] Label for the Cancel button
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Show a confirmation dialog with the standard - localized - 'Yes'/ 'No'
+      * buttons or custom labels.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {Object} options Options for the confirm dialog:
+      *                               - {String} message        Message body for the dialog
+      *                               - {String} [okButton]     Label for the OK button
+      *                               - {String} [cancelButton] Label for the Cancel button
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   Confirm: function Confirm(message, reply) {
     var options = message.data[0];
     var buttonFlags = void 0;
     if (options.okButton && options.cancelButton) {
-      buttonFlags = 
-      Ci.nsIPrompt.BUTTON_POS_0 * Ci.nsIPrompt.BUTTON_TITLE_IS_STRING + 
-      Ci.nsIPrompt.BUTTON_POS_1 * Ci.nsIPrompt.BUTTON_TITLE_IS_STRING;} else 
-    if (!options.okButton && !options.cancelButton) {
-      buttonFlags = Services.prompt.STD_YES_NO_BUTTONS;} else 
-    {
+      buttonFlags =
+      Ci.nsIPrompt.BUTTON_POS_0 * Ci.nsIPrompt.BUTTON_TITLE_IS_STRING +
+      Ci.nsIPrompt.BUTTON_POS_1 * Ci.nsIPrompt.BUTTON_TITLE_IS_STRING;
+    } else if (!options.okButton && !options.cancelButton) {
+      buttonFlags = Services.prompt.STD_YES_NO_BUTTONS;
+    } else {
       reply(cloneableError("confirm: missing button options"));
-      return;}
-
+      return;
+    }
 
     try {
-      var chosenButton = Services.prompt.confirmEx(null, "", 
-      options.message, buttonFlags, options.okButton, options.cancelButton, 
+      var chosenButton = Services.prompt.confirmEx(null, "",
+      options.message, buttonFlags, options.okButton, options.cancelButton,
       null, null, {});
 
-      reply(chosenButton == 0);} 
-    catch (ex) {
-      reply(ex);}}, 
-
-
+      reply(chosenButton == 0);
+    } catch (ex) {
+      reply(ex);
+    }
+  },
 
   /**
-   * Copies passed string onto the system clipboard.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} str The string to copy
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Copies passed string onto the system clipboard.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} str The string to copy
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   CopyString: function CopyString(message, reply) {
     var str = message.data[0];
     clipboardHelper.copyString(str);
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Returns a new GUID (UUID) in curly braces format.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Returns a new GUID (UUID) in curly braces format.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   GenerateUUID: function GenerateUUID(message, reply) {
-    reply(MozLoopService.generateUUID());}, 
-
+    reply(MozLoopService.generateUUID());
+  },
 
   /**
-   * Fetch the JSON blob of localized strings from the loop.properties bundle.
-   * @see MozLoopService#getStrings
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Fetch the JSON blob of localized strings from the loop.properties bundle.
+      * @see MozLoopService#getStrings
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   GetAllStrings: function GetAllStrings(message, reply) {
     if (gStringBundle) {
       reply(gStringBundle);
-      return;}
-
+      return;
+    }
 
     // Get the map of strings.
     var strings = MozLoopService.getStrings();
     // Convert it to an object.
     gStringBundle = {};var _iteratorNormalCompletion2 = true;var _didIteratorError2 = false;var _iteratorError2 = undefined;try {
       for (var _iterator2 = strings.entries()[Symbol.iterator](), _step2; !(_iteratorNormalCompletion2 = (_step2 = _iterator2.next()).done); _iteratorNormalCompletion2 = true) {var _ref = _step2.value;var _ref2 = _slicedToArray(_ref, 2);var key = _ref2[0];var value = _ref2[1];
-        gStringBundle[key] = value;}} catch (err) {_didIteratorError2 = true;_iteratorError2 = err;} finally {try {if (!_iteratorNormalCompletion2 && _iterator2.return) {_iterator2.return();}} finally {if (_didIteratorError2) {throw _iteratorError2;}}}
-
-    reply(gStringBundle);}, 
-
+        gStringBundle[key] = value;
+      }} catch (err) {_didIteratorError2 = true;_iteratorError2 = err;} finally {try {if (!_iteratorNormalCompletion2 && _iterator2.return) {_iterator2.return();}} finally {if (_didIteratorError2) {throw _iteratorError2;}}}
+    reply(gStringBundle);
+  },
 
   /**
-   * Fetch all constants that are used both on the client and the chrome-side.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Fetch all constants that are used both on the client and the chrome-side.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   GetAllConstants: function GetAllConstants(message, reply) {
-    reply({ 
-      COPY_PANEL: COPY_PANEL, 
-      LOOP_SESSION_TYPE: LOOP_SESSION_TYPE, 
-      LOOP_MAU_TYPE: LOOP_MAU_TYPE, 
-      ROOM_CREATE: ROOM_CREATE, 
-      SHARING_ROOM_URL: SHARING_ROOM_URL });}, 
+    reply({
+      COPY_PANEL: COPY_PANEL,
+      LOOP_SESSION_TYPE: LOOP_SESSION_TYPE,
+      LOOP_MAU_TYPE: LOOP_MAU_TYPE,
+      ROOM_CREATE: ROOM_CREATE,
+      SHARING_ROOM_URL: SHARING_ROOM_URL });
 
-
+  },
 
   /**
-   * Returns the app version information for use during feedback.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   * @return {Object} An object containing:
-   *   - channel: The update channel the application is on
-   *   - version: The application version
-   *   - OS: The operating system the application is running on
-   */
+      * Returns the app version information for use during feedback.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      * @return {Object} An object containing:
+      *   - channel: The update channel the application is on
+      *   - version: The application version
+      *   - OS: The operating system the application is running on
+      */
   GetAppVersionInfo: function GetAppVersionInfo(message, reply) {
     if (!gAppVersionInfo) {
       // If the lazy getter explodes, we're probably loaded in xpcshell,
       // which doesn't have what we need, so log an error.
       try {
-        gAppVersionInfo = { 
-          channel: UpdateUtils.UpdateChannel, 
-          version: appInfo.version, 
-          OS: appInfo.OS };} 
+        gAppVersionInfo = {
+          channel: UpdateUtils.UpdateChannel,
+          version: appInfo.version,
+          OS: appInfo.OS };
 
-      catch (ex) {
+      } catch (ex) {
         // Do nothing
-      }}
-
-    reply(gAppVersionInfo);}, 
-
+      }
+    }
+    reply(gAppVersionInfo);
+  },
 
   /**
-   * Fetch the contents of a specific audio file and return it as a Blob object.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} name Name of the sound to fetch
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Fetch the contents of a specific audio file and return it as a Blob object.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} name Name of the sound to fetch
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   GetAudioBlob: function GetAudioBlob(message, reply) {
     var name = message.data[0];
     var request = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"].
     createInstance(Ci.nsIXMLHttpRequest);
     var url = "chrome://loop/content/shared/sounds/" + name + ".ogg";
 
     request.open("GET", url, true);
     request.responseType = "arraybuffer";
     request.onload = function () {
       if (request.status < 200 || request.status >= 300) {
         reply(cloneableError(request.status + " " + request.statusText));
-        return;}
-
+        return;
+      }
 
       var blob = new Blob([request.response], { type: "audio/ogg" });
-      reply(blob);};
-
+      reply(blob);
+    };
 
-    request.send();}, 
-
+    request.send();
+  },
 
   /**
-   * Returns the window data for a specific conversation window id.
-   *
-   * This data will be relevant to the type of window, e.g. rooms or calls.
-   * See LoopRooms for more information.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} conversationWindowId
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   * @returns {Object} The window data or null if error.
-   */
+      * Returns the window data for a specific conversation window id.
+      *
+      * This data will be relevant to the type of window, e.g. rooms or calls.
+      * See LoopRooms for more information.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} conversationWindowId
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      * @returns {Object} The window data or null if error.
+      */
   GetConversationWindowData: function GetConversationWindowData(message, reply) {
-    reply(MozLoopService.getConversationWindowData(message.data[0]));}, 
-
+    reply(MozLoopService.getConversationWindowData(message.data[0]));
+  },
 
   /**
-   * Gets the "do not disturb" mode activation flag.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Gets the "do not disturb" mode activation flag.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   GetDoNotDisturb: function GetDoNotDisturb(message, reply) {
-    reply(MozLoopService.doNotDisturb);}, 
-
+    reply(MozLoopService.doNotDisturb);
+  },
 
   /**
-   * Retrieve the list of errors that are currently pending on the MozLoopService
-   * class.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Retrieve the list of errors that are currently pending on the MozLoopService
+      * class.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   GetErrors: function GetErrors(message, reply) {
     var errors = {};var _iteratorNormalCompletion3 = true;var _didIteratorError3 = false;var _iteratorError3 = undefined;try {
       for (var _iterator3 = MozLoopService.errors[Symbol.iterator](), _step3; !(_iteratorNormalCompletion3 = (_step3 = _iterator3.next()).done); _iteratorNormalCompletion3 = true) {var _ref3 = _step3.value;var _ref4 = _slicedToArray(_ref3, 2);var type = _ref4[0];var error = _ref4[1];
         // if error.error is an nsIException, just delete it since it's hard
         // to clone across the boundary.
         if (error.error instanceof Ci.nsIException) {
-          MozLoopService.log.debug("Warning: Some errors were omitted from MozLoopAPI.errors " + 
-          "due to issues copying nsIException across boundaries.", 
+          MozLoopService.log.debug("Warning: Some errors were omitted from MozLoopAPI.errors " +
+          "due to issues copying nsIException across boundaries.",
           error.error);
-          delete error.error;}
+          delete error.error;
+        }
+
+        errors[type] = cloneableError(error);
+      }} catch (err) {_didIteratorError3 = true;_iteratorError3 = err;} finally {try {if (!_iteratorNormalCompletion3 && _iterator3.return) {_iterator3.return();}} finally {if (_didIteratorError3) {throw _iteratorError3;}}}
+    return reply(errors);
+  },
 
-
-        errors[type] = cloneableError(error);}} catch (err) {_didIteratorError3 = true;_iteratorError3 = err;} finally {try {if (!_iteratorNormalCompletion3 && _iterator3.return) {_iterator3.return();}} finally {if (_didIteratorError3) {throw _iteratorError3;}}}
-
-    return reply(errors);}, 
-
+  /**
+      * Returns true if this profile has an encryption key.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      * @return {Boolean} True if the profile has an encryption key.
+      */
+  GetHasEncryptionKey: function GetHasEncryptionKey(message, reply) {
+    reply(MozLoopService.hasEncryptionKey);
+  },
 
   /**
-   * Returns true if this profile has an encryption key.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   * @return {Boolean} True if the profile has an encryption key.
-   */
-  GetHasEncryptionKey: function GetHasEncryptionKey(message, reply) {
-    reply(MozLoopService.hasEncryptionKey);}, 
-
+      * Returns the current locale of the browser.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      * @returns {String} The locale string
+      */
+  GetLocale: function GetLocale(message, reply) {
+    reply(MozLoopService.locale);
+  },
 
   /**
-   * Returns the current locale of the browser.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   * @returns {String} The locale string
-   */
-  GetLocale: function GetLocale(message, reply) {
-    reply(MozLoopService.locale);}, 
-
+      * Returns the version number for the addon.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      * @returns {String} Addon Version string.
+      */
+  GetAddonVersion: function GetAddonVersion(message, reply) {
+    reply(MozLoopService.addonVersion);
+  },
 
   /**
-   * Returns the version number for the addon.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   * @returns {String} Addon Version string.
-   */
-  GetAddonVersion: function GetAddonVersion(message, reply) {
-    reply(MozLoopService.addonVersion);}, 
-
+      * Return any preference under "loop.".
+      * Any errors thrown by the Mozilla pref API are logged to the console
+      * and cause null to be returned. This includes the case of the preference
+      * not being found.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} prefName The name of the pref without
+      *                                               the preceding "loop."
+      *                             {Enum}   prefType Type of preference, defined
+      *                                               at Ci.nsIPrefBranch. Optional.
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      * @return {*} on success, null on error
+      */
+  GetLoopPref: function GetLoopPref(message, reply) {var _message$data4 = _slicedToArray(
+    message.data, 2);var prefName = _message$data4[0];var prefType = _message$data4[1];
+    reply(MozLoopService.getLoopPref(prefName, prefType));
+  },
 
   /**
-   * Return any preference under "loop.".
-   * Any errors thrown by the Mozilla pref API are logged to the console
-   * and cause null to be returned. This includes the case of the preference
-   * not being found.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} prefName The name of the pref without
-   *                                               the preceding "loop."
-   *                             {Enum}   prefType Type of preference, defined
-   *                                               at Ci.nsIPrefBranch. Optional.
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   * @return {*} on success, null on error
-   */
-  GetLoopPref: function GetLoopPref(message, reply) {var _message$data4 = _slicedToArray(
-    message.data, 2);var prefName = _message$data4[0];var prefType = _message$data4[1];
-    reply(MozLoopService.getLoopPref(prefName, prefType));}, 
-
+      * Returns any URL preference under "loop.". Used to retrieve properly
+      * formatted URL strings which include platform and version number.
+      */
+  GetLoopUrl: function GetLoopUrl(message, reply) {var _message$data5 = _slicedToArray(
+    message.data, 2);var prefName = _message$data5[0];var prefType = _message$data5[1];
+    reply(MozLoopService.getLoopUrl(prefName, prefType));
+  },
 
   /**
-   * Retrieve the plural rule number of the active locale.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Retrieve the plural rule number of the active locale.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   GetPluralRule: function GetPluralRule(message, reply) {
-    reply(PluralForm.ruleNum);}, 
-
+    reply(PluralForm.ruleNum);
+  },
 
   /**
-   * Gets the metadata related to the currently selected tab in
-   * the most recent window.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Gets the metadata related to the currently selected tab in
+      * the most recent window.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   GetSelectedTabMetadata: function GetSelectedTabMetadata(message, reply) {
     var win = Services.wm.getMostRecentWindow("navigator:browser");
     var browser = win && win.gBrowser.selectedBrowser;
     if (!win || !browser) {
       MozLoopService.log.error("Error occurred whilst fetching page metadata");
       reply();
-      return;}
-
+      return;
+    }
 
     // non-remote pages have no metadata
     if (!browser.getAttribute("remote") === "true") {
-      reply(null);}
+      reply(null);
+    }
 
-
-    win.messageManager.addMessageListener("PageMetadata:PageDataResult", 
+    win.messageManager.addMessageListener("PageMetadata:PageDataResult",
     function onPageDataResult(msg) {
 
-      win.messageManager.removeMessageListener("PageMetadata:PageDataResult", 
+      win.messageManager.removeMessageListener("PageMetadata:PageDataResult",
       onPageDataResult);
       var pageData = msg.json;
       win.LoopUI.getFavicon(function (err, favicon) {
         if (err && err !== "favicon not found for uri") {
           MozLoopService.log.error("Error occurred whilst fetching favicon", err);
           // We don't return here intentionally to make sure the callback is
           // invoked at all times. We just report the error here.
         }
         pageData.favicon = favicon || null;
 
-        reply(pageData);});});
-
-
-    win.gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetPageData");}, 
-
+        reply(pageData);
+      });
+    });
+    win.gBrowser.selectedBrowser.messageManager.sendAsyncMessage("PageMetadata:GetPageData");
+  },
 
   /**
-   * Gets an object with data that represents the currently
-   * authenticated user's identity.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   * @return null if user not logged in; profile object otherwise
-   */
+      * Gets an object with data that represents the currently
+      * authenticated user's identity.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      * @return null if user not logged in; profile object otherwise
+      */
   GetUserProfile: function GetUserProfile(message, reply) {
     if (!MozLoopService.userProfile) {
       reply(null);
-      return;}
-
+      return;
+    }
 
-    reply({ 
-      email: MozLoopService.userProfile.email, 
-      uid: MozLoopService.userProfile.uid });}, 
+    reply({
+      email: MozLoopService.userProfile.email,
+      uid: MozLoopService.userProfile.uid });
 
-
+  },
 
   /**
-   * Hangup and close all chat windows that are open.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Hangup and close all chat windows that are open.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   HangupAllChatWindows: function HangupAllChatWindows(message, reply) {
     MozLoopService.hangupAllChatWindows();
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Hangup a specific chay window or room, by leaving a room, resetting the
-   * screensharing state and removing any active browser switch listeners.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} roomToken The token of the room to leave
-   *                             {Number} windowId  The window ID of the chat window
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
-  HangupNow: function HangupNow(message, reply) {var _message$data5 = _slicedToArray(
-    message.data, 3);var roomToken = _message$data5[0];var sessionToken = _message$data5[1];var windowId = _message$data5[2];
+      * Hangup a specific chay window or room, by leaving a room, resetting the
+      * screensharing state and removing any active browser switch listeners.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} roomToken The token of the room to leave
+      *                             {Number} windowId  The window ID of the chat window
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
+  HangupNow: function HangupNow(message, reply) {var _message$data6 = _slicedToArray(
+    message.data, 3);var roomToken = _message$data6[0];var sessionToken = _message$data6[1];var windowId = _message$data6[2];
     if (!windowId) {
-      windowId = sessionToken;}
-
+      windowId = sessionToken;
+    }
 
     LoopRooms.logDomains(roomToken);
     LoopRooms.leave(roomToken);
     MozLoopService.setScreenShareState(windowId, false);
-    LoopAPI.sendMessageToHandler({ 
-      name: "RemoveBrowserSharingListener", 
+    LoopAPI.sendMessageToHandler({
+      name: "RemoveBrowserSharingListener",
       data: [windowId] });
 
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Check if the current browser has e10s enabled or not
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           []
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Check if the current browser has e10s enabled or not
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           []
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   IsMultiProcessActive: function IsMultiProcessActive(message, reply) {
-    reply(isMultiProcessActive());}, 
-
+    reply(isMultiProcessActive());
+  },
 
   /**
-   *  Checks that the current tab can be shared.
-   *  Non-shareable tabs are the non-remote ones when e10s is enabled.
-   *
-   *  @param {Object}   message Message meant for the handler function,
-   *                            with no data attached.
-   *  @param {Function} reply   Callback function, invoked with the result of
-   *                            the check. The result will be sent back to
-   *                            the senders' channel.
-   */
+      *  Checks that the current tab can be shared.
+      *  Non-shareable tabs are the non-remote ones when e10s is enabled.
+      *
+      *  @param {Object}   message Message meant for the handler function,
+      *                            with no data attached.
+      *  @param {Function} reply   Callback function, invoked with the result of
+      *                            the check. The result will be sent back to
+      *                            the senders' channel.
+      */
   IsTabShareable: function IsTabShareable(message, reply) {
     var win = Services.wm.getMostRecentWindow("navigator:browser");
     var browser = win && win.gBrowser.selectedBrowser;
     if (!win || !browser) {
       reply(false);
-      return;}
-
+      return;
+    }
 
     var e10sActive = isMultiProcessActive();
     var tabRemote = browser.getAttribute("remote") === "true";
 
-    reply(!e10sActive || e10sActive && tabRemote);}, 
-
+    reply(!e10sActive || e10sActive && tabRemote);
+  },
 
   /**
-   * Start the FxA login flow using the OAuth client and params from the Loop
-   * server.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {Boolean} forceReAuth Set to true to force FxA
-   *                                                   into a re-auth even if the
-   *                                                   user is already logged in.
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   * @return {Promise} Returns a promise that is resolved on successful
-   *                   completion, or rejected otherwise.
-   */
+      * Start the FxA login flow using the OAuth client and params from the Loop
+      * server.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {Boolean} forceReAuth Set to true to force FxA
+      *                                                   into a re-auth even if the
+      *                                                   user is already logged in.
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      * @return {Promise} Returns a promise that is resolved on successful
+      *                   completion, or rejected otherwise.
+      */
   LoginToFxA: function LoginToFxA(message, reply) {
     var forceReAuth = message.data[0];
     MozLoopService.logInToFxA(forceReAuth);
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Logout completely from FxA.
-   * @see MozLoopService#logOutFromFxA
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Logout completely from FxA.
+      * @see MozLoopService#logOutFromFxA
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   LogoutFromFxA: function LogoutFromFxA(message, reply) {
     MozLoopService.logOutFromFxA();
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Notifies the UITour module that an event occurred that it might be
-   * interested in.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} subject  Subject of the notification
-   *                             {mixed}  [params] Optional parameters, providing
-   *                                               more details to the notification
-   *                                               subject
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
-  NotifyUITour: function NotifyUITour(message, reply) {var _message$data6 = _slicedToArray(
-    message.data, 2);var subject = _message$data6[0];var params = _message$data6[1];
+      * Notifies the UITour module that an event occurred that it might be
+      * interested in.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} subject  Subject of the notification
+      *                             {mixed}  [params] Optional parameters, providing
+      *                                               more details to the notification
+      *                                               subject
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
+  NotifyUITour: function NotifyUITour(message, reply) {var _message$data7 = _slicedToArray(
+    message.data, 2);var subject = _message$data7[0];var params = _message$data7[1];
     UITour.notify(subject, params);
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Opens the Getting Started tour in the browser.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           []
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Opens the Getting Started tour in the browser.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           []
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   OpenGettingStartedTour: function OpenGettingStartedTour(message, reply) {
     MozLoopService.openGettingStartedTour();
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Retrieves the Getting Started tour url.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [aSrc, aAdditionalParams]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Retrieves the Getting Started tour url.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [aSrc, aAdditionalParams]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   GettingStartedURL: function GettingStartedURL(message, reply) {
     var aSrc = message.data[0] || null;
     var aAdditionalParams = message.data[1] || {};
-    reply(MozLoopService.getTourURL(aSrc, aAdditionalParams).href);}, 
-
+    reply(MozLoopService.getTourURL(aSrc, aAdditionalParams).href);
+  },
 
   /**
-   * Open the FxA profile/ settings page.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Open the FxA profile/ settings page.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   OpenFxASettings: function OpenFxASettings(message, reply) {
     MozLoopService.openFxASettings();
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Opens a non e10s window
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [url]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Opens a non e10s window
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [url]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   OpenNonE10sWindow: function OpenNonE10sWindow(message, reply) {
     var win = Services.wm.getMostRecentWindow("navigator:browser");
     var url = message.data[0] ? message.data[0] : "about:home";
     win.openDialog("chrome://browser/content/", "_blank", "chrome,all,dialog=no,non-remote", url);
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Opens a URL in a new tab in the browser.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} url The new url to open
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Opens a URL in a new tab in the browser.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} url The new url to open
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   OpenURL: function OpenURL(message, reply) {
     var url = message.data[0];
     MozLoopService.openURL(url);
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Removes a listener that was previously added.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {Number} windowId The window ID of the chat
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Removes a listener that was previously added.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {Number} windowId The window ID of the chat
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   RemoveBrowserSharingListener: function RemoveBrowserSharingListener(message, reply) {
     if (!gBrowserSharingListeners.size) {
       reply();
-      return;}var _message$data7 = _slicedToArray(
+      return;
+    }var _message$data8 = _slicedToArray(
 
-
-    message.data, 1);var windowId = _message$data7[0];
+    message.data, 1);var windowId = _message$data8[0];
     gBrowserSharingListeners.delete(windowId);
     if (gBrowserSharingListeners.size > 0) {
       // There are still clients listening in, so keep on listening...
       reply();
-      return;}var _iteratorNormalCompletion4 = true;var _didIteratorError4 = false;var _iteratorError4 = undefined;try {
-
+      return;
+    }var _iteratorNormalCompletion4 = true;var _didIteratorError4 = false;var _iteratorError4 = undefined;try {
 
       for (var _iterator4 = gBrowserSharingWindows[Symbol.iterator](), _step4; !(_iteratorNormalCompletion4 = (_step4 = _iterator4.next()).done); _iteratorNormalCompletion4 = true) {var win = _step4.value;
         win = win.get();
         if (!win) {
-          continue;}
-
-        win.LoopUI.stopBrowserSharing();}} catch (err) {_didIteratorError4 = true;_iteratorError4 = err;} finally {try {if (!_iteratorNormalCompletion4 && _iterator4.return) {_iterator4.return();}} finally {if (_didIteratorError4) {throw _iteratorError4;}}}
-
+          continue;
+        }
+        win.LoopUI.stopBrowserSharing();
+      }} catch (err) {_didIteratorError4 = true;_iteratorError4 = err;} finally {try {if (!_iteratorNormalCompletion4 && _iterator4.return) {_iterator4.return();}} finally {if (_didIteratorError4) {throw _iteratorError4;}}}
 
     NewTabURL.reset();
 
     gBrowserSharingWindows.clear();
-    reply();}, 
-
+    reply();
+  },
 
   "Rooms:*": function Rooms(action, message, reply) {
-    LoopAPIInternal.handleObjectAPIMessage(LoopRooms, kRoomsPushPrefix, 
-    action, message, reply);}, 
-
+    LoopAPIInternal.handleObjectAPIMessage(LoopRooms, kRoomsPushPrefix,
+    action, message, reply);
+  },
 
   /**
-   * Sets the "do not disturb" mode activation flag.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [ ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Sets the "do not disturb" mode activation flag.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [ ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   SetDoNotDisturb: function SetDoNotDisturb(message, reply) {
     MozLoopService.doNotDisturb = message.data[0];
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Set any preference under "loop."
-   * Any errors thrown by the Mozilla pref API are logged to the console
-   * and cause false to be returned.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} prefName The name of the pref without
-   *                                               the preceding "loop."
-   *                             {*}      value    The value to set.
-   *                             {Enum}   prefType Type of preference, defined at
-   *                                               Ci.nsIPrefBranch. Optional.
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
-  SetLoopPref: function SetLoopPref(message, reply) {var _message$data8 = _slicedToArray(
-    message.data, 3);var prefName = _message$data8[0];var value = _message$data8[1];var prefType = _message$data8[2];
+      * Set any preference under "loop."
+      * Any errors thrown by the Mozilla pref API are logged to the console
+      * and cause false to be returned.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} prefName The name of the pref without
+      *                                               the preceding "loop."
+      *                             {*}      value    The value to set.
+      *                             {Enum}   prefType Type of preference, defined at
+      *                                               Ci.nsIPrefBranch. Optional.
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
+  SetLoopPref: function SetLoopPref(message, reply) {var _message$data9 = _slicedToArray(
+    message.data, 3);var prefName = _message$data9[0];var value = _message$data9[1];var prefType = _message$data9[2];
     MozLoopService.setLoopPref(prefName, value, prefType);
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Called when a closing room has just been created, so user can change
-   * the name of the room to be stored.
-   *
-   * @param {Object}   message Message meant for the handler function, shouldn't
-                               contain any data.
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * Called when a closing room has just been created, so user can change
+      * the name of the room to be stored.
+      *
+      * @param {Object}   message Message meant for the handler function, shouldn't
+                                  contain any data.
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   SetNameNewRoom: function SetNameNewRoom(message, reply) {
     var win = Services.wm.getMostRecentWindow("navigator:browser");
     win && win.LoopUI.renameRoom();
 
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Used to record the screen sharing state for a window so that it can
-   * be reflected on the toolbar button.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} windowId The id of the conversation window
-   *                                               the state is being changed for.
-   *                             {Boolean} active  Whether or not screen sharing
-   *                                               is now active.
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
-  SetScreenShareState: function SetScreenShareState(message, reply) {var _message$data9 = _slicedToArray(
-    message.data, 2);var windowId = _message$data9[0];var active = _message$data9[1];
+      * Used to record the screen sharing state for a window so that it can
+      * be reflected on the toolbar button.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} windowId The id of the conversation window
+      *                                               the state is being changed for.
+      *                             {Boolean} active  Whether or not screen sharing
+      *                                               is now active.
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
+  SetScreenShareState: function SetScreenShareState(message, reply) {var _message$data10 = _slicedToArray(
+    message.data, 2);var windowId = _message$data10[0];var active = _message$data10[1];
     MozLoopService.setScreenShareState(windowId, active);
-    reply();}, 
-
+    reply();
+  },
 
   /**
-   * Adds a value to a telemetry histogram.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following parameters in its `data` property:
-   *                           [
-   *                             {String} histogramId Name of the telemetry histogram
-   *                                                  to update.
-   *                             {String} value       Label of bucket to increment
-   *                                                   in the histogram.
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
-  TelemetryAddValue: function TelemetryAddValue(message, reply) {var _message$data10 = _slicedToArray(
-    message.data, 2);var histogramId = _message$data10[0];var value = _message$data10[1];
+      * Adds a value to a telemetry histogram.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following parameters in its `data` property:
+      *                           [
+      *                             {String} histogramId Name of the telemetry histogram
+      *                                                  to update.
+      *                             {String} value       Label of bucket to increment
+      *                                                   in the histogram.
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
+  TelemetryAddValue: function TelemetryAddValue(message, reply) {var _message$data11 = _slicedToArray(
+    message.data, 2);var histogramId = _message$data11[0];var value = _message$data11[1];
 
     if (histogramId === "LOOP_ACTIVITY_COUNTER") {
       var pref = "mau." + kMauPrefMap.get(value);
       var prefDate = MozLoopService.getLoopPref(pref) * 1000;
       var delta = Date.now() - prefDate;
 
       // Send telemetry event if period (30 days) passed.
       // 0 is default value for pref.
       // 2592000 seconds in 30 days
       if (pref === 0 || delta >= 2592000 * 1000) {
         try {
-          Services.telemetry.getHistogramById(histogramId).add(value);} 
-        catch (ex) {
-          MozLoopService.log.error("TelemetryAddValue failed for histogram '" + histogramId + "'", ex);}
-
-        MozLoopService.setLoopPref(pref, Math.floor(Date.now() / 1000));}} else 
-
-    {
+          Services.telemetry.getHistogramById(histogramId).add(value);
+        } catch (ex) {
+          MozLoopService.log.error("TelemetryAddValue failed for histogram '" + histogramId + "'", ex);
+        }
+        MozLoopService.setLoopPref(pref, Math.floor(Date.now() / 1000));
+      }
+    } else {
       try {
-        Services.telemetry.getHistogramById(histogramId).add(value);} 
-      catch (ex) {
-        MozLoopService.log.error("TelemetryAddValue failed for histogram '" + histogramId + "'", ex);}}
+        Services.telemetry.getHistogramById(histogramId).add(value);
+      } catch (ex) {
+        MozLoopService.log.error("TelemetryAddValue failed for histogram '" + histogramId + "'", ex);
+      }
+    }
+    reply();
+  } };
 
 
-    reply();} };
-
-
-
-var LoopAPIInternal = { 
+var LoopAPIInternal = {
   /**
-   * Initialize the Loop API, which means:
-   * 1) setup RemotePageManager to hook into loop documents as channels and
-   *    start listening for messages therein.
-   * 2) start listening for other events that may be interesting.
-   */
+                         * Initialize the Loop API, which means:
+                         * 1) setup RemotePageManager to hook into loop documents as channels and
+                         *    start listening for messages therein.
+                         * 2) start listening for other events that may be interesting.
+                         */
   initialize: function initialize() {
     if (gPageListeners) {
-      return;}
-
+      return;
+    }
 
     Cu.import("resource://gre/modules/RemotePageManager.jsm");
 
-    gPageListeners = [new RemotePages("about:looppanel"), 
-    new RemotePages("about:loopconversation"), 
+    gPageListeners = [new RemotePages("about:looppanel"),
+    new RemotePages("about:loopconversation"),
     // Slideshow added here to expose the loop api to make L10n work.
     // XXX Can remove once slideshow is made remote.
     new RemotePages("chrome://loop/content/panels/slideshow.html")];var _iteratorNormalCompletion5 = true;var _didIteratorError5 = false;var _iteratorError5 = undefined;try {
       for (var _iterator5 = gPageListeners[Symbol.iterator](), _step5; !(_iteratorNormalCompletion5 = (_step5 = _iterator5.next()).done); _iteratorNormalCompletion5 = true) {var page = _step5.value;
-        page.addMessageListener(kMessageName, this.handleMessage.bind(this));}
-
+        page.addMessageListener(kMessageName, this.handleMessage.bind(this));
+      }
 
       // Subscribe to global events:
-    } catch (err) {_didIteratorError5 = true;_iteratorError5 = err;} finally {try {if (!_iteratorNormalCompletion5 && _iterator5.return) {_iterator5.return();}} finally {if (_didIteratorError5) {throw _iteratorError5;}}}Services.obs.addObserver(this.handleStatusChanged, "loop-status-changed", false);}, 
-
+    } catch (err) {_didIteratorError5 = true;_iteratorError5 = err;} finally {try {if (!_iteratorNormalCompletion5 && _iterator5.return) {_iterator5.return();}} finally {if (_didIteratorError5) {throw _iteratorError5;}}}Services.obs.addObserver(this.handleStatusChanged, "loop-status-changed", false);
+  },
 
   /**
-   * Handles incoming messages from RemotePageManager that are sent from Loop
-   * content pages.
-   *
-   * @param {Object} message Object containing the following fields:
-   *                         - {MessageManager} target Where the message came from
-   *                         - {String}         name   Name of the message
-   *                         - {Array}          data   Payload of the message
-   * @param {Function} [reply]
-   */
+      * Handles incoming messages from RemotePageManager that are sent from Loop
+      * content pages.
+      *
+      * @param {Object} message Object containing the following fields:
+      *                         - {MessageManager} target Where the message came from
+      *                         - {String}         name   Name of the message
+      *                         - {Array}          data   Payload of the message
+      * @param {Function} [reply]
+      */
   handleMessage: function handleMessage(message, reply) {
     var seq = message.data.shift();
     var action = message.data.shift();
 
     var actionParts = action.split(":");
 
     // The name that is supposed to match with a handler function is tucked inside
     // the second part of the message name. If all is well.
     var handlerName = actionParts.shift();
 
     if (!reply) {
       reply = function reply(result) {
         try {
-          message.target.sendAsyncMessage(message.name, [seq, result]);} 
-        catch (ex) {
-          MozLoopService.log.error("Failed to send reply back to content:", ex);}};}
-
-
-
+          message.target.sendAsyncMessage(message.name, [seq, result]);
+        } catch (ex) {
+          MozLoopService.log.error("Failed to send reply back to content:", ex);
+        }
+      };
+    }
 
     // First, check if this is a batch call.
     if (handlerName == kBatchMessage) {
       this.handleBatchMessage(seq, message, reply);
-      return;}
-
+      return;
+    }
 
     // Second, check if the message is meant for one of our Object APIs.
     // If so, a wildcard entry should exist for the message name in the
     // `kMessageHandlers` dictionary.
     var wildcardName = handlerName + ":*";
     if (kMessageHandlers[wildcardName]) {
       // A unit test might've stubbed the handler.
       if (gStubbedMessageHandlers && gStubbedMessageHandlers[wildcardName]) {
-        gStubbedMessageHandlers[wildcardName](action, message, reply);} else 
-      {
+        gStubbedMessageHandlers[wildcardName](action, message, reply);
+      } else {
         // Alright, pass the message forward.
-        kMessageHandlers[wildcardName](action, message, reply);}
-
+        kMessageHandlers[wildcardName](action, message, reply);
+      }
       // Aaaaand we're done.
-      return;}
-
+      return;
+    }
 
     // A unit test might've stubbed the handler.
     if (gStubbedMessageHandlers && gStubbedMessageHandlers[handlerName]) {
       gStubbedMessageHandlers[handlerName](message, reply);
-      return;}
-
+      return;
+    }
 
     if (!kMessageHandlers[handlerName]) {
       var msg = "Ouch, no message handler available for '" + handlerName + "'";
       MozLoopService.log.error(msg);
       reply(cloneableError(msg));
-      return;}
-
+      return;
+    }
 
-    kMessageHandlers[handlerName](message, reply);}, 
-
+    kMessageHandlers[handlerName](message, reply);
+  },
 
   /**
-   * If `sendMessage` above detects that the incoming message consists of a whole
-   * set of messages, this function is tasked with handling them.
-   * It iterates over all the messages, sends each to their appropriate handler
-   * and collects their results. The results will be sent back in one go as response
-   * to the batch message.
-   *
-   * @param {Number} seq       Sequence ID of this message
-   * @param {Object} message   Message containing the following parameters in
-   *                           its `data` property:
-   *                           [
-   *                             {Array} requests Sequence of messages
-   *                           ]
-   * @param {Function} reply   Callback function, invoked with the result of this
-   *                           message handler. The result will be sent back to
-   *                           the senders' channel.
-   */
+      * If `sendMessage` above detects that the incoming message consists of a whole
+      * set of messages, this function is tasked with handling them.
+      * It iterates over all the messages, sends each to their appropriate handler
+      * and collects their results. The results will be sent back in one go as response
+      * to the batch message.
+      *
+      * @param {Number} seq       Sequence ID of this message
+      * @param {Object} message   Message containing the following parameters in
+      *                           its `data` property:
+      *                           [
+      *                             {Array} requests Sequence of messages
+      *                           ]
+      * @param {Function} reply   Callback function, invoked with the result of this
+      *                           message handler. The result will be sent back to
+      *                           the senders' channel.
+      */
   handleBatchMessage: function handleBatchMessage(seq, message, reply) {var _this = this;
     var requests = message.data[0];
     if (!requests.length) {
-      MozLoopService.log.error("Ough, a batch call with no requests is not much " + 
+      MozLoopService.log.error("Ough, a batch call with no requests is not much " +
       "of a batch, now is it?");
-      return;}
-
+      return;
+    }
 
     // Since `handleBatchMessage` can be called recursively, but the replies are
     // collected and sent only once, we'll make sure only one exists for the
     // entire tail.
     // We count the amount of recursive calls, because we don't want any consumer
     // to cause an infinite loop, now do we?
     if (!("loopCount" in reply)) {
-      reply.loopCount = 0;} else 
-    if (++reply.loopCount > kMaxLoopCount) {
+      reply.loopCount = 0;
+    } else if (++reply.loopCount > kMaxLoopCount) {
       reply(cloneableError("Too many nested calls"));
-      return;}
-
+      return;
+    }
 
     var resultSet = {};
     Promise.all(requests.map(function (requestSet) {
       var requestSeq = requestSet[0];
       return new Promise(function (resolve) {return _this.handleMessage({ data: requestSet }, function (result) {
           resultSet[requestSeq] = result;
-          resolve();});});})).
-
-    then(function () {return reply(resultSet);});}, 
-
+          resolve();
+        });});
+    })).then(function () {return reply(resultSet);});
+  },
 
   /**
-   * Separate handler that is specialized in dealing with messages meant for sub-APIs,
-   * like LoopRooms.
-   *
-   * @param {Object}   api               Pointer to the sub-API.
-   * @param {String}   pushMessagePrefix
-   * @param {String}   action            Action name that translates to a function
-   *                                     name present on the sub-API.
-   * @param {Object}   message           Message containing parameters required to
-   *                                     perform the action on the sub-API  in its
-   *                                     `data` property.
-   * @param {Function} reply             Callback function, invoked with the result
-   *                                     of this message handler. The result will
-   *                                     be sent back to the senders' channel.
-   */
+      * Separate handler that is specialized in dealing with messages meant for sub-APIs,
+      * like LoopRooms.
+      *
+      * @param {Object}   api               Pointer to the sub-API.
+      * @param {String}   pushMessagePrefix
+      * @param {String}   action            Action name that translates to a function
+      *                                     name present on the sub-API.
+      * @param {Object}   message           Message containing parameters required to
+      *                                     perform the action on the sub-API  in its
+      *                                     `data` property.
+      * @param {Function} reply             Callback function, invoked with the result
+      *                                     of this message handler. The result will
+      *                                     be sent back to the senders' channel.
+      */
   handleObjectAPIMessage: function handleObjectAPIMessage(api, pushMessagePrefix, action, message, reply) {
     var funcName = getObjectAPIFunctionName(action);
 
     if (funcName == kPushSubscription) {var _ret = function () {
         // Incoming event listener request!
         var events = message.data[0];
         if (!events || !events.length) {
-          var msg = "Oops, don't forget to pass in event names when you try to " + 
+          var msg = "Oops, don't forget to pass in event names when you try to " +
           "subscribe to them!";
           MozLoopService.log.error(msg);
           reply(cloneableError(msg));
-          return { v: void 0 };}
-
+          return { v: void 0 };
+        }
 
         var handlerFunc = function handlerFunc(e) {for (var _len = arguments.length, data = Array(_len > 1 ? _len - 1 : 0), _key = 1; _key < _len; _key++) {data[_key - 1] = arguments[_key];}
           var prettyEventName = e.charAt(0).toUpperCase() + e.substr(1);
           try {
-            message.target.sendAsyncMessage(kPushMessageName, [pushMessagePrefix + 
-            prettyEventName, data]);} 
-          catch (ex) {
-            MozLoopService.log.debug("Unable to send event through to target: " + 
+            message.target.sendAsyncMessage(kPushMessageName, [pushMessagePrefix +
+            prettyEventName, data]);
+          } catch (ex) {
+            MozLoopService.log.debug("Unable to send event through to target: " +
             ex.message);
             // Unregister event handlers when the message port is unreachable.
             var _iteratorNormalCompletion6 = true;var _didIteratorError6 = false;var _iteratorError6 = undefined;try {for (var _iterator6 = events[Symbol.iterator](), _step6; !(_iteratorNormalCompletion6 = (_step6 = _iterator6.next()).done); _iteratorNormalCompletion6 = true) {var eventName = _step6.value;
-                api.off(eventName, handlerFunc);}} catch (err) {_didIteratorError6 = true;_iteratorError6 = err;} finally {try {if (!_iteratorNormalCompletion6 && _iterator6.return) {_iterator6.return();}} finally {if (_didIteratorError6) {throw _iteratorError6;}}}}};var _iteratorNormalCompletion7 = true;var _didIteratorError7 = false;var _iteratorError7 = undefined;try {
-
-
-
+                api.off(eventName, handlerFunc);
+              }} catch (err) {_didIteratorError6 = true;_iteratorError6 = err;} finally {try {if (!_iteratorNormalCompletion6 && _iterator6.return) {_iterator6.return();}} finally {if (_didIteratorError6) {throw _iteratorError6;}}}
+          }
+        };var _iteratorNormalCompletion7 = true;var _didIteratorError7 = false;var _iteratorError7 = undefined;try {
 
           for (var _iterator7 = events[Symbol.iterator](), _step7; !(_iteratorNormalCompletion7 = (_step7 = _iterator7.next()).done); _iteratorNormalCompletion7 = true) {var eventName = _step7.value;
-            api.on(eventName, handlerFunc);}} catch (err) {_didIteratorError7 = true;_iteratorError7 = err;} finally {try {if (!_iteratorNormalCompletion7 && _iterator7.return) {_iterator7.return();}} finally {if (_didIteratorError7) {throw _iteratorError7;}}}
-
+            api.on(eventName, handlerFunc);
+          }} catch (err) {_didIteratorError7 = true;_iteratorError7 = err;} finally {try {if (!_iteratorNormalCompletion7 && _iterator7.return) {_iterator7.return();}} finally {if (_didIteratorError7) {throw _iteratorError7;}}}
         reply();
-        return { v: void 0 };}();if ((typeof _ret === "undefined" ? "undefined" : _typeof(_ret)) === "object") return _ret.v;}
-
+        return { v: void 0 };}();if ((typeof _ret === "undefined" ? "undefined" : _typeof(_ret)) === "object") return _ret.v;
+    }
 
     if (typeof api[funcName] != "function") {
       reply(cloneableError("Sorry, function '" + funcName + "' does not exist!"));
-      return;}
-
+      return;
+    }
     api[funcName].apply(api, _toConsumableArray(message.data).concat([function (err, result) {
-      reply(err ? cloneableError(err) : result);}]));}, 
-
-
+      reply(err ? cloneableError(err) : result);
+    }]));
+  },
 
   /**
-   * Observer function for the 'loop-status-changed' event.
-   */
+      * Observer function for the 'loop-status-changed' event.
+      */
   handleStatusChanged: function handleStatusChanged() {
-    LoopAPIInternal.broadcastPushMessage("LoopStatusChanged");}, 
-
+    LoopAPIInternal.broadcastPushMessage("LoopStatusChanged");
+  },
 
   /**
-   * Send an event to the content window to indicate that the state on the chrome
-   * side was updated.
-   *
-   * @param {name} name Name of the event
-   */
+      * Send an event to the content window to indicate that the state on the chrome
+      * side was updated.
+      *
+      * @param {name} name Name of the event
+      */
   broadcastPushMessage: function broadcastPushMessage(name, data) {
     if (!gPageListeners) {
-      return;}var _iteratorNormalCompletion8 = true;var _didIteratorError8 = false;var _iteratorError8 = undefined;try {
-
+      return;
+    }var _iteratorNormalCompletion8 = true;var _didIteratorError8 = false;var _iteratorError8 = undefined;try {
       for (var _iterator8 = gPageListeners[Symbol.iterator](), _step8; !(_iteratorNormalCompletion8 = (_step8 = _iterator8.next()).done); _iteratorNormalCompletion8 = true) {var page = _step8.value;
         try {
-          page.sendAsyncMessage(kPushMessageName, [name, data]);} 
-        catch (ex) {
+          page.sendAsyncMessage(kPushMessageName, [name, data]);
+        } catch (ex) {
           // Only make noise when the Remote Page Manager needs more time to
           // initialize.
           if (ex.result != Components.results.NS_ERROR_NOT_INITIALIZED) {
-            throw ex;}}}} catch (err) {_didIteratorError8 = true;_iteratorError8 = err;} finally {try {if (!_iteratorNormalCompletion8 && _iterator8.return) {_iterator8.return();}} finally {if (_didIteratorError8) {throw _iteratorError8;}}}}, 
-
-
-
-
+            throw ex;
+          }
+        }
+      }} catch (err) {_didIteratorError8 = true;_iteratorError8 = err;} finally {try {if (!_iteratorNormalCompletion8 && _iterator8.return) {_iterator8.return();}} finally {if (_didIteratorError8) {throw _iteratorError8;}}}
+  },
 
   /**
-   * De the reverse of `initialize` above; unhook page and event listeners.
-   */
+      * De the reverse of `initialize` above; unhook page and event listeners.
+      */
   destroy: function destroy() {
     if (!gPageListeners) {
-      return;}var _iteratorNormalCompletion9 = true;var _didIteratorError9 = false;var _iteratorError9 = undefined;try {
-
+      return;
+    }var _iteratorNormalCompletion9 = true;var _didIteratorError9 = false;var _iteratorError9 = undefined;try {
       for (var _iterator9 = gPageListeners[Symbol.iterator](), _step9; !(_iteratorNormalCompletion9 = (_step9 = _iterator9.next()).done); _iteratorNormalCompletion9 = true) {var listener = _step9.value;
-        listener.destroy();}} catch (err) {_didIteratorError9 = true;_iteratorError9 = err;} finally {try {if (!_iteratorNormalCompletion9 && _iterator9.return) {_iterator9.return();}} finally {if (_didIteratorError9) {throw _iteratorError9;}}}
-
+        listener.destroy();
+      }} catch (err) {_didIteratorError9 = true;_iteratorError9 = err;} finally {try {if (!_iteratorNormalCompletion9 && _iterator9.return) {_iterator9.return();}} finally {if (_didIteratorError9) {throw _iteratorError9;}}}
     gPageListeners = null;
 
     // Unsubscribe from global events.
-    Services.obs.removeObserver(this.handleStatusChanged, "loop-status-changed");} };
+    Services.obs.removeObserver(this.handleStatusChanged, "loop-status-changed");
+  } };
 
 
-
-this.LoopAPI = Object.freeze({ 
+this.LoopAPI = Object.freeze({
   /* @see LoopAPIInternal#initialize */
   initialize: function initialize() {
-    LoopAPIInternal.initialize();}, 
-
+    LoopAPIInternal.initialize();
+  },
   /* @see LoopAPIInternal#broadcastPushMessage */
   broadcastPushMessage: function broadcastPushMessage(name, data) {
-    LoopAPIInternal.broadcastPushMessage(name, data);}, 
-
+    LoopAPIInternal.broadcastPushMessage(name, data);
+  },
   /* @see LoopAPIInternal#destroy */
   destroy: function destroy() {
-    LoopAPIInternal.destroy();}, 
-
+    LoopAPIInternal.destroy();
+  },
   /**
-   * Gateway for chrome scripts to send a message to a message handler, when
-   * using the RemotePageManager module is not an option.
-   *
-   * @param {Object}   message Message meant for the handler function, containing
-   *                           the following properties:
-   *                           - {String} name     Name of handler to send this
-   *                                               message to. See `kMessageHandlers`
-   *                                               for the available names.
-   *                           - {String} [action] Optional action name of the
-   *                                               function to call on a sub-API.
-   *                           - {Array}  data     List of arguments that the
-   *                                               handler can use.
-   * @param {Function} [reply] Callback function, invoked with the result of this
-   *                           message handler. Optional.
-   */
+      * Gateway for chrome scripts to send a message to a message handler, when
+      * using the RemotePageManager module is not an option.
+      *
+      * @param {Object}   message Message meant for the handler function, containing
+      *                           the following properties:
+      *                           - {String} name     Name of handler to send this
+      *                                               message to. See `kMessageHandlers`
+      *                                               for the available names.
+      *                           - {String} [action] Optional action name of the
+      *                                               function to call on a sub-API.
+      *                           - {Array}  data     List of arguments that the
+      *                                               handler can use.
+      * @param {Function} [reply] Callback function, invoked with the result of this
+      *                           message handler. Optional.
+      */
   sendMessageToHandler: function sendMessageToHandler(message, reply) {
     reply = reply || function () {};
     var handlerName = message.name;
     var handler = kMessageHandlers[handlerName];
     if (gStubbedMessageHandlers && gStubbedMessageHandlers[handlerName]) {
-      handler = gStubbedMessageHandlers[handlerName];}
-
+      handler = gStubbedMessageHandlers[handlerName];
+    }
     if (!handler) {
       var msg = "Ouch, no message handler available for '" + handlerName + "'";
       MozLoopService.log.error(msg);
       reply(cloneableError(msg));
-      return;}
-
+      return;
+    }
 
     if (!message.data) {
-      message.data = [];}
-
+      message.data = [];
+    }
 
     if (handlerName.endsWith("*")) {
-      handler(message.action, message, reply);} else 
-    {
-      handler(message, reply);}}, 
-
-
+      handler(message.action, message, reply);
+    } else {
+      handler(message, reply);
+    }
+  },
   // The following functions are only used in unit tests.
   inspect: function inspect() {
-    return [Object.create(LoopAPIInternal), Object.create(kMessageHandlers), 
-    gPageListeners ? [].concat(_toConsumableArray(gPageListeners)) : null];}, 
-
+    return [Object.create(LoopAPIInternal), Object.create(kMessageHandlers),
+    gPageListeners ? [].concat(_toConsumableArray(gPageListeners)) : null];
+  },
   stub: function stub(pageListeners) {
     if (!gOriginalPageListeners) {
-      gOriginalPageListeners = gPageListeners;}
-
-    gPageListeners = pageListeners;}, 
-
+      gOriginalPageListeners = gPageListeners;
+    }
+    gPageListeners = pageListeners;
+  },
   stubMessageHandlers: function stubMessageHandlers(handlers) {
-    gStubbedMessageHandlers = handlers;}, 
-
+    gStubbedMessageHandlers = handlers;
+  },
   restore: function restore() {
     if (gOriginalPageListeners) {
-      gPageListeners = gOriginalPageListeners;}
-
-    gStubbedMessageHandlers = null;} });
+      gPageListeners = gOriginalPageListeners;
+    }
+    gStubbedMessageHandlers = null;
+  } });
--- a/browser/extensions/loop/chrome/content/modules/MozLoopPushHandler.jsm
+++ b/browser/extensions/loop/chrome/content/modules/MozLoopPushHandler.jsm
@@ -1,19 +1,19 @@
 /* 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";function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}}var _Components = 
+"use strict";function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}}var _Components =
 
 Components;var Cc = _Components.classes;var Ci = _Components.interfaces;var Cu = _Components.utils;
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
-Cu.import("resource://gre/modules/Timer.jsm");var _Cu$import = 
+Cu.import("resource://gre/modules/Timer.jsm");var _Cu$import =
 
 Cu.import("chrome://loop/content/modules/MozLoopService.jsm", {});var MozLoopService = _Cu$import.MozLoopService;
 var consoleLog = MozLoopService.log;
 
 /* exported MozLoopPushHandler */
 
 this.EXPORTED_SYMBOLS = ["MozLoopPushHandler"];
 
@@ -21,590 +21,590 @@ var CONNECTION_STATE_CLOSED = 0;
 var CONNECTION_STATE_CONNECTING = 1;
 var CONNECTION_STATE_OPEN = 2;
 
 var SERVICE_STATE_OFFLINE = 0;
 var SERVICE_STATE_PENDING = 1;
 var SERVICE_STATE_ACTIVE = 2;
 
 function PushSocket() {var webSocket = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0];
-  this._websocket = webSocket;}
+  this._websocket = webSocket;
+}
 
-
-PushSocket.prototype = { 
+PushSocket.prototype = {
 
   /**
-   * Open push-notification websocket.
-   *
-   * @param {String} pushUri
-   * @param {Function} onMsg(aMsg) callback receives any incoming messages
-   *                   aMsg is constructed from the json payload; both
-   *                   text and binary message reception are mapped to this
-   *                   callback.
-   * @param {Function} onStart called when the socket is connected
-   * @param {Function} onClose(aCode, aReason) called when the socket closes;
-   *                   both near and far side close events map to this
-   *                   callback.
-   *                   aCode is any status code returned on close
-   *                   aReason is any string returned on close
-   */
+                          * Open push-notification websocket.
+                          *
+                          * @param {String} pushUri
+                          * @param {Function} onMsg(aMsg) callback receives any incoming messages
+                          *                   aMsg is constructed from the json payload; both
+                          *                   text and binary message reception are mapped to this
+                          *                   callback.
+                          * @param {Function} onStart called when the socket is connected
+                          * @param {Function} onClose(aCode, aReason) called when the socket closes;
+                          *                   both near and far side close events map to this
+                          *                   callback.
+                          *                   aCode is any status code returned on close
+                          *                   aReason is any string returned on close
+                          */
 
   connect: function connect(pushUri, onMsg, onStart, onClose) {
     if (!pushUri || !onMsg || !onStart || !onClose) {
       throw new Error("PushSocket: missing required parameter(s):" + (
       pushUri ? "" : " pushUri") + (
       onMsg ? "" : " onMsg") + (
       onStart ? "" : " onStart") + (
-      onClose ? "" : " onClose"));}
-
+      onClose ? "" : " onClose"));
+    }
 
     this._onMsg = onMsg;
     this._onStart = onStart;
     this._onClose = onClose;
 
     if (!this._websocket) {
       this._websocket = Cc["@mozilla.org/network/protocol;1?name=wss"].
       createInstance(Ci.nsIWebSocketChannel);
       this._websocket.initLoadInfo(null, // aLoadingNode
-      Services.scriptSecurityManager.getSystemPrincipal(), 
+      Services.scriptSecurityManager.getSystemPrincipal(),
       null, // aTriggeringPrincipal
-      Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL, 
-      Ci.nsIContentPolicy.TYPE_WEBSOCKET);}
-
+      Ci.nsILoadInfo.SEC_ALLOW_CROSS_ORIGIN_DATA_IS_NULL,
+      Ci.nsIContentPolicy.TYPE_WEBSOCKET);
+    }
 
     var uri = Services.io.newURI(pushUri, null, null);
     this._websocket.protocol = "push-notification";
-    this._websocket.asyncOpen(uri, pushUri, 0, this, null);}, 
-
+    this._websocket.asyncOpen(uri, pushUri, 0, this, null);
+  },
 
   /**
-   * nsIWebSocketListener method, handles the start of the websocket stream.
-   *
-   * @param {nsISupports} aContext Not used
-   */
+      * nsIWebSocketListener method, handles the start of the websocket stream.
+      *
+      * @param {nsISupports} aContext Not used
+      */
   onStart: function onStart() {
     this._socketOpen = true;
-    this._onStart();}, 
-
+    this._onStart();
+  },
 
   /**
-   * nsIWebSocketListener method, called when the websocket is closed locally.
-   *
-   * @param {nsISupports} aContext Not used
-   * @param {nsresult} aStatusCode
-   */
+      * nsIWebSocketListener method, called when the websocket is closed locally.
+      *
+      * @param {nsISupports} aContext Not used
+      * @param {nsresult} aStatusCode
+      */
   onStop: function onStop(aContext, aStatusCode) {
     this._socketOpen = false;
-    this._onClose(aStatusCode, "websocket onStop");}, 
-
+    this._onClose(aStatusCode, "websocket onStop");
+  },
 
   /**
-   * nsIWebSocketListener method, called when the websocket is closed
-   * by the far end.
-   *
-   * @param {nsISupports} aContext Not used
-   * @param {integer} aCode the websocket closing handshake close code
-   * @param {String} aReason the websocket closing handshake close reason
-   */
+      * nsIWebSocketListener method, called when the websocket is closed
+      * by the far end.
+      *
+      * @param {nsISupports} aContext Not used
+      * @param {integer} aCode the websocket closing handshake close code
+      * @param {String} aReason the websocket closing handshake close reason
+      */
   onServerClose: function onServerClose(aContext, aCode, aReason) {
     this._socketOpen = false;
-    this._onClose(aCode, aReason);}, 
-
+    this._onClose(aCode, aReason);
+  },
 
   /**
-   * nsIWebSocketListener method, called when the websocket receives
-   * a text message (normally json encoded).
-   *
-   * @param {nsISupports} aContext Not used
-   * @param {String} aMsg The message data
-   */
+      * nsIWebSocketListener method, called when the websocket receives
+      * a text message (normally json encoded).
+      *
+      * @param {nsISupports} aContext Not used
+      * @param {String} aMsg The message data
+      */
   onMessageAvailable: function onMessageAvailable(aContext, aMsg) {
     consoleLog.log("PushSocket: Message received: ", aMsg);
     if (!this._socketOpen) {
       consoleLog.error("Message received in Winsocket closed state");
-      return;}
-
+      return;
+    }
 
     try {
-      this._onMsg(JSON.parse(aMsg));} 
-
+      this._onMsg(JSON.parse(aMsg));
+    }
     catch (error) {
-      consoleLog.error("PushSocket: error parsing message payload - ", error);}}, 
-
-
+      consoleLog.error("PushSocket: error parsing message payload - ", error);
+    }
+  },
 
   /**
-   * nsIWebSocketListener method, called when the websocket receives a binary message.
-   * This class assumes that it is connected to a SimplePushServer and therefore treats
-   * the message payload as json encoded.
-   *
-   * @param {nsISupports} aContext Not used
-   * @param {String} aMsg The message data
-   */
+      * nsIWebSocketListener method, called when the websocket receives a binary message.
+      * This class assumes that it is connected to a SimplePushServer and therefore treats
+      * the message payload as json encoded.
+      *
+      * @param {nsISupports} aContext Not used
+      * @param {String} aMsg The message data
+      */
   onBinaryMessageAvailable: function onBinaryMessageAvailable(aContext, aMsg) {
     consoleLog.log("PushSocket: Binary message received: ", aMsg);
     if (!this._socketOpen) {
       consoleLog.error("PushSocket: message receive in Winsocket closed state");
-      return;}
-
+      return;
+    }
 
     try {
-      this._onMsg(JSON.parse(aMsg));} 
-
+      this._onMsg(JSON.parse(aMsg));
+    }
     catch (error) {
-      consoleLog.error("PushSocket: error parsing message payload - ", error);}}, 
-
-
+      consoleLog.error("PushSocket: error parsing message payload - ", error);
+    }
+  },
 
   /**
-   * Create a JSON encoded message payload and send via websocket.
-   *
-   * @param {Object} aMsg Message to send.
-   *
-   * @returns {Boolean} true if message has been sent, false otherwise
-   */
+      * Create a JSON encoded message payload and send via websocket.
+      *
+      * @param {Object} aMsg Message to send.
+      *
+      * @returns {Boolean} true if message has been sent, false otherwise
+      */
   send: function send(aMsg) {
     if (!this._socketOpen) {
       consoleLog.error("PushSocket: attempt to send before websocket is open");
-      return false;}
-
+      return false;
+    }
 
     var msg = void 0;
     try {
-      msg = JSON.stringify(aMsg);} 
-
+      msg = JSON.stringify(aMsg);
+    }
     catch (error) {
       consoleLog.error("PushSocket: JSON generation error - ", error);
-      return false;}
-
+      return false;
+    }
 
     try {
       this._websocket.sendMsg(msg);
-      consoleLog.log("PushSocket: Message sent: ", msg);}
-
+      consoleLog.log("PushSocket: Message sent: ", msg);
+    }
     // guard against the case that the websocket has closed before this call.
     catch (e) {
       consoleLog.warn("PushSocket: websocket send error", e);
-      return false;}
-
+      return false;
+    }
 
-    return true;}, 
-
+    return true;
+  },
 
   /**
-   * Close the websocket.
-   */
+      * Close the websocket.
+      */
   close: function close() {
     if (!this._socketOpen) {
-      return;}
-
+      return;
+    }
 
     this._socketOpen = false;
     consoleLog.info("PushSocket: websocket closing");
 
     // Do not pass through any callbacks after this point.
     this._onStart = function () {};
     this._onMsg = this._onStart;
     this._onClose = this._onStart;
 
     try {
-      this._websocket.close(this._websocket.CLOSE_NORMAL);} 
-
+      this._websocket.close(this._websocket.CLOSE_NORMAL);
+    }
     catch (e) {
       // Do nothing
-    }} };
-
-
-
-
-/**
- * Create a RetryManager object. Class to handle retrying a UserAgent
- * to PushServer request following a retry back-off scheme managed by
- * this class. The current delay mechanism is to double the delay
- * each time an operation to be retried until a maximum is met.
- *
- * @param {Integer} startDelay The initial delay interval in milliseconds.
- * @param {Integer} maxDelay Maximum time delay value in milliseconds.
- */
-function RetryManager(startDelay, maxDelay) {
-  if (!startDelay || !maxDelay) {
-    throw new Error("RetryManager: missing required parameters(s)" + (
-    startDelay ? "" : " startDelay") + (
-    maxDelay ? "" : " maxDelay"));}
-
-
-  this._startDelay = startDelay;
-  // The maximum delay cannot be less than the starting delay.
-  this._maxDelay = maxDelay > startDelay ? maxDelay : startDelay;}
-
-
-RetryManager.prototype = { 
-  /**
-   * Method to handle retrying a UserAgent to PushServer request.
-   *
-   * @param {Function} delayedOp Function to call after current delay is satisfied
-   */
-  retry: function retry(delayedOp) {
-    if (!this._timeoutID) {
-      this._retryDelay = this._startDelay;} else 
-    {
-      clearTimeout(this._timeoutID);
-      var nextDelay = this._retryDelay * 2;
-      this._retryDelay = nextDelay > this._maxDelay ? this._maxDelay : nextDelay;}
-
-
-    this._timeoutID = setTimeout(delayedOp, this._retryDelay);
-    consoleLog.log("PushHandler: retry delay set for ", this._retryDelay);}, 
-
-
-  /**
-   * Method used to reset the delay back-off logic and clear any currently
-   * running delay timeout.
-   */
-  reset: function reset() {
-    if (this._timeoutID) {
-      clearTimeout(this._timeoutID);
-      this._timeoutID = null;}} };
-
+    }
+  } };
 
 
 
 /**
- * Create a PingMonitor object. An object instance will periodically execute
- * a ping send function and if not reset, will then execute an error function.
- *
- * @param {Function} pingFunc Function that is called after a ping interval
- *                   has expired without being restart.
- * @param {Function} onTimeout Function that is called after a ping timeout
- *                   interval has expired without restart being called.
- * @param {Integer} interval Timeout value in milliseconds between successive
- *                  pings or between the last restart call and a ping.
- *                  When this interval expires, pingFunc is called and the
- *                  timeout interval is started.
- * @param {Integer} timeout Timeout value in milliseconds between a call to
- *                  pingFunc and a call to onTimeout unless restart is called.
- *                  Restart will begin the ping timeout interval again.
- */
+        * Create a RetryManager object. Class to handle retrying a UserAgent
+        * to PushServer request following a retry back-off scheme managed by
+        * this class. The current delay mechanism is to double the delay
+        * each time an operation to be retried until a maximum is met.
+        *
+        * @param {Integer} startDelay The initial delay interval in milliseconds.
+        * @param {Integer} maxDelay Maximum time delay value in milliseconds.
+        */
+function RetryManager(startDelay, maxDelay) {
+  if (!startDelay || !maxDelay) {
+    throw new Error("RetryManager: missing required parameters(s)" + (
+    startDelay ? "" : " startDelay") + (
+    maxDelay ? "" : " maxDelay"));
+  }
+
+  this._startDelay = startDelay;
+  // The maximum delay cannot be less than the starting delay.
+  this._maxDelay = maxDelay > startDelay ? maxDelay : startDelay;
+}
+
+RetryManager.prototype = {
+  /**
+                            * Method to handle retrying a UserAgent to PushServer request.
+                            *
+                            * @param {Function} delayedOp Function to call after current delay is satisfied
+                            */
+  retry: function retry(delayedOp) {
+    if (!this._timeoutID) {
+      this._retryDelay = this._startDelay;
+    } else {
+      clearTimeout(this._timeoutID);
+      var nextDelay = this._retryDelay * 2;
+      this._retryDelay = nextDelay > this._maxDelay ? this._maxDelay : nextDelay;
+    }
+
+    this._timeoutID = setTimeout(delayedOp, this._retryDelay);
+    consoleLog.log("PushHandler: retry delay set for ", this._retryDelay);
+  },
+
+  /**
+      * Method used to reset the delay back-off logic and clear any currently
+      * running delay timeout.
+      */
+  reset: function reset() {
+    if (this._timeoutID) {
+      clearTimeout(this._timeoutID);
+      this._timeoutID = null;
+    }
+  } };
+
+
+/**
+        * Create a PingMonitor object. An object instance will periodically execute
+        * a ping send function and if not reset, will then execute an error function.
+        *
+        * @param {Function} pingFunc Function that is called after a ping interval
+        *                   has expired without being restart.
+        * @param {Function} onTimeout Function that is called after a ping timeout
+        *                   interval has expired without restart being called.
+        * @param {Integer} interval Timeout value in milliseconds between successive
+        *                  pings or between the last restart call and a ping.
+        *                  When this interval expires, pingFunc is called and the
+        *                  timeout interval is started.
+        * @param {Integer} timeout Timeout value in milliseconds between a call to
+        *                  pingFunc and a call to onTimeout unless restart is called.
+        *                  Restart will begin the ping timeout interval again.
+        */
 function PingMonitor(pingFunc, onTimeout, interval, timeout) {
   if (!pingFunc || !onTimeout || !interval || !timeout) {
-    throw new Error("PingMonitor: missing required parameters");}
-
+    throw new Error("PingMonitor: missing required parameters");
+  }
   this._onTimeout = onTimeout;
   this._pingFunc = pingFunc;
   this._pingInterval = interval;
-  this._pingTimeout = timeout;}
-
+  this._pingTimeout = timeout;
+}
 
-PingMonitor.prototype = { 
+PingMonitor.prototype = {
   /**
-   * Function to restart the ping timeout and cancel any current timeout operation.
-   */
+                           * Function to restart the ping timeout and cancel any current timeout operation.
+                           */
   restart: function restart() {var _this = this;
     consoleLog.info("PushHandler: ping timeout restart");
     this.stop();
-    this._pingTimerID = setTimeout(function () {return _this._pingSend();}, this._pingInterval);}, 
-
+    this._pingTimerID = setTimeout(function () {return _this._pingSend();}, this._pingInterval);
+  },
 
   /**
-   * Function to stop the PingMonitor.
-   */
+      * Function to stop the PingMonitor.
+      */
   stop: function stop() {
     if (this._pingTimerID) {
       clearTimeout(this._pingTimerID);
-      this._pingTimerID = undefined;}}, 
-
-
+      this._pingTimerID = undefined;
+    }
+  },
 
   _pingSend: function _pingSend() {
     consoleLog.info("PushHandler: ping sent");
     this._pingTimerID = setTimeout(this._onTimeout, this._pingTimeout);
-    this._pingFunc();} };
-
+    this._pingFunc();
+  } };
 
 
 
 /**
- * We don't have push notifications on desktop currently, so this is a
- * workaround to get them going for us.
- */
-var MozLoopPushHandler = { 
+        * We don't have push notifications on desktop currently, so this is a
+        * workaround to get them going for us.
+        */
+var MozLoopPushHandler = {
   // This is the uri of the push server.
-  pushServerUri: undefined, 
+  pushServerUri: undefined,
   // Records containing the registration and notification callbacks indexed by channelID.
   // Each channel will be registered with the PushServer.
-  channels: new Map(), 
+  channels: new Map(),
   // This is the UserAgent UUID assigned by the PushServer
-  uaID: undefined, 
+  uaID: undefined,
   // Each successfully registered channelID is used as a key to hold its pushEndpoint URL.
-  registeredChannels: {}, 
+  registeredChannels: {},
   // Push protocol state variable
-  serviceState: SERVICE_STATE_OFFLINE, 
+  serviceState: SERVICE_STATE_OFFLINE,
   // Websocket connection state variable
-  connectionState: CONNECTION_STATE_CLOSED, 
+  connectionState: CONNECTION_STATE_CLOSED,
   // Contains channels that need to be registered with the PushServer
-  _channelsToRegister: [], 
+  _channelsToRegister: [],
 
   get _startRetryDelay_ms() {
     try {
-      return Services.prefs.getIntPref("loop.retry_delay.start");} 
-
+      return Services.prefs.getIntPref("loop.retry_delay.start");
+    }
     catch (e) {
       return 60000; // 1 minute
-    }}, 
-
+    }
+  },
 
   get _maxRetryDelay_ms() {
     try {
-      return Services.prefs.getIntPref("loop.retry_delay.limit");} 
-
+      return Services.prefs.getIntPref("loop.retry_delay.limit");
+    }
     catch (e) {
       return 300000; // 5 minutes
-    }}, 
-
+    }
+  },
 
   get _pingInterval_ms() {
     try {
-      return Services.prefs.getIntPref("loop.ping.interval");} 
-
+      return Services.prefs.getIntPref("loop.ping.interval");
+    }
     catch (e) {
       return 18000000; // 30 minutes
-    }}, 
-
+    }
+  },
 
   get _pingTimeout_ms() {
     try {
-      return Services.prefs.getIntPref("loop.ping.timeout");} 
-
+      return Services.prefs.getIntPref("loop.ping.timeout");
+    }
     catch (e) {
       return 10000; // 10 seconds
-    }}, 
-
+    }
+  },
 
   /**
-   * Inializes the PushHandler and opens a socket with the PushServer.
-   * It will automatically say hello and register any channels
-   * that are found in the work queue at that point.
-   *
-   * @param {Object} options Set of configuration options. Currently,
-   *                 the only option is mocketWebSocket which will be
-   *                 used for testing.
-   */
+      * Inializes the PushHandler and opens a socket with the PushServer.
+      * It will automatically say hello and register any channels
+      * that are found in the work queue at that point.
+      *
+      * @param {Object} options Set of configuration options. Currently,
+      *                 the only option is mocketWebSocket which will be
+      *                 used for testing.
+      */
   initialize: function initialize() {var _this2 = this;var options = arguments.length <= 0 || arguments[0] === undefined ? {} : arguments[0];
     consoleLog.info("PushHandler: initialize options = ", options);
 
     if (this._initDone) {
-      return;}
-
+      return;
+    }
 
     this._initDone = true;
-    this._retryManager = new RetryManager(this._startRetryDelay_ms, 
+    this._retryManager = new RetryManager(this._startRetryDelay_ms,
     this._maxRetryDelay_ms);
     // Send an empty json payload as a ping.
     // Close the websocket and re-open if a timeout occurs.
-    this._pingMonitor = new PingMonitor(function () {return _this2._pushSocket.send({});}, 
-    function () {return _this2._restartConnection();}, 
-    this._pingInterval_ms, 
+    this._pingMonitor = new PingMonitor(function () {return _this2._pushSocket.send({});},
+    function () {return _this2._restartConnection();},
+    this._pingInterval_ms,
     this._pingTimeout_ms);
 
     if ("mockWebSocket" in options) {
-      this._mockWebSocket = options.mockWebSocket;}
-
+      this._mockWebSocket = options.mockWebSocket;
+    }
 
     this.pushServerUri = Services.prefs.getCharPref("dom.push.serverURL");
 
-    this._openSocket();}, 
-
+    this._openSocket();
+  },
 
   /**
-   * Reset and clear PushServer connection.
-   * Returns MozLoopPushHandler to pre-initialized state.
-   */
+      * Reset and clear PushServer connection.
+      * Returns MozLoopPushHandler to pre-initialized state.
+      */
   shutdown: function shutdown() {var _this3 = this;
     consoleLog.info("PushHandler: shutdown");
     if (!this._initDone) {
-      return;}
-
+      return;
+    }
 
     this._initDone = false;
     this._retryManager.reset();
     this._pingMonitor.stop();
 
     // Un-register each active notification channel
     if (this.connectionState === CONNECTION_STATE_OPEN) {
       Object.keys(this.registeredChannels).forEach(function (id) {
-        var unRegMsg = { messageType: "unregister", 
+        var unRegMsg = { messageType: "unregister",
           channelID: id };
-        _this3._pushSocket.send(unRegMsg);});
-
-      this.registeredChannels = {};}
-
+        _this3._pushSocket.send(unRegMsg);
+      });
+      this.registeredChannels = {};
+    }
 
     this.connectionState = CONNECTION_STATE_CLOSED;
     this.serviceState = SERVICE_STATE_OFFLINE;
     this._pushSocket.close();
     this._pushSocket = undefined;
     // NOTE: this PushSocket instance will not be released until at least
     // the websocket referencing it as an nsIWebSocketListener is released.
     this.channels.clear();
     this.uaID = undefined;
     this.pushUrl = undefined;
-    this.pushServerUri = undefined;}, 
-
+    this.pushServerUri = undefined;
+  },
 
   /**
-   * Assign a channel to be registered with the PushServer
-   * This channel will be registered when a connection to the PushServer
-   * has been established or re-registered after a connection has been lost
-   * and re-established. Calling this more than once for the same channel
-   * has no additional effect.
-   *
-   * onRegistered callback parameters:
-   * - {String|null} err: Encountered error, if any
-   * - {String} url: The push url obtained from the server
-   * - {String} channelID The channelID on which the notification was sent.
-   *
-   * onNotification parameters:
-   * - {String} version The version string received from the push server for
-   *                    the notification.
-   * - {String} channelID The channelID on which the notification was sent.
-   *
-   * @param {String} channelID Channel ID to use in registration.
-   *
-   * @param {Function} onRegistered Callback to be called once we are
-   *                   registered.
-   *                   NOTE: This function can be called multiple times if
-   *                   the PushServer generates new pushURLs due to
-   *                   re-registration due to network loss or PushServer
-   *                   initiated re-assignment.
-   * @param {Function} onNotification Callback to be called when a
-   *                   push notification is received (may be called multiple
-   *                   times).
-   */
+      * Assign a channel to be registered with the PushServer
+      * This channel will be registered when a connection to the PushServer
+      * has been established or re-registered after a connection has been lost
+      * and re-established. Calling this more than once for the same channel
+      * has no additional effect.
+      *
+      * onRegistered callback parameters:
+      * - {String|null} err: Encountered error, if any
+      * - {String} url: The push url obtained from the server
+      * - {String} channelID The channelID on which the notification was sent.
+      *
+      * onNotification parameters:
+      * - {String} version The version string received from the push server for
+      *                    the notification.
+      * - {String} channelID The channelID on which the notification was sent.
+      *
+      * @param {String} channelID Channel ID to use in registration.
+      *
+      * @param {Function} onRegistered Callback to be called once we are
+      *                   registered.
+      *                   NOTE: This function can be called multiple times if
+      *                   the PushServer generates new pushURLs due to
+      *                   re-registration due to network loss or PushServer
+      *                   initiated re-assignment.
+      * @param {Function} onNotification Callback to be called when a
+      *                   push notification is received (may be called multiple
+      *                   times).
+      */
   register: function register(channelID, onRegistered, onNotification) {
     if (!channelID || !onRegistered || !onNotification) {
       throw new Error("missing required parameter(s):" + (
       channelID ? "" : " channelID") + (
       onRegistered ? "" : " onRegistered") + (
-      onNotification ? "" : " onNotification"));}
-
+      onNotification ? "" : " onNotification"));
+    }
 
     consoleLog.info("PushHandler: channel registration: ", channelID);
     if (this.channels.has(channelID)) {
       // If this channel has an active registration with the PushServer
       // call the onRegister callback with the URL.
       if (this.registeredChannels[channelID]) {
-        onRegistered(null, this.registeredChannels[channelID], channelID);}
-
+        onRegistered(null, this.registeredChannels[channelID], channelID);
+      }
       // Update the channel record.
-      this.channels.set(channelID, { onRegistered: onRegistered, 
+      this.channels.set(channelID, { onRegistered: onRegistered,
         onNotification: onNotification });
-      return;}
+      return;
+    }
 
-
-    this.channels.set(channelID, { onRegistered: onRegistered, 
+    this.channels.set(channelID, { onRegistered: onRegistered,
       onNotification: onNotification });
     this._channelsToRegister.push(channelID);
-    this._registerChannels();}, 
-
+    this._registerChannels();
+  },
 
   /**
-   * Un-register a notification channel.
-   *
-   * @param {String} channelID Notification channel ID.
-   */
+      * Un-register a notification channel.
+      *
+      * @param {String} channelID Notification channel ID.
+      */
   unregister: function unregister(channelID) {
     consoleLog.info("MozLoopPushHandler: un-register channel ", channelID);
     if (!this.channels.has(channelID)) {
-      return;}
-
+      return;
+    }
 
     this.channels.delete(channelID);
 
     if (this.registeredChannels[channelID]) {
       delete this.registeredChannels[channelID];
       if (this.connectionState === CONNECTION_STATE_OPEN) {
-        this._pushSocket.send({ messageType: "unregister", 
-          channelID: channelID });}}}, 
-
-
-
+        this._pushSocket.send({ messageType: "unregister",
+          channelID: channelID });
+      }
+    }
+  },
 
   /**
-   * Handles the start of the websocket stream.
-   * Sends a hello message to the server.
-   *
-   */
+      * Handles the start of the websocket stream.
+      * Sends a hello message to the server.
+      *
+      */
   _onStart: function _onStart() {var _this4 = this;
     consoleLog.info("PushHandler: websocket open, sending 'hello' to PushServer");
     this.connectionState = CONNECTION_STATE_OPEN;
     // If a uaID has already been assigned, assume this is a re-connect;
     // send the uaID and channelIDs in order to re-synch with the
     // PushServer. The PushServer does not need to accept the existing channelIDs
     // and may issue new channelIDs along with new pushURLs.
     this.serviceState = SERVICE_STATE_PENDING;
-    var helloMsg = { 
-      messageType: "hello", 
-      uaid: this.uaID || "", 
+    var helloMsg = {
+      messageType: "hello",
+      uaid: this.uaID || "",
       channelIDs: this.uaID ? Object.keys(this.registeredChannels) : [] };
 
     // The Simple PushServer spec does not allow a retry of the Hello handshake but requires that the socket
     // be closed and another socket openned in order to re-attempt the handshake.
     // Here, the retryManager is not set up to retry the sending another 'hello' message: the timeout will
     // trigger closing the websocket and starting the connection again from the start.
     this._retryManager.reset();
     this._retryManager.retry(function () {return _this4._restartConnection();});
-    this._pushSocket.send(helloMsg);}, 
-
+    this._pushSocket.send(helloMsg);
+  },
 
   /**
-   * Handles websocket close callbacks.
-   *
-   * This method will continually try to re-establish a connection
-   * to the PushServer unless shutdown has been called.
-   */
+      * Handles websocket close callbacks.
+      *
+      * This method will continually try to re-establish a connection
+      * to the PushServer unless shutdown has been called.
+      */
   _onClose: function _onClose(aCode) {var _this5 = this;
     this._pingMonitor.stop();
 
     switch (this.connectionState) {
       case CONNECTION_STATE_OPEN:
         this.connectionState = CONNECTION_STATE_CLOSED;
         consoleLog.info("PushHandler: websocket closed: begin reconnect - ", aCode);
         // The first retry is immediate
         this._retryManager.reset();
         this._openSocket();
         break;
 
       case CONNECTION_STATE_CONNECTING:
         // Wait before re-attempting to open the websocket.
         consoleLog.info("PushHandler: websocket closed: delay and retry - ", aCode);
         this._retryManager.retry(function () {return _this5._openSocket();});
-        break;}}, 
+        break;}
 
-
+  },
 
   /**
-   * Listener method, called when the websocket receives a message.
-   *
-   * @param {Object} aMsg The message data
-   */
+      * Listener method, called when the websocket receives a message.
+      *
+      * @param {Object} aMsg The message data
+      */
   _onMsg: function _onMsg(aMsg) {
     // If an error property exists in the message object ignore the other
     // properties.
     if (aMsg.error) {
       consoleLog.error("PushHandler: received error response msg: ", aMsg.error);
-      return;}
-
+      return;
+    }
 
     // The recommended response to a ping message when the push server has nothing
     // else to send is a blank JSON message body: {}
     if (!aMsg.messageType && this.serviceState === SERVICE_STATE_ACTIVE) {
       // Treat this as a ping response
       this._pingMonitor.restart();
-      return;}
-
+      return;
+    }
 
     switch (aMsg.messageType) {
       case "hello":
         this._onHello(aMsg);
         break;
 
       case "register":
         this._onRegister(aMsg);
@@ -613,212 +613,214 @@ var MozLoopPushHandler = {
       case "notification":
         this._onNotification(aMsg);
         break;
 
       default:
         consoleLog.warn("PushHandler: unknown message type = ", aMsg.messageType);
         if (this.serviceState === SERVICE_STATE_ACTIVE) {
           // Treat this as a ping response
-          this._pingMonitor.restart();}
+          this._pingMonitor.restart();
+        }
+        break;}
 
-        break;}}, 
-
-
+  },
 
   /**
-   * Handles hello message.
-   *
-   * This method will parse the hello response from the PushServer
-   * and determine whether registration is necessary.
-   *
-   * @param {aMsg} hello message body
-   */
+      * Handles hello message.
+      *
+      * This method will parse the hello response from the PushServer
+      * and determine whether registration is necessary.
+      *
+      * @param {aMsg} hello message body
+      */
   _onHello: function _onHello(aMsg) {
     if (this.serviceState !== SERVICE_STATE_PENDING) {
       consoleLog.error("PushHandler: extra 'hello' response received from PushServer");
-      return;}
-
+      return;
+    }
 
     // Clear any pending timeout that will restart the connection.
     this._retryManager.reset();
     this.serviceState = SERVICE_STATE_ACTIVE;
     consoleLog.info("PushHandler: 'hello' handshake complete");
     // Start the PushServer ping monitor
     this._pingMonitor.restart();
     // If a new uaID is received, then any previous channel registrations
     // are no longer valid and a Registration request is generated.
     if (this.uaID !== aMsg.uaid) {
       consoleLog.log("PushHandler: registering all channels");
       this.uaID = aMsg.uaid;
       // Re-register all channels.
       this._channelsToRegister = [].concat(_toConsumableArray(this.channels.keys()));
-      this.registeredChannels = {};}
-
+      this.registeredChannels = {};
+    }
     // Allow queued registrations to start (or all if cleared above).
-    this._registerChannels();}, 
-
+    this._registerChannels();
+  },
 
   /**
-   * Handles notification message.
-   *
-   * This method will parse the Array of updates and trigger
-   * the callback of any registered channel.
-   * This method will construct an ack message containing
-   * a set of channel version update notifications.
-   *
-   * @param {aMsg} notification message body
-   */
+      * Handles notification message.
+      *
+      * This method will parse the Array of updates and trigger
+      * the callback of any registered channel.
+      * This method will construct an ack message containing
+      * a set of channel version update notifications.
+      *
+      * @param {aMsg} notification message body
+      */
   _onNotification: function _onNotification(aMsg) {var _this6 = this;
-    if (this.serviceState !== SERVICE_STATE_ACTIVE || 
+    if (this.serviceState !== SERVICE_STATE_ACTIVE ||
     this.registeredChannels.length === 0) {
       // Treat reception of a notification before handshake and registration
       // are complete as a fatal error.
       consoleLog.error("PushHandler: protocol error - notification received in wrong state");
       this._restartConnection();
-      return;}
-
+      return;
+    }
 
     this._pingMonitor.restart();
     if (Array.isArray(aMsg.updates) && aMsg.updates.length > 0) {(function () {
         var ackChannels = [];
         aMsg.updates.forEach(function (update) {
           if (update.channelID in _this6.registeredChannels) {
-            consoleLog.log("PushHandler: notification: version = ", update.version, 
+            consoleLog.log("PushHandler: notification: version = ", update.version,
             ", channelID = ", update.channelID);
             _this6.channels.get(update.channelID).
             onNotification(update.version, update.channelID);
-            ackChannels.push(update);} else 
-          {
-            consoleLog.error("PushHandler: notification received for unknown channelID: ", 
-            update.channelID);}});
-
-
+            ackChannels.push(update);
+          } else {
+            consoleLog.error("PushHandler: notification received for unknown channelID: ",
+            update.channelID);
+          }
+        });
 
         consoleLog.log("PushHandler: PusherServer 'ack': ", ackChannels);
-        _this6._pushSocket.send({ messageType: "ack", 
-          updates: ackChannels });})();}}, 
-
-
+        _this6._pushSocket.send({ messageType: "ack",
+          updates: ackChannels });})();
+    }
+  },
 
   /**
-   * Handles the PushServer registration response.
-   *
-   * @param {Object} msg PushServer to UserAgent registration response (parsed from JSON).
-   */
+      * Handles the PushServer registration response.
+      *
+      * @param {Object} msg PushServer to UserAgent registration response (parsed from JSON).
+      */
   _onRegister: function _onRegister(msg) {var _this7 = this;
-    if (this.serviceState !== SERVICE_STATE_ACTIVE || 
+    if (this.serviceState !== SERVICE_STATE_ACTIVE ||
     msg.channelID != this._pendingChannelID) {
       // Treat reception of a register response outside of a completed handshake
       // or for a channelID not currently pending a response
       // as an indication that the connections should be reset.
       consoleLog.error("PushHandler: registration protocol error");
       this._restartConnection();
-      return;}
-
+      return;
+    }
 
     this._retryManager.reset();
     this._pingMonitor.restart();
 
     switch (msg.status) {
       case 200:
         consoleLog.info("PushHandler: channel registered: ", msg.channelID);
         this.registeredChannels[msg.channelID] = msg.pushEndpoint;
         this.channels.get(msg.channelID).
         onRegistered(null, msg.pushEndpoint, msg.channelID);
         this._registerNext();
         break;
 
       case 500:
-        consoleLog.info("PushHandler: eeceived a 500 retry response from the PushServer: ", 
+        consoleLog.info("PushHandler: eeceived a 500 retry response from the PushServer: ",
         msg.channelID);
         // retry the registration request after a suitable delay
         this._retryManager.retry(function () {return _this7._sendRegistration(msg.channelID);});
         break;
 
       case 409:
-        consoleLog.error("PushHandler: received a 409 response from the PushServer: ", 
+        consoleLog.error("PushHandler: received a 409 response from the PushServer: ",
         msg.channelID);
         this.channels.get(this._pendingChannelID).onRegistered("409");
         // Remove this channel from the channel list.
         this.channels.delete(this._pendingChannelID);
         this._registerNext();
         break;
 
       default:
-        consoleLog.error("PushHandler: received error ", msg.status, 
+        consoleLog.error("PushHandler: received error ", msg.status,
         " from the PushServer: ", msg.channelID);
         this.channels.get(this._pendingChannelID).onRegistered(msg.status);
         this.channels.delete(this._pendingChannelID);
         this._registerNext();
-        break;}}, 
+        break;}
 
-
+  },
 
   /**
-   * Attempts to open a websocket.
-   *
-   * A new websocket interface is used each time. If an onStop callback
-   * was received, calling asyncOpen() on the same interface will
-   * trigger an "already open socket" exception even though the channel
-   * is logically closed.
-   */
+      * Attempts to open a websocket.
+      *
+      * A new websocket interface is used each time. If an onStop callback
+      * was received, calling asyncOpen() on the same interface will
+      * trigger an "already open socket" exception even though the channel
+      * is logically closed.
+      */
   _openSocket: function _openSocket() {var _this8 = this;
     this.connectionState = CONNECTION_STATE_CONNECTING;
     // For tests, use the mock instance.
     this._pushSocket = new PushSocket(this._mockWebSocket);
 
     consoleLog.info("PushHandler: attempt to open websocket to PushServer: ", this.pushServerUri);
-    this._pushSocket.connect(this.pushServerUri, 
-    function (aMsg) {return _this8._onMsg(aMsg);}, 
-    function () {return _this8._onStart();}, 
-    function (aCode, aReason) {return _this8._onClose(aCode, aReason);});}, 
+    this._pushSocket.connect(this.pushServerUri,
+    function (aMsg) {return _this8._onMsg(aMsg);},
+    function () {return _this8._onStart();},
+    function (aCode, aReason) {return _this8._onClose(aCode, aReason);});
 
-
+  },
 
   /**
-    * Closes websocket and begins re-establishing a connection with the PushServer
-    */
+       * Closes websocket and begins re-establishing a connection with the PushServer
+       */
   _restartConnection: function _restartConnection() {
     this._retryManager.reset();
     this._pingMonitor.stop();
     this.serviceState = SERVICE_STATE_OFFLINE;
     this._pendingChannelID = null;
 
     if (this.connectionState === CONNECTION_STATE_OPEN) {
       // Close the current PushSocket and start the operation to open a new one.
       this.connectionState = CONNECTION_STATE_CLOSED;
       this._pushSocket.close();
       consoleLog.warn("PushHandler: connection error: re-establishing connection to PushServer");
-      this._openSocket();}}, 
-
-
+      this._openSocket();
+    }
+  },
 
   /**
-   * Begins registering the channelIDs with the PushServer
-   */
+      * Begins registering the channelIDs with the PushServer
+      */
   _registerChannels: function _registerChannels() {
     // Hold off registration operation until handshake is complete.
     // If a registration cycle is in progress, do nothing.
-    if (this.serviceState !== SERVICE_STATE_ACTIVE || 
+    if (this.serviceState !== SERVICE_STATE_ACTIVE ||
     this._pendingChannelID) {
-      return;}
-
-    this._registerNext();}, 
-
+      return;
+    }
+    this._registerNext();
+  },
 
   /**
-   * Gets the next channel to register from the worklist and kicks of its registration
-   */
+      * Gets the next channel to register from the worklist and kicks of its registration
+      */
   _registerNext: function _registerNext() {
     this._pendingChannelID = this._channelsToRegister.pop();
-    this._sendRegistration(this._pendingChannelID);}, 
-
+    this._sendRegistration(this._pendingChannelID);
+  },
 
   /**
-   * Handles registering a service
-   *
-   * @param {string} channelID - identification token to use in registration for this channel.
-   */
+      * Handles registering a service
+      *
+      * @param {string} channelID - identification token to use in registration for this channel.
+      */
   _sendRegistration: function _sendRegistration(channelID) {
     if (channelID) {
-      this._pushSocket.send({ messageType: "register", 
-        channelID: channelID });}} };
+      this._pushSocket.send({ messageType: "register",
+        channelID: channelID });
+    }
+  } };
--- a/browser/extensions/loop/chrome/content/modules/MozLoopService.jsm
+++ b/browser/extensions/loop/chrome/content/modules/MozLoopService.jsm
@@ -1,1069 +1,1069 @@
 /* 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";var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {return typeof obj;} : function (obj) {return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;};function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}}var _Components = 
+"use strict";var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) {return typeof obj;} : function (obj) {return obj && typeof Symbol === "function" && obj.constructor === Symbol ? "symbol" : typeof obj;};function _toConsumableArray(arr) {if (Array.isArray(arr)) {for (var i = 0, arr2 = Array(arr.length); i < arr.length; i++) {arr2[i] = arr[i];}return arr2;} else {return Array.from(arr);}}var _Components =
 
 Components;var Ci = _Components.interfaces;var Cu = _Components.utils;var Cr = _Components.results;
 
-var LOOP_SESSION_TYPE = { 
-  GUEST: 1, 
+var LOOP_SESSION_TYPE = {
+  GUEST: 1,
   FXA: 2 };
 
 
 /**
- * Values that we segment sharing a room URL action telemetry probes into.
- *
- * @type {{COPY_FROM_PANEL: Number, COPY_FROM_CONVERSATION: Number,
- *    EMAIL_FROM_CALLFAILED: Number, EMAIL_FROM_CONVERSATION: Number,
- *    FACEBOOK_FROM_CONVERSATION: Number, EMAIL_FROM_PANEL: Number}}
- */
-var SHARING_ROOM_URL = { 
-  COPY_FROM_PANEL: 0, 
-  COPY_FROM_CONVERSATION: 1, 
-  EMAIL_FROM_CALLFAILED: 2, 
-  EMAIL_FROM_CONVERSATION: 3, 
-  FACEBOOK_FROM_CONVERSATION: 4, 
+             * Values that we segment sharing a room URL action telemetry probes into.
+             *
+             * @type {{COPY_FROM_PANEL: Number, COPY_FROM_CONVERSATION: Number,
+             *    EMAIL_FROM_CALLFAILED: Number, EMAIL_FROM_CONVERSATION: Number,
+             *    FACEBOOK_FROM_CONVERSATION: Number, EMAIL_FROM_PANEL: Number}}
+             */
+var SHARING_ROOM_URL = {
+  COPY_FROM_PANEL: 0,
+  COPY_FROM_CONVERSATION: 1,
+  EMAIL_FROM_CALLFAILED: 2,
+  EMAIL_FROM_CONVERSATION: 3,
+  FACEBOOK_FROM_CONVERSATION: 4,
   EMAIL_FROM_PANEL: 5 };
 
 
 /**
- * Values that we segment room create action telemetry probes into.
- *
- * @type {{CREATE_SUCCESS: Number, CREATE_FAIL: Number}}
- */
-var ROOM_CREATE = { 
-  CREATE_SUCCESS: 0, 
+                          * Values that we segment room create action telemetry probes into.
+                          *
+                          * @type {{CREATE_SUCCESS: Number, CREATE_FAIL: Number}}
+                          */
+var ROOM_CREATE = {
+  CREATE_SUCCESS: 0,
   CREATE_FAIL: 1 };
 
 
 /**
- * Values that we segment copy panel action telemetry probes into.
- *
- * @enum {Number}
- */
-var COPY_PANEL = { 
+                     * Values that we segment copy panel action telemetry probes into.
+                     *
+                     * @enum {Number}
+                     */
+var COPY_PANEL = {
   // Copy panel was shown to the user.
-  SHOWN: 0, 
+  SHOWN: 0,
   // User selected "no" and to allow the panel to show again.
-  NO_AGAIN: 1, 
+  NO_AGAIN: 1,
   // User selected "no" and to never show the panel.
-  NO_NEVER: 2, 
+  NO_NEVER: 2,
   // User selected "yes" and to allow the panel to show again.
-  YES_AGAIN: 3, 
+  YES_AGAIN: 3,
   // User selected "yes" and to never show the panel.
   YES_NEVER: 4 };
 
 
 /**
-* Values that we segment MAUs telemetry probes into.
-*
-* @type {{OPEN_PANEL: Number, OPEN_CONVERSATION: Number,
-*        ROOM_OPEN: Number, ROOM_SHARE: Number, ROOM_DELETE: Number}}
-*/
-var LOOP_MAU_TYPE = { 
-  OPEN_PANEL: 0, 
-  OPEN_CONVERSATION: 1, 
-  ROOM_OPEN: 2, 
-  ROOM_SHARE: 3, 
+                  * Values that we segment MAUs telemetry probes into.
+                  *
+                  * @type {{OPEN_PANEL: Number, OPEN_CONVERSATION: Number,
+                  *        ROOM_OPEN: Number, ROOM_SHARE: Number, ROOM_DELETE: Number}}
+                  */
+var LOOP_MAU_TYPE = {
+  OPEN_PANEL: 0,
+  OPEN_CONVERSATION: 1,
+  ROOM_OPEN: 2,
+  ROOM_SHARE: 3,
   ROOM_DELETE: 4 };
 
 
 // See LOG_LEVELS in Console.jsm. Common examples: "All", "Info", "Warn", & "Error".
 var PREF_LOG_LEVEL = "loop.debug.loglevel";
 
-var kChatboxHangupButton = { 
-  id: "loop-hangup", 
-  visibleWhenUndocked: false, 
+var kChatboxHangupButton = {
+  id: "loop-hangup",
+  visibleWhenUndocked: false,
   onCommand: function onCommand(e, chatbox) {
     var mm = chatbox.content.messageManager;
-    mm.sendAsyncMessage("Social:CustomEvent", { name: "LoopHangupNow" });} };
-
+    mm.sendAsyncMessage("Social:CustomEvent", { name: "LoopHangupNow" });
+  } };
 
 
 Cu.import("resource://gre/modules/Services.jsm");
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource://gre/modules/osfile.jsm", this);
 Cu.import("resource://gre/modules/Task.jsm");
 Cu.import("resource://gre/modules/Timer.jsm");
 Cu.import("resource://gre/modules/FxAccountsOAuthClient.jsm");
 
 Cu.importGlobalProperties(["URL"]);
 
-this.EXPORTED_SYMBOLS = ["MozLoopService", "LOOP_SESSION_TYPE", "LOOP_MAU_TYPE", 
+this.EXPORTED_SYMBOLS = ["MozLoopService", "LOOP_SESSION_TYPE", "LOOP_MAU_TYPE",
 "SHARING_ROOM_URL", "COPY_PANEL", "ROOM_CREATE"];
 
 XPCOMUtils.defineConstant(this, "LOOP_SESSION_TYPE", LOOP_SESSION_TYPE);
 XPCOMUtils.defineConstant(this, "SHARING_ROOM_URL", SHARING_ROOM_URL);
 XPCOMUtils.defineConstant(this, "COPY_PANEL", COPY_PANEL);
 XPCOMUtils.defineConstant(this, "ROOM_CREATE", ROOM_CREATE);
 XPCOMUtils.defineConstant(this, "LOOP_MAU_TYPE", LOOP_MAU_TYPE);
 
-XPCOMUtils.defineLazyModuleGetter(this, "LoopAPI", 
+XPCOMUtils.defineLazyModuleGetter(this, "LoopAPI",
 "chrome://loop/content/modules/MozLoopAPI.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "convertToRTCStatsReport", 
+XPCOMUtils.defineLazyModuleGetter(this, "convertToRTCStatsReport",
 "resource://gre/modules/media/RTCStatsReport.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "loopUtils", 
+XPCOMUtils.defineLazyModuleGetter(this, "loopUtils",
 "chrome://loop/content/modules/utils.js", "utils");
-XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto", 
+XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto",
 "chrome://loop/content/shared/js/crypto.js", "LoopCrypto");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Chat", "resource:///modules/Chat.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", 
+XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils",
 "resource://services-common/utils.js");
 
-XPCOMUtils.defineLazyModuleGetter(this, "CryptoUtils", 
+XPCOMUtils.defineLazyModuleGetter(this, "CryptoUtils",
 "resource://services-crypto/utils.js");
 
-XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsProfileClient", 
+XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsProfileClient",
 "resource://gre/modules/FxAccountsProfileClient.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "HawkClient", 
+XPCOMUtils.defineLazyModuleGetter(this, "HawkClient",
 "resource://services-common/hawkclient.js");
 
-XPCOMUtils.defineLazyModuleGetter(this, "deriveHawkCredentials", 
+XPCOMUtils.defineLazyModuleGetter(this, "deriveHawkCredentials",
 "resource://services-common/hawkrequest.js");
 
-XPCOMUtils.defineLazyModuleGetter(this, "LoopRooms", 
+XPCOMUtils.defineLazyModuleGetter(this, "LoopRooms",
 "chrome://loop/content/modules/LoopRooms.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "roomsPushNotification", 
+XPCOMUtils.defineLazyModuleGetter(this, "roomsPushNotification",
 "chrome://loop/content/modules/LoopRooms.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler", 
+XPCOMUtils.defineLazyModuleGetter(this, "MozLoopPushHandler",
 "chrome://loop/content/modules/MozLoopPushHandler.jsm");
 
-XPCOMUtils.defineLazyModuleGetter(this, "UITour", 
+XPCOMUtils.defineLazyModuleGetter(this, "UITour",
 "resource:///modules/UITour.jsm");
 
-XPCOMUtils.defineLazyServiceGetter(this, "uuidgen", 
-"@mozilla.org/uuid-generator;1", 
+XPCOMUtils.defineLazyServiceGetter(this, "uuidgen",
+"@mozilla.org/uuid-generator;1",
 "nsIUUIDGenerator");
 
-XPCOMUtils.defineLazyServiceGetter(this, "gDNSService", 
-"@mozilla.org/network/dns-service;1", 
+XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
+"@mozilla.org/network/dns-service;1",
 "nsIDNSService");
 
-XPCOMUtils.defineLazyServiceGetter(this, "gWM", 
-"@mozilla.org/appshell/window-mediator;1", 
+XPCOMUtils.defineLazyServiceGetter(this, "gWM",
+"@mozilla.org/appshell/window-mediator;1",
 "nsIWindowMediator");
 
 // Create a new instance of the ConsoleAPI so we can control the maxLogLevel with a pref.
 XPCOMUtils.defineLazyGetter(this, "log", function () {
   var ConsoleAPI = Cu.import("resource://gre/modules/Console.jsm", {}).ConsoleAPI;
-  var consoleOptions = { 
-    maxLogLevelPref: PREF_LOG_LEVEL, 
+  var consoleOptions = {
+    maxLogLevelPref: PREF_LOG_LEVEL,
     prefix: "Loop" };
 
-  return new ConsoleAPI(consoleOptions);});
-
+  return new ConsoleAPI(consoleOptions);
+});
 
 function setJSONPref(aName, aValue) {
   var value = aValue ? JSON.stringify(aValue) : "";
-  Services.prefs.setCharPref(aName, value);}
-
+  Services.prefs.setCharPref(aName, value);
+}
 
 function getJSONPref(aName) {
   var value = Services.prefs.getCharPref(aName);
-  return value ? JSON.parse(value) : null;}
-
+  return value ? JSON.parse(value) : null;
+}
 
 var gHawkClient = null;
 var gLocalizedStrings = new Map();
 var gFxAOAuthClientPromise = null;
 var gFxAOAuthClient = null;
 var gErrors = new Map();
 var gConversationWindowData = new Map();
 var gAddonVersion = "unknown";
 
 /**
- * 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.
- */
-var MozLoopServiceInternal = { 
-  conversationContexts: new Map(), 
-  pushURLs: new Map(), 
-
-  mocks: { 
-    pushHandler: undefined, 
-    isChatWindowOpen: undefined }, 
-
-
-  /**
-   * The current deferreds for the registration processes. This is set if in progress
-   * or the registration was successful. This is null if a registration attempt was
-   * unsuccessful.
-   */
-  deferredRegistrations: 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.
+                                */
+var MozLoopServiceInternal = {
+  conversationContexts: new Map(),
+  pushURLs: new Map(),
 
-  get pushHandler() {
-    return this.mocks.pushHandler || MozLoopPushHandler;}, 
-
-
-  // The uri of the Loop server.
-  get loopServerUri() {
-    return 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.
-   */
-  get initialRegistrationDelayMilliseconds() {
-    try {
-      // Let a pref override this for developer & testing use.
-      return Services.prefs.getIntPref("loop.initialDelay");} 
-    catch (x) {
-      // Default to 5 seconds
-      return 5000;}}, 
-
+  mocks: {
+    pushHandler: undefined,
+    isChatWindowOpen: undefined },
 
 
   /**
-   * Retrieves MozLoopService Firefox Accounts OAuth token.
-   *
-   * @return {Object} OAuth token
-   */
-  get fxAOAuthTokenData() {
-    return getJSONPref("loop.fxa_oauth.tokendata");}, 
+                                    * The current deferreds for the registration processes. This is set if in progress
+                                    * or the registration was successful. This is null if a registration attempt was
+                                    * unsuccessful.
+                                    */
+  deferredRegistrations: new Map(),
 
+  get pushHandler() {
+    return this.mocks.pushHandler || MozLoopPushHandler;
+  },
+
+  // The uri of the Loop server.
+  get loopServerUri() {
+    return Services.prefs.getCharPref("loop.server");
+  },
 
   /**
-   * Sets MozLoopService Firefox Accounts OAuth token.
-   * If the tokenData is being cleared, will also clear the
-   * profile since the profile is dependent on the token data.
-   *
-   * @param {Object} aTokenData OAuth token
-   */
+      * The initial delay for push registration. This ensures we don't start
+      * kicking off straight after browser startup, just a few seconds later.
+      */
+  get initialRegistrationDelayMilliseconds() {
+    try {
+      // Let a pref override this for developer & testing use.
+      return Services.prefs.getIntPref("loop.initialDelay");
+    } catch (x) {
+      // Default to 5 seconds
+      return 5000;
+    }
+  },
+
+  /**
+      * Retrieves MozLoopService Firefox Accounts OAuth token.
+      *
+      * @return {Object} OAuth token
+      */
+  get fxAOAuthTokenData() {
+    return getJSONPref("loop.fxa_oauth.tokendata");
+  },
+
+  /**
+      * Sets MozLoopService Firefox Accounts OAuth token.
+      * If the tokenData is being cleared, will also clear the
+      * profile since the profile is dependent on the token data.
+      *
+      * @param {Object} aTokenData OAuth token
+      */
   set fxAOAuthTokenData(aTokenData) {
     setJSONPref("loop.fxa_oauth.tokendata", aTokenData);
     if (!aTokenData) {
-      this.fxAOAuthProfile = null;}}, 
-
-
+      this.fxAOAuthProfile = null;
+    }
+  },
 
   /**
-   * Sets MozLoopService Firefox Accounts Profile data.
-   *
-   * @param {Object} aProfileData Profile data
-   */
+      * Sets MozLoopService Firefox Accounts Profile data.
+      *
+      * @param {Object} aProfileData Profile data
+      */
   set fxAOAuthProfile(aProfileData) {
     setJSONPref("loop.fxa_oauth.profile", aProfileData);
-    this.notifyStatusChanged(aProfileData ? "login" : undefined);}, 
-
+    this.notifyStatusChanged(aProfileData ? "login" : undefined);
+  },
 
   /**
-   * Retrieves MozLoopService "do not disturb" pref value.
-   *
-   * @return {Boolean} aFlag
-   */
+      * Retrieves MozLoopService "do not disturb" pref value.
+      *
+      * @return {Boolean} aFlag
+      */
   get doNotDisturb() {
-    return Services.prefs.getBoolPref("loop.do_not_disturb");}, 
-
+    return Services.prefs.getBoolPref("loop.do_not_disturb");
+  },
 
   /**
-   * Sets MozLoopService "do not disturb" pref value.
-   *
-   * @param {Boolean} aFlag
-   */
+      * Sets MozLoopService "do not disturb" pref value.
+      *
+      * @param {Boolean} aFlag
+      */
   set doNotDisturb(aFlag) {
     Services.prefs.setBoolPref("loop.do_not_disturb", Boolean(aFlag));
-    this.notifyStatusChanged();}, 
-
+    this.notifyStatusChanged();
+  },
 
   notifyStatusChanged: function notifyStatusChanged() {var aReason = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0];
     log.debug("notifyStatusChanged with reason:", aReason);
     var profile = MozLoopService.userProfile;
     LoopRooms.maybeRefresh(profile && profile.uid);
-    Services.obs.notifyObservers(null, "loop-status-changed", aReason);}, 
-
+    Services.obs.notifyObservers(null, "loop-status-changed", aReason);
+  },
 
   /**
-   * Record an error and notify interested UI with the relevant user-facing strings attached.
-   *
-   * @param {String} errorType a key to identify the type of error. Only one
-   *                           error of a type will be saved at a time. This value may be used to
-   *                           determine user-facing (aka. friendly) strings.
-   * @param {Object} error     an object describing the error in the format from Hawk errors
-   * @param {Function} [actionCallback] an object describing the label and callback function for error
-   *                                    bar's button e.g. to retry.
-   */
+      * Record an error and notify interested UI with the relevant user-facing strings attached.
+      *
+      * @param {String} errorType a key to identify the type of error. Only one
+      *                           error of a type will be saved at a time. This value may be used to
+      *                           determine user-facing (aka. friendly) strings.
+      * @param {Object} error     an object describing the error in the format from Hawk errors
+      * @param {Function} [actionCallback] an object describing the label and callback function for error
+      *                                    bar's button e.g. to retry.
+      */
   setError: function setError(errorType, error) {var actionCallback = arguments.length <= 2 || arguments[2] === undefined ? null : arguments[2];
     log.debug("setError", errorType, error);
     log.trace();
-    var messageString = void 0, detailsString = void 0, detailsButtonLabelString = void 0, detailsButtonCallback = void 0;
+    var messageString = void 0,detailsString = void 0,detailsButtonLabelString = void 0,detailsButtonCallback = void 0;
     var NETWORK_ERRORS = [
-    Cr.NS_ERROR_CONNECTION_REFUSED, 
-    Cr.NS_ERROR_NET_INTERRUPT, 
-    Cr.NS_ERROR_NET_RESET, 
-    Cr.NS_ERROR_NET_TIMEOUT, 
-    Cr.NS_ERROR_OFFLINE, 
-    Cr.NS_ERROR_PROXY_CONNECTION_REFUSED, 
-    Cr.NS_ERROR_UNKNOWN_HOST, 
+    Cr.NS_ERROR_CONNECTION_REFUSED,
+    Cr.NS_ERROR_NET_INTERRUPT,
+    Cr.NS_ERROR_NET_RESET,
+    Cr.NS_ERROR_NET_TIMEOUT,
+    Cr.NS_ERROR_OFFLINE,
+    Cr.NS_ERROR_PROXY_CONNECTION_REFUSED,
+    Cr.NS_ERROR_UNKNOWN_HOST,
     Cr.NS_ERROR_UNKNOWN_PROXY_HOST];
 
 
-    if (error.code === null && error.errno === null && 
-    error.error instanceof Ci.nsIException && 
+    if (error.code === null && error.errno === null &&
+    error.error instanceof Ci.nsIException &&
     NETWORK_ERRORS.indexOf(error.error.result) != -1) {
       // Network error. Override errorType so we can easily clear it on the next succesful request.
       errorType = "network";
       messageString = "could_not_connect";
       detailsString = "check_internet_connection";
-      detailsButtonLabelString = "retry_button";} else 
-    if (errorType == "profile" && error.code >= 500 && error.code < 600) {
-      messageString = "problem_accessing_account";} else 
-    if (error.code == 401) {
+      detailsButtonLabelString = "retry_button";
+    } else if (errorType == "profile" && error.code >= 500 && error.code < 600) {
+      messageString = "problem_accessing_account";
+    } else if (error.code == 401) {
       if (errorType == "login") {
         messageString = "could_not_authenticate"; // XXX: Bug 1076377
         detailsString = "password_changed_question";
         detailsButtonLabelString = "retry_button";
-        detailsButtonCallback = function detailsButtonCallback() {return MozLoopService.logInToFxA();};} else 
-      {
-        messageString = "session_expired_error_description";}} else 
-
-    if (error.code >= 500 && error.code < 600) {
+        detailsButtonCallback = function detailsButtonCallback() {return MozLoopService.logInToFxA();};
+      } else {
+        messageString = "session_expired_error_description";
+      }
+    } else if (error.code >= 500 && error.code < 600) {
       messageString = "service_not_available";
       detailsString = "try_again_later";