Bug 1287827 - Part 1. Remove Loop code from Firefox. rs=dmose,a=sledru
authorMark Banner <standard8@mozilla.com>
Tue, 26 Jul 2016 20:32:59 +0100
changeset 325635 183d4deab3e587d38075ffb3d81ae71d6f9adcc5
parent 325634 f3a3809acae60a936d6b09297bbac7c02dac00b0
child 325636 0b526a1650107bf212a217969a9ce9b568a7f7ef
push id9850
push usermbanner@mozilla.com
push dateSat, 30 Jul 2016 18:50:05 +0000
treeherdermozilla-aurora@77ab90179681 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersdmose, sledru
bugs1287827
milestone49.0a2
Bug 1287827 - Part 1. Remove Loop code from Firefox. rs=dmose,a=sledru
browser/extensions/loop/.gitignore
browser/extensions/loop/README.txt
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/conversation.html
browser/extensions/loop/chrome/content/panels/copy.html
browser/extensions/loop/chrome/content/panels/css/copy.css
browser/extensions/loop/chrome/content/panels/css/desktop.css
browser/extensions/loop/chrome/content/panels/css/panel.css
browser/extensions/loop/chrome/content/panels/css/slideshow.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/panel.html
browser/extensions/loop/chrome/content/panels/slideshow.html
browser/extensions/loop/chrome/content/panels/test/.eslintrc
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/index.html
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/test/test_desktop_all.py
browser/extensions/loop/chrome/content/panels/vendor/l10n.js
browser/extensions/loop/chrome/content/panels/vendor/simpleSlideshow.css
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/css/conversation.css
browser/extensions/loop/chrome/content/shared/css/reset.css
browser/extensions/loop/chrome/content/shared/img/02.png
browser/extensions/loop/chrome/content/shared/img/02@2x.png
browser/extensions/loop/chrome/content/shared/img/animated-spinner.svg
browser/extensions/loop/chrome/content/shared/img/arrow-01.svg
browser/extensions/loop/chrome/content/shared/img/audio-call-avatar.svg
browser/extensions/loop/chrome/content/shared/img/audio-default-16x16@1.5x.png
browser/extensions/loop/chrome/content/shared/img/audio-default-16x16@2x.png
browser/extensions/loop/chrome/content/shared/img/audio-hover.svg
browser/extensions/loop/chrome/content/shared/img/audio-mute-hover.svg
browser/extensions/loop/chrome/content/shared/img/audio-mute.svg
browser/extensions/loop/chrome/content/shared/img/audio-muted-darkgrey.svg
browser/extensions/loop/chrome/content/shared/img/audio.svg
browser/extensions/loop/chrome/content/shared/img/avatars.svg
browser/extensions/loop/chrome/content/shared/img/beta-ribbon.svg
browser/extensions/loop/chrome/content/shared/img/cam_audio-no.svg
browser/extensions/loop/chrome/content/shared/img/cam_audio.svg
browser/extensions/loop/chrome/content/shared/img/cam_audio_h.svg
browser/extensions/loop/chrome/content/shared/img/chatbubble-arrow-left.svg
browser/extensions/loop/chrome/content/shared/img/chatbubble-arrow-right.svg
browser/extensions/loop/chrome/content/shared/img/check.svg
browser/extensions/loop/chrome/content/shared/img/close-02.svg
browser/extensions/loop/chrome/content/shared/img/cursor.svg
browser/extensions/loop/chrome/content/shared/img/ellipsis-v.svg
browser/extensions/loop/chrome/content/shared/img/empty_search.svg
browser/extensions/loop/chrome/content/shared/img/exit.svg
browser/extensions/loop/chrome/content/shared/img/facemute-14x14.png
browser/extensions/loop/chrome/content/shared/img/facemute-14x14@2x.png
browser/extensions/loop/chrome/content/shared/img/firefox-avatar.svg
browser/extensions/loop/chrome/content/shared/img/firefox-hello_logo.svg
browser/extensions/loop/chrome/content/shared/img/firefox-hello_tour-slide-01.svg
browser/extensions/loop/chrome/content/shared/img/firefox-hello_tour-slide-02.svg
browser/extensions/loop/chrome/content/shared/img/firefox-hello_tour-slide-03.svg
browser/extensions/loop/chrome/content/shared/img/firefox-hello_tour-slide-04.svg
browser/extensions/loop/chrome/content/shared/img/firefox-logo.png
browser/extensions/loop/chrome/content/shared/img/glyph-email-16x16.svg
browser/extensions/loop/chrome/content/shared/img/glyph-facebook-16x16.svg
browser/extensions/loop/chrome/content/shared/img/glyph-help-16x16.svg
browser/extensions/loop/chrome/content/shared/img/glyph-help-no-circle-16x16.svg
browser/extensions/loop/chrome/content/shared/img/glyph-help-no-circle-blue-16x16.svg
browser/extensions/loop/chrome/content/shared/img/glyph-link-16x16.svg
browser/extensions/loop/chrome/content/shared/img/glyph-user-16x16.svg
browser/extensions/loop/chrome/content/shared/img/hangup-inverse-14x14.png
browser/extensions/loop/chrome/content/shared/img/hangup-inverse-14x14@2x.png
browser/extensions/loop/chrome/content/shared/img/happy.png
browser/extensions/loop/chrome/content/shared/img/hello-web-share.svg
browser/extensions/loop/chrome/content/shared/img/hello_logo.svg
browser/extensions/loop/chrome/content/shared/img/helloicon.svg
browser/extensions/loop/chrome/content/shared/img/icon_32.png
browser/extensions/loop/chrome/content/shared/img/icon_64.png
browser/extensions/loop/chrome/content/shared/img/icons-10x10.svg
browser/extensions/loop/chrome/content/shared/img/icons-14x14.svg
browser/extensions/loop/chrome/content/shared/img/icons-16x16.svg
browser/extensions/loop/chrome/content/shared/img/join_notification.svg
browser/extensions/loop/chrome/content/shared/img/leave.svg
browser/extensions/loop/chrome/content/shared/img/leave_notification.svg
browser/extensions/loop/chrome/content/shared/img/media-group-left-hover.svg
browser/extensions/loop/chrome/content/shared/img/media-group-right-hover.svg
browser/extensions/loop/chrome/content/shared/img/media-group.svg
browser/extensions/loop/chrome/content/shared/img/movistar.png
browser/extensions/loop/chrome/content/shared/img/movistar@2x.png
browser/extensions/loop/chrome/content/shared/img/mute-inverse-14x14.png
browser/extensions/loop/chrome/content/shared/img/mute-inverse-14x14@2x.png
browser/extensions/loop/chrome/content/shared/img/pause-12x12.svg
browser/extensions/loop/chrome/content/shared/img/paused-hello.svg
browser/extensions/loop/chrome/content/shared/img/play-12x12.svg
browser/extensions/loop/chrome/content/shared/img/sad.png
browser/extensions/loop/chrome/content/shared/img/sad_hello_icon_64x64.svg
browser/extensions/loop/chrome/content/shared/img/settings-hover.svg
browser/extensions/loop/chrome/content/shared/img/settings.svg
browser/extensions/loop/chrome/content/shared/img/sharing-active.svg
browser/extensions/loop/chrome/content/shared/img/sharing-hover.svg
browser/extensions/loop/chrome/content/shared/img/sharing-pending.svg
browser/extensions/loop/chrome/content/shared/img/sharing.svg
browser/extensions/loop/chrome/content/shared/img/spinner.png
browser/extensions/loop/chrome/content/shared/img/spinner.svg
browser/extensions/loop/chrome/content/shared/img/spinner@2x.png
browser/extensions/loop/chrome/content/shared/img/stop-12x12.svg
browser/extensions/loop/chrome/content/shared/img/telefonica-logo.svg
browser/extensions/loop/chrome/content/shared/img/video-hover.svg
browser/extensions/loop/chrome/content/shared/img/video-mute-hover.svg
browser/extensions/loop/chrome/content/shared/img/video-mute.svg
browser/extensions/loop/chrome/content/shared/img/video-muted-darkgrey.svg
browser/extensions/loop/chrome/content/shared/img/video.svg
browser/extensions/loop/chrome/content/shared/img/vivo.png
browser/extensions/loop/chrome/content/shared/img/vivo@2x.png
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/sounds/connected.ogg
browser/extensions/loop/chrome/content/shared/sounds/connecting.ogg
browser/extensions/loop/chrome/content/shared/sounds/failure.ogg
browser/extensions/loop/chrome/content/shared/sounds/message.ogg
browser/extensions/loop/chrome/content/shared/sounds/room-joined-in.ogg
browser/extensions/loop/chrome/content/shared/sounds/room-joined.ogg
browser/extensions/loop/chrome/content/shared/sounds/room-left.ogg
browser/extensions/loop/chrome/content/shared/sounds/terminated.ogg
browser/extensions/loop/chrome/content/shared/test/.eslintrc
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/frontend_tester.py
browser/extensions/loop/chrome/content/shared/test/index.html
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/test_shared_all.py
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/vendor/chai-as-promised.js
browser/extensions/loop/chrome/content/shared/test/vendor/chai.js
browser/extensions/loop/chrome/content/shared/test/vendor/mocha.css
browser/extensions/loop/chrome/content/shared/test/vendor/mocha.js
browser/extensions/loop/chrome/content/shared/test/vendor/react-dom-server.js
browser/extensions/loop/chrome/content/shared/test/vendor/sinon.js
browser/extensions/loop/chrome/content/shared/test/views_test.js
browser/extensions/loop/chrome/content/shared/vendor/backbone.js
browser/extensions/loop/chrome/content/shared/vendor/classnames.js
browser/extensions/loop/chrome/content/shared/vendor/lodash.js
browser/extensions/loop/chrome/content/shared/vendor/react-dom-prod.js
browser/extensions/loop/chrome/content/shared/vendor/react-dom.js
browser/extensions/loop/chrome/content/shared/vendor/react-prod.js
browser/extensions/loop/chrome/content/shared/vendor/react.js
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/css/ot.css
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/access-denied-chrome.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/access-denied-copy-firefox.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/access-denied-firefox.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/access-predenied-chrome.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/access-prompt-chrome.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/audioonly-publisher.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/audioonly-subscriber.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/buttons.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/loader.gif
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/mic-off.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/mic-on.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/speaker-off.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/speaker-on.png
browser/extensions/loop/chrome/content/shared/vendor/sdk-content/js/dynamic_config.min.js
browser/extensions/loop/chrome/content/shared/vendor/sdk.js
browser/extensions/loop/chrome/locale/af/loop.properties
browser/extensions/loop/chrome/locale/ar/loop.properties
browser/extensions/loop/chrome/locale/as/loop.properties
browser/extensions/loop/chrome/locale/ast/loop.properties
browser/extensions/loop/chrome/locale/az/loop.properties
browser/extensions/loop/chrome/locale/be/loop.properties
browser/extensions/loop/chrome/locale/bg/loop.properties
browser/extensions/loop/chrome/locale/bn-BD/loop.properties
browser/extensions/loop/chrome/locale/bn-IN/loop.properties
browser/extensions/loop/chrome/locale/bs/loop.properties
browser/extensions/loop/chrome/locale/ca/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/el/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/eo/loop.properties
browser/extensions/loop/chrome/locale/es-AR/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/eu/loop.properties
browser/extensions/loop/chrome/locale/fa/loop.properties
browser/extensions/loop/chrome/locale/ff/loop.properties
browser/extensions/loop/chrome/locale/fi/loop.properties
browser/extensions/loop/chrome/locale/fr/loop.properties
browser/extensions/loop/chrome/locale/fy-NL/loop.properties
browser/extensions/loop/chrome/locale/fy/loop.properties
browser/extensions/loop/chrome/locale/ga/loop.properties
browser/extensions/loop/chrome/locale/gd/loop.properties
browser/extensions/loop/chrome/locale/gl/loop.properties
browser/extensions/loop/chrome/locale/gu-IN/loop.properties
browser/extensions/loop/chrome/locale/he/loop.properties
browser/extensions/loop/chrome/locale/hi-IN/loop.properties
browser/extensions/loop/chrome/locale/hr/loop.properties
browser/extensions/loop/chrome/locale/hsb/loop.properties
browser/extensions/loop/chrome/locale/ht/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/jar.mn
browser/extensions/loop/chrome/locale/kk/loop.properties
browser/extensions/loop/chrome/locale/km/loop.properties
browser/extensions/loop/chrome/locale/kn/loop.properties
browser/extensions/loop/chrome/locale/ko/loop.properties
browser/extensions/loop/chrome/locale/ku/loop.properties
browser/extensions/loop/chrome/locale/lij/loop.properties
browser/extensions/loop/chrome/locale/lt/loop.properties
browser/extensions/loop/chrome/locale/lv/loop.properties
browser/extensions/loop/chrome/locale/mk/loop.properties
browser/extensions/loop/chrome/locale/ml/loop.properties
browser/extensions/loop/chrome/locale/mn/loop.properties
browser/extensions/loop/chrome/locale/moz.build
browser/extensions/loop/chrome/locale/ms/loop.properties
browser/extensions/loop/chrome/locale/my/loop.properties
browser/extensions/loop/chrome/locale/nb-NO/loop.properties
browser/extensions/loop/chrome/locale/ne-NP/loop.properties
browser/extensions/loop/chrome/locale/nl/loop.properties
browser/extensions/loop/chrome/locale/nn-NO/loop.properties
browser/extensions/loop/chrome/locale/or/loop.properties
browser/extensions/loop/chrome/locale/pa-IN/loop.properties
browser/extensions/loop/chrome/locale/pa/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/pt/loop.properties
browser/extensions/loop/chrome/locale/rm/loop.properties
browser/extensions/loop/chrome/locale/ro/loop.properties
browser/extensions/loop/chrome/locale/ru/loop.properties
browser/extensions/loop/chrome/locale/si/loop.properties
browser/extensions/loop/chrome/locale/sk/loop.properties
browser/extensions/loop/chrome/locale/sl/loop.properties
browser/extensions/loop/chrome/locale/son/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/ta/loop.properties
browser/extensions/loop/chrome/locale/te/loop.properties
browser/extensions/loop/chrome/locale/th/loop.properties
browser/extensions/loop/chrome/locale/tr/loop.properties
browser/extensions/loop/chrome/locale/uk/loop.properties
browser/extensions/loop/chrome/locale/ur/loop.properties
browser/extensions/loop/chrome/locale/vi/loop.properties
browser/extensions/loop/chrome/locale/xh/loop.properties
browser/extensions/loop/chrome/locale/zh-CN/loop.properties
browser/extensions/loop/chrome/locale/zh-TW/loop.properties
browser/extensions/loop/chrome/locale/zu/loop.properties
browser/extensions/loop/chrome/skin/linux/menuPanel.png
browser/extensions/loop/chrome/skin/linux/menuPanel@2x.png
browser/extensions/loop/chrome/skin/linux/platform.css
browser/extensions/loop/chrome/skin/linux/toolbar-inverted.png
browser/extensions/loop/chrome/skin/linux/toolbar-inverted@2x.png
browser/extensions/loop/chrome/skin/linux/toolbar.png
browser/extensions/loop/chrome/skin/linux/toolbar@2x.png
browser/extensions/loop/chrome/skin/osx/menuPanel-yosemite.png
browser/extensions/loop/chrome/skin/osx/menuPanel-yosemite@2x.png
browser/extensions/loop/chrome/skin/osx/menuPanel.png
browser/extensions/loop/chrome/skin/osx/menuPanel@2x.png
browser/extensions/loop/chrome/skin/osx/platform.css
browser/extensions/loop/chrome/skin/osx/toolbar-inverted.png
browser/extensions/loop/chrome/skin/osx/toolbar-inverted@2x.png
browser/extensions/loop/chrome/skin/osx/toolbar-yosemite.png
browser/extensions/loop/chrome/skin/osx/toolbar-yosemite@2x.png
browser/extensions/loop/chrome/skin/osx/toolbar.png
browser/extensions/loop/chrome/skin/osx/toolbar@2x.png
browser/extensions/loop/chrome/skin/shared/loop.css
browser/extensions/loop/chrome/skin/windows/menuPanel-aero.png
browser/extensions/loop/chrome/skin/windows/menuPanel-aero@2x.png
browser/extensions/loop/chrome/skin/windows/menuPanel.png
browser/extensions/loop/chrome/skin/windows/menuPanel@2x.png
browser/extensions/loop/chrome/skin/windows/platform.css
browser/extensions/loop/chrome/skin/windows/toolbar-XP.png
browser/extensions/loop/chrome/skin/windows/toolbar-XP@2x.png
browser/extensions/loop/chrome/skin/windows/toolbar-aero.png
browser/extensions/loop/chrome/skin/windows/toolbar-aero@2x.png
browser/extensions/loop/chrome/skin/windows/toolbar-inverted.png
browser/extensions/loop/chrome/skin/windows/toolbar-inverted@2x.png
browser/extensions/loop/chrome/skin/windows/toolbar-lunaSilver.png
browser/extensions/loop/chrome/skin/windows/toolbar-lunaSilver@2x.png
browser/extensions/loop/chrome/skin/windows/toolbar-win8.png
browser/extensions/loop/chrome/skin/windows/toolbar-win8@2x.png
browser/extensions/loop/chrome/skin/windows/toolbar.png
browser/extensions/loop/chrome/skin/windows/toolbar@2x.png
browser/extensions/loop/chrome/test/mochitest/.eslintrc
browser/extensions/loop/chrome/test/mochitest/browser.ini
browser/extensions/loop/chrome/test/mochitest/browser_LoopRooms_channel.js
browser/extensions/loop/chrome/test/mochitest/browser_copypanel.js
browser/extensions/loop/chrome/test/mochitest/browser_fxa_login.js
browser/extensions/loop/chrome/test/mochitest/browser_loop_fxa_server.js
browser/extensions/loop/chrome/test/mochitest/browser_menuitem.js
browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_appVersionInfo.js
browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_chat.js
browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_context.js
browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_infobar.js
browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_sharingListeners.js
browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_telemetry.js
browser/extensions/loop/chrome/test/mochitest/browser_panel_privateBrowsing.js
browser/extensions/loop/chrome/test/mochitest/browser_sharingTitleListeners.js
browser/extensions/loop/chrome/test/mochitest/browser_throttler.js
browser/extensions/loop/chrome/test/mochitest/browser_toolbarbutton.js
browser/extensions/loop/chrome/test/mochitest/head.js
browser/extensions/loop/chrome/test/mochitest/loop_fxa.sjs
browser/extensions/loop/chrome/test/mochitest/test_loopLinkClicker_channel.html
browser/extensions/loop/chrome/test/xpcshell/.eslintrc
browser/extensions/loop/chrome/test/xpcshell/head.js
browser/extensions/loop/chrome/test/xpcshell/test_loopapi_app_version.js
browser/extensions/loop/chrome/test/xpcshell/test_loopapi_doNotDisturb.js
browser/extensions/loop/chrome/test/xpcshell/test_loopapi_ftu_url.js
browser/extensions/loop/chrome/test/xpcshell/test_loopapi_internal.js
browser/extensions/loop/chrome/test/xpcshell/test_loopapi_prefs.js
browser/extensions/loop/chrome/test/xpcshell/test_looppush_initialize.js
browser/extensions/loop/chrome/test/xpcshell/test_looprooms.js
browser/extensions/loop/chrome/test/xpcshell/test_looprooms_encryption_in_fxa.js
browser/extensions/loop/chrome/test/xpcshell/test_looprooms_first_notification.js
browser/extensions/loop/chrome/test/xpcshell/test_looprooms_getall.js
browser/extensions/loop/chrome/test/xpcshell/test_looprooms_upgrade_to_encryption.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_dnd.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_encryptionkey.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_hawk_errors.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_hawk_request.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_initialize.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_locales.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_loop_prefs.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_registration.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_registration_retry.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_restart.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_token_invalid.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_token_save.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_token_send.js
browser/extensions/loop/chrome/test/xpcshell/test_loopservice_token_validation.js
browser/extensions/loop/chrome/test/xpcshell/xpcshell.ini
browser/extensions/loop/install.rdf.in
browser/extensions/loop/jar.mn
browser/extensions/loop/manifest.ini
browser/extensions/loop/moz.build
browser/extensions/loop/run-all-loop-tests.sh
browser/extensions/loop/test/functional/config.py
browser/extensions/loop/test/functional/hanging_threads.py
browser/extensions/loop/test/functional/loopTestDriver.py
browser/extensions/loop/test/functional/manifest.ini
browser/extensions/loop/test/functional/serversetup.py
browser/extensions/loop/test/functional/test_1_browser_call.py
browser/extensions/loop/test/functional/test_2_linkclicker.py
deleted file mode 100644
--- a/browser/extensions/loop/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-.module-cache
-test/coverage/desktop
-test/coverage/shared_standalone
-test/node_modules
-test/visual-regression/diff
-test/visual-regression/new
-test/visual-regression/refs
deleted file mode 100644
--- a/browser/extensions/loop/README.txt
+++ /dev/null
@@ -1,3 +0,0 @@
-This is the loop project output, https://github.com/mozilla/loop
-
-Current extension version is: 0.1
deleted file mode 100644
--- a/browser/extensions/loop/bootstrap.js
+++ /dev/null
@@ -1,1495 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";
-
-/* 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;
-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", 
-"resource://gre/modules/PrivateBrowsingUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "CustomizableUI", 
-"resource:///modules/CustomizableUI.jsm");
-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, 
-    prefix: "Loop" };
-
-  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 = { 
-  // Records the add-on version once we know it.
-  addonVersion: "unknown", 
-
-  /**
-   * 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 
-    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 {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);}, 
-
-
-      /**
-       * @var {XULElement} panel Getter for the Loop panel element.
-       */
-      get panel() {
-        delete this.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.
-       */
-      get browser() {
-        var browser = document.querySelector("#loop-notification-panel > #loop-panel-iframe");
-        if (browser) {
-          delete this.browser;
-          this.browser = browser;}
-
-        return browser;}, 
-
-
-      get isSlideshowOpen() {
-        return isSlideshowOpen;}, 
-
-
-      set isSlideshowOpen(aOpen) {
-        isSlideshowOpen = aOpen;
-        this.updateToolbarState();}, 
-
-      /**
-       * @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" }, 
-          function (result) {
-            _this._constants = result;});}
-
-
-
-        return this._constants;}, 
-
-
-      get mm() {
-        return window.getGroupMessageManager("browsers");}, 
-
-
-      /**
-       * @return {Promise}
-       */
-      promiseDocumentVisible: function promiseDocumentVisible(aDocument) {
-        if (!aDocument.hidden) {
-          return Promise.resolve(aDocument);}
-
-
-        return new Promise(function (resolve) {
-          aDocument.addEventListener("visibilitychange", function onVisibilityChanged() {
-            aDocument.removeEventListener("visibilitychange", onVisibilityChanged);
-            resolve(aDocument);});});}, 
-
-
-
-
-      /**
-       * 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);};
-
-            Services.obs.addObserver(obs, "browser-delayed-startup-finished", false);
-            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();});}
-
-
-
-        if (this.isSlideshowOpen) {
-          return Promise.resolve();}
-
-
-        return this.openPanel(event).then(function (mm) {
-          if (mm) {
-            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
-       */
-      renameRoom: function renameRoom() {
-        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}
-       */
-      openPanel: function openPanel(event) {var _this3 = this;
-        if (PrivateBrowsingUtils.isWindowPrivate(window)) {
-          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;}
-
-
-            if (!_this3._panelInitialized) {
-              _this3.hookWindowCloseForPanelClose(iframe);
-              _this3._panelInitialized = true;}
-
-
-            mm.sendAsyncMessage("Social:WaitForDocumentVisible");
-            mm.addMessageListener("Social:DocumentVisible", function onDocumentVisible() {
-              mm.removeMessageListener("Social:DocumentVisible", onDocumentVisible);
-              resolve(mm);});
-
-
-            var buckets = _this3.constants.LOOP_MAU_TYPE;
-            _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;}
-
-
-            _this3.LoopAPI.initialize();
-
-            var anchor = event ? event.target : _this3.toolbarButton.anchor;
-            _this3.PanelFrame.showPopup(
-            window, 
-            anchor, 
-            "loop", // Notification Panel Type
-            null, // Origin
-            "about:looppanel", // Source
-            null, // Size
-            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}
-       */
-      openCallPanel: function openCallPanel(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.
-       */
-      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;}
-
-
-        if (!this.LoopRooms.participantsCount) {
-          // Nobody is in the rooms
-          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 true;}), 
-
-
-      /**
-       * @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;}
-
-                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);});});}, 
-
-
-
-
-      /**
-       * 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") && 
-          !ex.message.contains("not needed")) {
-            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;}
-
-
-        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;}
-
-
-        // 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.addObserver(this, "loop-status-changed", false);
-
-        this.maybeAddCopyPanel();
-        this.updateToolbarState();}, 
-
-
-      /**
-       * 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;}
-
-
-        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"));}, 
-
-
-      /**
-       * Removes the menu item from the browsers' Tools menu.
-       */
-      removeMenuItem: function removeMenuItem() {
-        if (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.
-       */
-      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") || 
-        Services.prefs.getIntPref("loop.copy.showLimit") <= 0) {
-          return Promise.resolve();}
-
-
-        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;
-        // 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" });};
-
-
-
-        // 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";});
-
-
-            // 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();}
-
-
-              // Stop showing the panel if the user says so.
-              if (stop) {
-                LoopUI.removeCopyPanel();
-                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) {
-                // 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;}
-
-
-          // Don't bother prompting the user if already sharing.
-          if (_this8.MozLoopService.screenShareActive) {
-            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);};}, 
-
-
-
-      /**
-       * 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;}
-
-
-        var copy = document.getElementById("loop-copy-notification-panel");
-        if (copy) {
-          copy.parentNode.removeChild(copy);}}, 
-
-
-
-      // Implements nsIObserver
-      observe: function observe(subject, topic, data) {
-        if (topic != "loop-status-changed") {
-          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.
-       */
-      updateToolbarState: function updateToolbarState() {var _this9 = this;var aReason = arguments.length <= 0 || arguments[0] === undefined ? null : arguments[0];
-        if (!this.toolbarButton.node) {
-          return;}
-
-        var state = "";
-        var mozL10nId = "loop-call-button3";
-        var suffix = ".tooltiptext";
-        if (this.MozLoopService.errors.size) {
-          state = "error";
-          mozL10nId += "-error";} else 
-        if (this.isSlideshowOpen) {
-          state = "slideshow";
-          suffix = ".label";} else 
-        if (this.MozLoopService.screenShareActive) {
-          state = "action";
-          mozL10nId += "-screensharing";} else 
-        if (aReason == "login" && this.MozLoopService.userProfile) {
-          state = "active";
-          mozL10nId += "-active";
-          suffix += "2";} else 
-        if (this.MozLoopService.doNotDisturb) {
-          state = "disabled";
-          mozL10nId += "-donotdisturb";} else 
-        if (this.MozLoopService.roomsParticipantsCount > 0) {
-          state = "active";
-          this.roomsWithNonOwners().then(function (roomsWithNonOwners) {
-            if (roomsWithNonOwners.length > 0) {
-              mozL10nId += "-participantswaiting";} else 
-            {
-              mozL10nId += "-active";}
-
-
-            suffix += "2";
-            _this9.updateTooltiptext(mozL10nId + suffix);
-            _this9.toolbarButton.node.setAttribute("state", state);});
-
-          return;} else 
-        {
-          suffix += "2";}
-
-
-        this.toolbarButton.node.setAttribute("state", state);
-        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.
-       */
-      updateTooltiptext: function updateTooltiptext(mozL10nId) {
-        this.toolbarButton.node.setAttribute("tooltiptext", mozL10nId);
-        var tooltiptext = CustomizableUI.getLocalizedProperty(this.toolbarButton, "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.
-       */
-      showNotification: function showNotification(options) {var _this10 = this;
-        if (this.MozLoopService.doNotDisturb) {
-          return;}
-
-
-        if (!options.title) {
-          throw new Error("Missing title, can not display notification");}
-
-
-        var notificationOptions = { 
-          body: options.message || "" };
-
-        if (options.icon) {
-          notificationOptions.icon = options.icon;}
-
-        if (options.sound) {
-          // This will not do anything, until bug bug 1105222 is resolved.
-          notificationOptions.mozbehavior = { 
-            soundFile: "" };
-
-          this.playSound(options.sound);}
-
-
-        var notification = new window.Notification(options.title, notificationOptions);
-        notification.addEventListener("click", function () {
-          if (window.closed) {
-            return;}
-
-
-          try {
-            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 
-            {
-              // Open the Loop panel as a default action.
-              _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'
-       */
-      playSound: function playSound(name) {var _this11 = this;
-        if (this.ActiveSound || this.MozLoopService.doNotDisturb) {
-          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);}, 
-
-
-      /**
-       * 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", 
-          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);}
-
-
-        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;}
-
-
-          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));});}, 
-
-
-      /**
-       * Stop listening to selected tab changes.
-       */
-      stopBrowserSharing: function stopBrowserSharing() {
-        if (!this._listeningToTabSelect) {
-          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", 
-          titleChangedListener);
-          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;}, 
-
-
-      /**
-       *  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;}
-
-
-        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);}
-
-
-        // Update the cursor's position with CSS.
-        cursor.style.left = 
-        Math.abs(cursorData.ratioX * browser.boxObject.width) + "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
-       */
-      clickRemoteCursor: function clickRemoteCursor(clickData) {
-        if (!clickData || !this._listeningToTabSelect) {
-          return;}
-
-
-        var class_name = "clicked";
-        var cursor = document.getElementById("loop-remote-cursor");
-        if (!cursor) {
-          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);}, 
-
-
-      /**
-       *  Removes the remote cursor from the screen
-       */
-      removeRemoteCursor: function removeRemoteCursor() {
-        var cursor = document.getElementById("loop-remote-cursor");
-
-        if (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}
-       */
-      _getString: function _getString(key) {
-        var str = this.MozLoopService.getStrings(key);
-        if (str) {
-          str = JSON.parse(str).textContent;}
-
-        return str;}, 
-
-
-      /**
-       * 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 
-
-        {
-          // Just the owner in the room.
-          message = this._getString(
-          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 };}, 
-
-
-      /**
-       * 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: {}, 
-
-      /**
-       * 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;}, 
-
-
-      /**
-       * 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 && 
-          this._browserSharePaused === this._lastNotification.paused) {
-            return;}
-
-
-          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, 
-          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;}, 
-
-          type: "pause" }, 
-
-        { 
-          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();}, 
-
-          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;}, 
-
-
-      /**
-       * 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;}
-
-
-        return removed;}, 
-
-
-      /**
-       * Broadcast 'BrowserSwitch' event.
-       */
-      _notifyBrowserSwitch: function _notifyBrowserSwitch() {
-        // Get the first window Id for the listener.
-        this.LoopAPI.broadcastPushMessage("BrowserSwitch", 
-        gBrowser.selectedBrowser.outerWindowID);}, 
-
-
-      /**
-       * 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);}, 
-
-
-      /**
-       * 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;}
-
-
-        if (gBrowser.selectedBrowser == message.target) {
-          // Get the new title of the shared tab
-          this._notifyBrowserSwitch();}}, 
-
-
-
-      /**
-       * 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();}
-
-
-              // 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;}
-
-          case "mousemove":
-            this.handleMousemove(event);
-            break;
-          case "click":
-            this.handleMouseClick(event);
-            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.
-       */
-      handleMousemove: function handleMousemove(event) {
-        // Won't send events if not sharing (paused or not started).
-        if (this._browserSharePaused || !this._listeningToTabSelect) {
-          return;}
-
-
-        // Only update every so often.
-        var now = Date.now();
-        if (now - this.lastCursorTime < CURSOR_MIN_INTERVAL) {
-          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 && 
-        Math.abs(deltaY - this.lastCursorY) < CURSOR_MIN_DELTA) {
-          return;}
-
-        this.lastCursorX = deltaX;
-        this.lastCursorY = deltaY;
-
-        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.
-       */
-      handleMouseClick: function handleMouseClick() {
-        // We want to stop sending events if sharing is paused.
-        if (this._browserSharePaused) {
-          return;}
-
-
-        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.
-       */
-      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;}
-
-
-        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;}
-
-
-            var reader = new FileReader();
-            reader.onload = reader.onload = function () {return callback(null, reader.result);};
-            reader.onerror = callback;
-            reader.readAsDataURL(xhr.response);};
-
-          xhr.onerror = callback;
-          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;}, 
-
-
-  /**
-   * 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);}, 
-
-
-  onCloseWindow: function onCloseWindow() {}, 
-
-
-  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 = { 
-  // Each 8-bit block of the IP address allows for 0% rollout (value 0) to 100%
-  // rollout (value 255).
-  TICKET_LIMIT: 255, 
-
-  // Allow the DNS service to be overwritten for testing.
-  _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: 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);}
-
-      // Short circuit if the special ticket value indicates we're good to go.
-      else if (ticket >= _this14.TICKET_LIMIT) {
-          resolve();
-          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;}
-
-
-        // Ensure we have a special loopback value before checking other blocks.
-        var ipBlocks = record.getNextAddrAsString().split(".");
-        if (ipBlocks[0] !== "127") {
-          reject();
-          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;
-          case "aurora":
-          case "nightly":
-            index = 3;
-            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 
-
-        {
-          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);});} };
-
-
-
-
-/**
- * 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, 
-    onBuild: function onBuild(aDocument) {
-      // If we're not supposed to see the button, return zip.
-      if (!Services.prefs.getBoolPref("loop.enabled")) {
-        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")]) : 
-      CustomizableUI.getLocalizedProperty(this, "tooltiptext");
-      node.setAttribute("tooltiptext", tooltiptext);
-      node.setAttribute("removable", "true");
-      node.addEventListener("command", function (event) {
-        aDocument.defaultView.LoopUI.togglePanel(event);});
-
-
-      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.
- */
-function loadDefaultPrefs() {
-  var branch = Services.prefs.getDefaultBranch("");
-  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;}
-
-      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;}} });
-
-
-
-
-  if (Services.vc.compare(Services.appinfo.version, "47.0a1") < 0) {
-    branch.setBoolPref("loop.remote.autostart", false);}}
-
-
-
-/**
- * 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;}
-
-
-  createLoopButton();
-
-  // Attach to hidden window (for OS X).
-  if (AppConstants.platform == "macosx") {
-    try {
-      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);})();}}
-
-
-
-  // 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);}
-
-
-  // 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/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;}}}}
-
-
-
-/**
- * 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();});
-
-
-  // Detach from hidden window (for OS X).
-  if (AppConstants.platform == "macosx") {
-    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);}
-
-
-  // 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;}
-
-
-  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", 
-  "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, 
-      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");}
-
-
-function install() {}
-
-function uninstall() {}
deleted file mode 100644
--- a/browser/extensions/loop/chrome/content/modules/DomainWhitelist.jsm
+++ /dev/null
@@ -1,3018 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";
-
-/* exported DomainWhitelist */
-this.EXPORTED_SYMBOLS = ["DomainWhitelist"];
-
-this.DomainWhitelist = Object.freeze({ 
-  check: function check(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".
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-trim().split("\n"));
deleted file mode 100644
--- a/browser/extensions/loop/chrome/content/modules/LoopRooms.jsm
+++ /dev/null
@@ -1,1268 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";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("chrome://loop/content/modules/MozLoopService.jsm", {});var MozLoopService = _Cu$import.MozLoopService;var LOOP_SESSION_TYPE = _Cu$import.LOOP_SESSION_TYPE;
-XPCOMUtils.defineLazyModuleGetter(this, "Promise", 
-"resource://gre/modules/Promise.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "CommonUtils", 
-"resource://services-common/utils.js");
-XPCOMUtils.defineLazyModuleGetter(this, "WebChannel", 
-"resource://gre/modules/WebChannel.jsm");
-
-XPCOMUtils.defineLazyGetter(this, "eventEmitter", function () {var _Cu$import2 = 
-  Cu.import("resource://devtools/shared/event-emitter.js", {});var EventEmitter = _Cu$import2.EventEmitter;
-  return new EventEmitter();});
-
-
-XPCOMUtils.defineLazyModuleGetter(this, "DomainWhitelist", 
-"chrome://loop/content/modules/DomainWhitelist.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "LoopRoomsCache", 
-"chrome://loop/content/modules/LoopRoomsCache.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "loopUtils", 
-"chrome://loop/content/modules/utils.js", "utils");
-XPCOMUtils.defineLazyModuleGetter(this, "loopCrypto", 
-"chrome://loop/content/shared/js/crypto.js", "LoopCrypto");
-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;
-
-// Wait at least 5 seconds before doing opportunistic encryption.
-var MIN_TIME_BEFORE_ENCRYPTION = 5 * 1000;
-// Wait at maximum of 30 minutes before doing opportunistic encryption.
-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);};
-
-
-// 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
- */
-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;};
-
-
-/**
- * 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;};
-
-
-/**
- * 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;}
-
-
-  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);}}
-
-
-
-    // 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;}}}};
-
-
-
-
-/**
- * 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.
-   */
-  startTimer: function startTimer(callback, delay) {
-    return setTimeout(callback, delay);} };
-
-
-
-/**
- * The Rooms class.
- *
- * Each method that is a member of this class requires the last argument to be a
- * callback Function. MozLoopAPI will cause things to break if this invariant is
- * violated. You'll notice this as well in the documentation for each method.
- */
-var LoopRoomsInternal = { 
-  /**
-   * @var {Map} rooms Collection of rooms currently in cache.
-   */
-  rooms: new Map(), 
-
-  get roomsCache() {
-    if (!gRoomsCache) {
-      gRoomsCache = new LoopRoomsCache();}
-
-    return gRoomsCache;}, 
-
-
-  /**
-   * @var {Object} encryptionQueue  This stores the list of rooms awaiting
-   *                                encryption and associated timers.
-   */
-  encryptionQueue: { 
-    queue: [], 
-    timer: null, 
-    reset: function 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();}, 
-
-
-  /**
-   * 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;}
-
-
-    var linkClickerUrl = Services.prefs.getCharPref(LINKCLICKER_URL_PREFNAME);
-
-    // Don't do anything if there's no url.
-    if (!linkClickerUrl) {
-      return;}
-
-
-    var uri = Services.io.newURI(linkClickerUrl, null, null);
-
-    gLinkClickerChannel = new WebChannel("loop-link-clicker", uri);
-    gLinkClickerChannel.listen(this._handleLinkClickerMessage.bind(this));}, 
-
-
-  /**
-   * @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;}, 
-
-
-  /**
-   * @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;}, 
-
-
-  /**
-   * 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) {
-        MozLoopService.log.error("Upgrade encryption of room failed", error);
-        // No need to remove the room from the list as that's done in the shift above.
-      }}
-
-
-    if (this.encryptionQueue.queue.length) {
-      this.encryptionQueue.timer = 
-      timerHandlers.startTimer(this.processEncryptionQueue.bind(this), TIME_BETWEEN_ENCRYPTIONS);} else 
-    {
-      this.encryptionQueue.timer = null;}}), 
-
-
-
-  /**
-   * Queues a room for encryption sometime in the future. This is done so as
-   * not to overload the server or the browser when we initially request the
-   * list of rooms.
-   *
-   * @param {String} roomToken The token for the room that needs encrypting.
-   */
-  queueForEncryption: function queueForEncryption(roomToken) {
-    if (this.encryptionQueue.queue.indexOf(roomToken) == -1) {
-      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) * 
-      Math.random() + MIN_TIME_BEFORE_ENCRYPTION;
-      this.encryptionQueue.timer = 
-      timerHandlers.startTimer(this.processEncryptionQueue.bind(this), waitTime);}}, 
-
-
-
-  /**
-   * Gets or creates a room key for a room.
-   *
-   * It assumes that the room data is decrypted.
-   *
-   * @param {Object} roomData The roomData to get the key for.
-   * @return {Promise} A promise that is resolved whith the room key.
-   */
-  promiseGetOrCreateRoomKey: Task.async(function* (roomData) {
-    if (roomData.roomKey) {
-      return roomData.roomKey;}
-
-
-    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.
-   */
-  promiseEncryptedRoomKey: Task.async(function* (key) {
-    var profileKey = yield MozLoopService.promiseProfileEncryptionKey();
-
-    var encryptedRoomKey = yield loopCrypto.encryptBytes(profileKey, key);
-    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.
-   */
-  promiseDecryptRoomKey: Task.async(function* (encryptedKey) {
-    var profileKey = yield MozLoopService.promiseProfileEncryptionKey();
-
-    var decryptedRoomKey = yield loopCrypto.decryptBytes(profileKey, encryptedKey);
-    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.
-   */
-  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;}, 
-
-
-  /**
-   * 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 = {};}
-
-
-    // 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, 
-    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 };}), 
-
-
-
-  /**
-   * 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;}
-
-
-    if (!roomData.context.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) {
-      // If we don't have a key saved, then we can't do anything.
-      if (!savedRoomKey) {
-        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;}
-
-
-    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", 
-      roomData.roomToken);
-      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);} 
-
-      catch (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;}), 
-
-
-  /**
-   * 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);}, 
-
-
-  /**
-   * 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 = { 
-        roomName: room.roomName };
-
-      delete room.roomName;
-
-      // This room doesn't have context, so we'll save it for a later encryption
-      // cycle.
-      this.queueForEncryption(room.roomToken);
-
-      this.saveAndNotifyUpdate(room, isUpdate);} else 
-    {
-      // We could potentially optimise this later by not decrypting if the
-      // encrypted context hasn't already changed. However perf doesn't seem
-      // to be too bigger an issue at the moment, so we just decrypt for now.
-      // If we do change this, then we need to make sure we get the new room
-      // data setup properly, as happens at the end of promiseDecryptRoomData.
-      try {
-        var roomData = yield this.promiseDecryptRoomData(room);
-
-        this.saveAndNotifyUpdate(roomData, isUpdate);} 
-      catch (error) {
-        MozLoopService.log.error("Failed to decrypt room data: ", error);
-        // Do what we can to save the room data.
-        room.decryptedContext = {};
-        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.
-   */
-  getAll: function getAll(version) {
-    if (gGetAllPromise && !version) {
-      return gGetAllPromise;}
-
-
-    if (!gDirty) {
-      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 {
-
-
-        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);}
-
-
-            eventEmitter.emit("delete", room);
-            eventEmitter.emit("delete:" + room.roomToken, room);} else 
-          {
-            yield this.addOrUpdateRoom(room, !!orig);
-
-            if (orig) {
-              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);}
-
-
-      // 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) {
-      gGetAllPromise = null;
-      // Re-throw error so callers get notified.
-      throw error;});
-
-
-    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.
-   */
-  getNumParticipants: function getNumParticipants(roomToken) {
-    try {
-      if (this.rooms && this.rooms.has(roomToken)) {
-        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;}}, 
-
-
-
-  /**
-   * 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;}
-
-
-    Task.spawn(function* () {
-      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 
-      {
-        yield this.addOrUpdateRoom(data, !needsUpdate);
-
-        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: function create(room, callback) {
-    if (!("decryptedContext" in room) || !("maxSize" in room)) {
-      callback(new Error("Missing required property to create a room"));
-      return;}
-
-
-    if (!("roomOwner" in room)) {
-      room.roomOwner = "-";}
-
-
-    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", 
-      "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);}
-
-
-      // 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);}, 
-
-
-  /**
-   * 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");}}, 
-
-
-
-  /**
-   * 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;}}, 
-
-
-
-  open: function open(roomToken) {
-    var windowData = { 
-      roomToken: roomToken, 
-      type: "room" };
-
-
-    eventEmitter.emit("open", roomToken);
-
-    return MozLoopService.openChatWindow(windowData, function () {
-      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`.
-   */
-  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);});}, 
-
-
-  /**
-   * 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);});}, 
-
-
-  /**
-   * 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);}, 
-
-
-  /**
-   * 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);}, 
-
-
-  /**
-   * 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);}};}
-
-
-
-    var room = this.rooms.get(roomToken);
-    if (!sessionToken && room && room.sessionToken) {
-      if (!room || !room.sessionToken) {
-        return;}
-
-      sessionToken = room.sessionToken;
-      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`.
-   */
-  sendConnectionStatus: function sendConnectionStatus(roomToken, sessionToken, status, callback) {
-    if (!callback) {
-      callback = function callback(error) {
-        if (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);}, 
-
-
-  _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
-   */
-  _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();}
-
-
-    var domain = void 0;
-    try {
-      domain = Services.eTLD.getBaseDomain(Services.io.newURI(url, null, null));} 
-
-    catch (ex) {
-      // Failed to extract domain, so don't record it.
-      return;}
-
-
-    // Only record domains that are whitelisted.
-    if (!DomainWhitelist.check(domain)) {
-      return;}
-
-
-    // Increment the count for previously recorded domains.
-    if (this._domainLog.domainMap.has(domain)) {
-      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 });}}, 
-
-
-
-  /**
-   * 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);}};}
-
-
-
-
-    // Submit the domains that have been collected so far.
-    if (this._domainLog.roomToken === roomToken && 
-    this._domainLog.domainMap.size > 0) {
-      this._postToRoom(roomToken, { 
-        action: "logDomain", 
-        domains: [].concat(_toConsumableArray(this._domainLog.domainMap.values())) }, 
-      callback);
-      this._domainLog.domainMap.clear();}
-
-    // Indicate that nothing was logged.
-    else {
-        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`.
-   */
-  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.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;}
-
-    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);}}
-
-
-
-    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 = { 
-        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, 
-      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 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 || 
-    this.sessionType == LOOP_SESSION_TYPE.FXA && channelID != channelIDs.roomsFxA) {
-      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 () {});}, 
-
-
-  /**
-   * 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;}
-
-
-    gCurrentUser = user;
-    if (!gDirty) {
-      gDirty = true;
-      this.rooms.clear();
-      eventEmitter.emit("refresh");
-      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.
-   */
-  _handleLinkClickerMessage: function _handleLinkClickerMessage(id, message, sendingContext) {
-    if (!message) {
-      return;}
-
-
-    var sendResponse = function sendResponse(response, alreadyOpen) {
-      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 
-          {
-            this.open(message.roomToken);
-            sendResponse(hasRoom, false);}} else 
-
-        {
-          sendResponse(hasRoom, false);}
-
-        break;
-      default:
-        sendResponse(false, false);
-        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 = { 
-  init: function init() {
-    LoopRoomsInternal.init();}, 
-
-
-  get participantsCount() {
-    return LoopRoomsInternal.participantsCount;}, 
-
-
-  getAll: function getAll(version, callback) {
-    if (!callback) {
-      callback = version;
-      version = null;}
-
-
-    LoopRoomsInternal.getAll(version).then(function (result) {return callback(null, result);}).
-    catch(function (error) {return callback(error);});}, 
-
-
-  get: function get(roomToken, callback) {
-    return LoopRoomsInternal.get(roomToken, callback);}, 
-
-
-  create: function create(options, callback) {
-    return LoopRoomsInternal.create(options, callback);}, 
-
-
-  open: function open(roomToken) {
-    return LoopRoomsInternal.open(roomToken);}, 
-
-
-  delete: function _delete(roomToken, callback) {
-    return LoopRoomsInternal.delete(roomToken, callback);}, 
-
-
-  join: function join(roomToken, displayName, callback) {
-    return LoopRoomsInternal.join(roomToken, displayName, callback);}, 
-
-
-  refreshMembership: function refreshMembership(roomToken, sessionToken, callback) {
-    return LoopRoomsInternal.refreshMembership(roomToken, sessionToken, 
-    callback);}, 
-
-
-  leave: function leave(roomToken, sessionToken, callback) {
-    return LoopRoomsInternal.leave(roomToken, sessionToken, callback);}, 
-
-
-  sendConnectionStatus: function sendConnectionStatus(roomToken, sessionToken, status, callback) {
-    return LoopRoomsInternal.sendConnectionStatus(roomToken, sessionToken, status, callback);}, 
-
-
-  logDomains: function logDomains(roomToken, callback) {
-    return LoopRoomsInternal.logDomains(roomToken, callback);}, 
-
-
-  update: function update(roomToken, roomData, callback) {
-    return LoopRoomsInternal.update(roomToken, roomData, callback);}, 
-
-
-  getGuestCreatedRoom: function getGuestCreatedRoom() {
-    return LoopRoomsInternal.getGuestCreatedRoom();}, 
-
-
-  maybeRefresh: function maybeRefresh(user) {
-    return LoopRoomsInternal.maybeRefresh(user);}, 
-
-
-  getNumParticipants: function 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
-   */
-  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 
-    {
-      // Restore the cache to not be stubbed anymore, but it'll need a refresh
-      // from the server for sure.
-      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 new Promise(function (resolve, reject) {
-      _this3[method].apply(_this3, params.concat([function (error, result) {
-        if (error) {
-          reject(error);} else 
-        {
-          resolve(result);}}]));});}, 
-
-
-
-
-
-  on: function on() {var _eventEmitter;return (_eventEmitter = eventEmitter).on.apply(_eventEmitter, 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);}, 
-
-  /**
-   * 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;}}}
-
-
-      gGetAllPromise = null;
-      gDirty = false;}} };
-
-
-
-Object.freeze(this.LoopRooms);
deleted file mode 100644
--- a/browser/extensions/loop/chrome/content/modules/LoopRoomsCache.jsm
+++ /dev/null
@@ -1,157 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-"use strict";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("chrome://loop/content/modules/MozLoopService.jsm", {});var MozLoopService = _Cu$import.MozLoopService;var LOOP_SESSION_TYPE = _Cu$import.LOOP_SESSION_TYPE;
-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.
- */
-function LoopRoomsCache(options) {
-  options = options || {};
-
-  this.baseDir = options.baseDir || OS.Constants.Path.profileDir;
-  this.path = OS.Path.join(
-  this.baseDir, 
-  options.filename || LOOP_ROOMS_CACHE_FILENAME);
-
-  this._cache = null;}
-
-
-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.
-   */
-  _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));});}, 
-
-
-  /**
-   * 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;}
-
-
-    try {
-      return this._cache = yield CommonUtils.readJSON(this.path);} 
-    catch (error) {
-      if (!error.becauseNoSuchFile) {
-        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.
-   */
-  clear: function clear() {
-    this._cache = null;
-    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.
-   */
-  getKey: Task.async(function* (sessionType, roomToken) {
-    if (sessionType != LOOP_SESSION_TYPE.FXA) {
-      return null;}
-
-
-    var sessionData = (yield this._getCache())[sessionType];
-
-    if (!sessionData || !sessionData[roomToken]) {
-      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.
-   */
-  setKey: Task.async(function* (sessionType, roomToken, roomKey) {
-    if (sessionType != LOOP_SESSION_TYPE.FXA) {
-      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] = {};}
-
-
-    if (!cache[sessionType][roomToken]) {
-      cache[sessionType][roomToken] = {};}
-
-
-    // Only save it if there's no key, or it is different.
-    if (!cache[sessionType][roomToken].key || 
-    cache[sessionType][roomToken].key != roomKey) {
-      cache[sessionType][roomToken].key = roomKey;
-      return yield this._setCache(cache);}
-
-
-    return Promise.resolve();}) };
deleted file mode 100644
--- a/browser/extensions/loop/chrome/content/modules/MozLoopAPI.jsm
+++ /dev/null
@@ -1,1373 +0,0 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this file,
- * You can obtain one at http://mozilla.org/MPL/2.0/. */
-
-"use strict";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", 
-"resource:///modules/NewTabURL.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PageMetadata", 
-"resource://gre/modules/PageMetadata.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "PluralForm", 
-"resource://gre/modules/PluralForm.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils", 
-"resource://gre/modules/UpdateUtils.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "UITour", 
-"resource:///modules/UITour.jsm");
-XPCOMUtils.defineLazyModuleGetter(this, "Social", 
-"resource:///modules/Social.jsm");
-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", 
-"nsIClipboardHelper");
-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);}
-
-
-  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 {
-
-    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;}
-
-      // Don't do anything to members that are already cloneable.
-      if (/boolean|number|string/.test(type)) {
-        error[prop] = value;} else 
-      {
-        // Convert non-compatible types to a String.
-        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;};
-
-
-var getObjectAPIFunctionName = function getObjectAPIFunctionName(action) {
-  var funcName = action.split(":").pop();
-  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:
- */
-var isMultiProcessActive = function isMultiProcessActive() {
-  var win = Services.wm.getMostRecentWindow("navigator:browser");
-  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;
-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)];}));
-
-
-
-/**
- * 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.
-   */
-  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;}
-
-
-    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;}
-
-
-    // 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();}, 
-
-
-  /**
-   * 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]);}
-
-
-    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.
-   */
-  ClickRemoteCursor: function ClickRemoteCursor(message, reply) {
-    var win = Services.wm.getMostRecentWindow("navigator:browser");
-    if (win) {
-      win.LoopUI.clickRemoteCursor(message.data[0]);}
-
-
-    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.
-   */
-  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, 
-      callId: callid });
-
-    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.
-   */
-  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) + 
-    "&body=" + encodeURIComponent(body);
-    extProtocolSvc.loadURI(CommonUtils.makeURI(mailtoURL));
-    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.
-   */
-  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 
-    {
-      reply(cloneableError("confirm: missing button options"));
-      return;}
-
-
-    try {
-      var chosenButton = Services.prompt.confirmEx(null, "", 
-      options.message, buttonFlags, options.okButton, options.cancelButton, 
-      null, null, {});
-
-      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.
-   */
-  CopyString: function CopyString(message, reply) {
-    var str = message.data[0];
-    clipboardHelper.copyString(str);
-    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.
-   */
-  GenerateUUID: function GenerateUUID(message, reply) {
-    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.
-   */
-  GetAllStrings: function GetAllStrings(message, reply) {
-    if (gStringBundle) {
-      reply(gStringBundle);
-      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);}, 
-
-
-  /**
-   * 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 });}, 
-
-
-
-  /**
-   * 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 };} 
-
-      catch (ex) {
-        // Do nothing
-      }}
-
-    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.
-   */
-  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;}
-
-
-      var blob = new Blob([request.response], { type: "audio/ogg" });
-      reply(blob);};
-
-
-    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.
-   */
-  GetConversationWindowData: function GetConversationWindowData(message, reply) {
-    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.
-   */
-  GetDoNotDisturb: function GetDoNotDisturb(message, reply) {
-    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.
-   */
-  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.", 
-          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);}, 
-
-
-  /**
-   * 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 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));}, 
-
-
-  /**
-   * 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);}, 
-
-
-  /**
-   * 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;}
-
-
-    // non-remote pages have no metadata
-    if (!browser.getAttribute("remote") === "true") {
-      reply(null);}
-
-
-    win.messageManager.addMessageListener("PageMetadata:PageDataResult", 
-    function onPageDataResult(msg) {
-
-      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");}, 
-
-
-  /**
-   * 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;}
-
-
-    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.
-   */
-  HangupAllChatWindows: function HangupAllChatWindows(message, reply) {
-    MozLoopService.hangupAllChatWindows();
-    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];
-    if (!windowId) {
-      windowId = sessionToken;}
-
-
-    LoopRooms.logDomains(roomToken);
-    LoopRooms.leave(roomToken);
-    MozLoopService.setScreenShareState(windowId, false);
-    LoopAPI.sendMessageToHandler({ 
-      name: "RemoveBrowserSharingListener", 
-      data: [windowId] });
-
-    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.
-   */
-  IsMultiProcessActive: function IsMultiProcessActive(message, reply) {
-    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.
-   */
-  IsTabShareable: function IsTabShareable(message, reply) {
-    var win = Services.wm.getMostRecentWindow("navigator:browser");
-    var browser = win && win.gBrowser.selectedBrowser;
-    if (!win || !browser) {
-      reply(false);
-      return;}
-
-
-    var e10sActive = isMultiProcessActive();
-    var tabRemote = browser.getAttribute("remote") === "true";
-
-    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.
-   */
-  LoginToFxA: function LoginToFxA(message, reply) {
-    var forceReAuth = message.data[0];
-    MozLoopService.logInToFxA(forceReAuth);
-    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.
-   */
-  LogoutFromFxA: function LogoutFromFxA(message, reply) {
-    MozLoopService.logOutFromFxA();
-    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];
-    UITour.notify(subject, params);
-    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.
-   */
-  OpenGettingStartedTour: function OpenGettingStartedTour(message, reply) {
-    MozLoopService.openGettingStartedTour();
-    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.
-   */
-  GettingStartedURL: function GettingStartedURL(message, reply) {
-    var aSrc = message.data[0] || null;
-    var aAdditionalParams = message.data[1] || {};
-    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.
-   */
-  OpenFxASettings: function OpenFxASettings(message, reply) {
-    MozLoopService.openFxASettings();
-    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.
-   */
-  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();}, 
-
-
-  /**
-   * 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();}, 
-
-
-  /**
-   * 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(
-
-
-    message.data, 1);var windowId = _message$data7[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 {
-
-
-      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;}}}
-
-
-    NewTabURL.reset();
-
-    gBrowserSharingWindows.clear();
-    reply();}, 
-
-
-  "Rooms:*": function Rooms(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.
-   */
-  SetDoNotDisturb: function SetDoNotDisturb(message, reply) {
-    MozLoopService.doNotDisturb = message.data[0];
-    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];
-    MozLoopService.setLoopPref(prefName, value, prefType);
-    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.
-   */
-  SetNameNewRoom: function SetNameNewRoom(message, reply) {
-    var win = Services.wm.getMostRecentWindow("navigator:browser");
-    win && win.LoopUI.renameRoom();
-
-    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];
-    MozLoopService.setScreenShareState(windowId, active);
-    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];
-
-    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 
-
-    {
-      try {
-        Services.telemetry.getHistogramById(histogramId).add(value);} 
-      catch (ex) {
-        MozLoopService.log.error("TelemetryAddValue failed for histogram '" + histogramId + "'", ex);}}
-
-
-    reply();} };
-
-
-
-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: function initialize() {
-    if (gPageListeners) {
-      return;}
-
-
-    Cu.import("resource://gre/modules/RemotePageManager.jsm");
-
-    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));}
-
-
-      // 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);}, 
-
-
-  /**
-   * 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);}};}
-
-
-
-
-    // First, check if this is a batch call.
-    if (handlerName == kBatchMessage) {
-      this.handleBatchMessage(seq, message, reply);
-      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 
-      {
-        // Alright, pass the message forward.
-        kMessageHandlers[wildcardName](action, message, reply);}
-
-      // Aaaaand we're done.
-      return;}
-
-
-    // A unit test might've stubbed the handler.
-    if (gStubbedMessageHandlers && gStubbedMessageHandlers[handlerName]) {
-      gStubbedMessageHandlers[handlerName](message, reply);
-      return;}
-
-
-    if (!kMessageHandlers[handlerName]) {
-      var msg = "Ouch, no message handler available for '" + handlerName + "'";
-      MozLoopService.log.error(msg);
-      reply(cloneableError(msg));
-      return;}
-
-
-    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.
-   */
-  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 " + 
-      "of a batch, now is it?");
-      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(cloneableError("Too many nested calls"));
-      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);});}, 
-
-
-  /**
-   * 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(