Merge mozilla-central to autoland
authorCarsten "Tomcat" Book <cbook@mozilla.com>
Sat, 30 Jul 2016 16:49:41 +0200
changeset 307463 9e48f74f44c387f4601ba0aab3d651703183848f
parent 307462 2ba03ba34ece7fdcd007056de6ee58b758333e54 (current diff)
parent 307394 e5859dfe0bcbd40f4e33f4a633f73ea3473a7849 (diff)
child 307464 75f47838f78d85f74e52566deca3badf506ca1a1
push id20179
push usercbook@mozilla.com
push dateSun, 31 Jul 2016 15:48:44 +0000
treeherderfx-team@4a18b5cacb1b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
milestone50.0a1
Merge mozilla-central to autoland
browser/base/content/test/webrtc/browser_devices_get_user_media_about_urls.js
browser/components/uitour/test/browser_UITour_loop.js
browser/components/uitour/test/browser_UITour_loop_panel.js
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
browser/locales/en-US/chrome/browser/loop/loop.properties
browser/themes/osx/KUI-background.png
browser/themes/windows/KUI-background.png
dom/events/test/pointerevents/test_pointerevent_touch-action-auto-css_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-button-test_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-illegal.html
dom/events/test/pointerevents/test_pointerevent_touch-action-inherit_child-auto-child-none_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-inherit_child-none_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-inherit_child-pan-x-child-pan-x_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-inherit_child-pan-x-child-pan-y_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-inherit_highest-parent-none_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-inherit_parent-none_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-keyboard-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-mouse-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-none-css_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-pan-x-css_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-pan-x-pan-y-pan-y_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-pan-x-pan-y_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-pan-y-css_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-span-test_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-svg-test_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-table-test_touch-manual.html
dom/events/test/pointerevents/test_pointerevent_touch-action-verification.html
dom/html/HTMLMediaElement.cpp
dom/html/HTMLMediaElement.h
mobile/android/base/java/org/mozilla/gecko/AppNotificationClient.java
mobile/android/base/java/org/mozilla/gecko/BrowserApp.java
mobile/android/base/java/org/mozilla/gecko/GeckoAppShell.java
mobile/android/base/java/org/mozilla/gecko/NotificationClient.java
mobile/android/base/java/org/mozilla/gecko/NotificationHandler.java
mobile/android/base/java/org/mozilla/gecko/NotificationHelper.java
mobile/android/base/java/org/mozilla/gecko/NotificationReceiver.java
mobile/android/base/java/org/mozilla/gecko/NotificationService.java
mobile/android/base/java/org/mozilla/gecko/ServiceNotificationClient.java
mobile/android/base/moz.build
modules/libpref/init/all.js
old-configure.in
testing/web-platform/meta/cors/allow-headers.htm.ini
testing/web-platform/meta/cors/origin.htm.ini
testing/web-platform/meta/cors/remote-origin.htm.ini
--- a/.eslintignore
+++ b/.eslintignore
@@ -69,19 +69,16 @@ browser/components/privatebrowsing/**
 browser/components/sessionstore/**
 browser/components/shell/**
 browser/components/tabview/**
 browser/components/translation/**
 browser/extensions/pdfjs/**
 browser/extensions/pocket/content/panels/js/vendor/**
 browser/locales/**
 
-# Ignore all of loop since it is imported from github and checked at source.
-browser/extensions/loop/**
-
 # devtools/ exclusions
 devtools/client/canvasdebugger/**
 devtools/client/commandline/**
 devtools/client/debugger/**
 devtools/client/eyedropper/**
 devtools/client/framework/**
 devtools/client/jsonview/lib/**
 devtools/client/memory/**
--- a/.gitignore
+++ b/.gitignore
@@ -6,19 +6,16 @@
 *.pyo
 TAGS
 tags
 ID
 .DS_Store*
 *.pdb
 *.egg-info
 
-# Allow the id locale directory for loop ('ID' matches this normally)
-!browser/extensions/loop/chrome/locale/id
-
 # Vim swap files.
 .*.sw[a-z]
 
 # Emacs directory variable files.
 **/.dir-locals.el
 
 # User files that may appear at the root
 /.mozconfig*
--- a/.hgignore
+++ b/.hgignore
@@ -82,26 +82,16 @@
 ^media/libstagefright/android$
 
 # Tag files generated by GNU Global
 GTAGS
 GRTAGS
 GSYMS
 GPATH
 
-# Various items for Loop
-^browser/components/loop/standalone/content/config\.js$
-^browser/extensions/loop/.*/node_modules/
-^browser/extensions/loop/.*\.module-cache
-^browser/extensions/loop/test/coverage/desktop
-^browser/extensions/loop/test/coverage/shared_standalone
-^browser/extensions/loop/test/visual-regression/diff
-^browser/extensions/loop/test/visual-regression/new
-^browser/extensions/loop/test/visual-regression/refs
-
 # Git clone directory for updating web-platform-tests
 ^testing/web-platform/sync/
 
 # Android Gradle artifacts.
 ^mobile/android/gradle/.gradle
 
 # XCode project cruft
 ^embedding/ios/GeckoEmbed/GeckoEmbed.xcodeproj/project.xcworkspace/xcuserdata
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1285541 - Clobber needed because this patch renames a file.
+Bug 1287827 - Clobber needed because this patch removes files, second landing AND Bug 1272693 - Clobber required to rebuild NSS.
--- a/accessible/xpcom/xpcAccessibleHyperText.cpp
+++ b/accessible/xpcom/xpcAccessibleHyperText.cpp
@@ -36,158 +36,225 @@ NS_IMPL_RELEASE_INHERITED(xpcAccessibleH
 // nsIAccessibleText
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetCharacterCount(int32_t* aCharacterCount)
 {
   NS_ENSURE_ARG_POINTER(aCharacterCount);
   *aCharacterCount = 0;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  *aCharacterCount = Intl()->CharacterCount();
+  if (mIntl.IsAccessible()) {
+    *aCharacterCount = Intl()->CharacterCount();
+  } else {
+    *aCharacterCount = mIntl.AsProxy()->CharacterCount();
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetText(int32_t aStartOffset, int32_t aEndOffset,
                                 nsAString& aText)
 {
   aText.Truncate();
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->TextSubstring(aStartOffset, aEndOffset, aText);
+  if (mIntl.IsAccessible()) {
+    Intl()->TextSubstring(aStartOffset, aEndOffset, aText);
+  } else {
+    nsString text;
+    mIntl.AsProxy()->TextSubstring(aStartOffset, aEndOffset, text);
+    aText = text;
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetTextBeforeOffset(int32_t aOffset,
                                             AccessibleTextBoundary aBoundaryType,
                                             int32_t* aStartOffset,
                                             int32_t* aEndOffset,
                                             nsAString& aText)
 {
   NS_ENSURE_ARG_POINTER(aStartOffset);
   NS_ENSURE_ARG_POINTER(aEndOffset);
   *aStartOffset = *aEndOffset = 0;
   aText.Truncate();
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->TextBeforeOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset, aText);
+  if (mIntl.IsAccessible()) {
+    Intl()->TextBeforeOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset, 
+                             aText);
+  } else {
+    nsString text;
+    mIntl.AsProxy()->GetTextBeforeOffset(aOffset, aBoundaryType, text,
+                                         aStartOffset, aEndOffset);
+    aText = text;
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetTextAtOffset(int32_t aOffset,
                                         AccessibleTextBoundary aBoundaryType,
                                         int32_t* aStartOffset,
                                         int32_t* aEndOffset, nsAString& aText)
 {
   NS_ENSURE_ARG_POINTER(aStartOffset);
   NS_ENSURE_ARG_POINTER(aEndOffset);
   *aStartOffset = *aEndOffset = 0;
   aText.Truncate();
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->TextAtOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset, aText);
+  if (mIntl.IsAccessible()) {
+    Intl()->TextAtOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset, 
+                         aText);
+  } else {
+    nsString text;
+    mIntl.AsProxy()->GetTextAtOffset(aOffset, aBoundaryType, text, 
+                                     aStartOffset, aEndOffset);
+    aText = text;
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetTextAfterOffset(int32_t aOffset,
                                            AccessibleTextBoundary aBoundaryType,
                                            int32_t* aStartOffset,
                                            int32_t* aEndOffset, nsAString& aText)
 {
   NS_ENSURE_ARG_POINTER(aStartOffset);
   NS_ENSURE_ARG_POINTER(aEndOffset);
   *aStartOffset = *aEndOffset = 0;
   aText.Truncate();
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->TextAfterOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset, aText);
+  if (mIntl.IsAccessible()) {
+    Intl()->TextAfterOffset(aOffset, aBoundaryType, aStartOffset, aEndOffset, 
+                            aText);
+  } else {
+    nsString text;
+    mIntl.AsProxy()->GetTextAfterOffset(aOffset, aBoundaryType, text, 
+                                        aStartOffset, aEndOffset);
+    aText = text;
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetCharacterAtOffset(int32_t aOffset,
                                              char16_t* aCharacter)
 {
   NS_ENSURE_ARG_POINTER(aCharacter);
   *aCharacter = L'\0';
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  *aCharacter = Intl()->CharAt(aOffset);
+  if (mIntl.IsAccessible()) {
+    *aCharacter = Intl()->CharAt(aOffset);
+  } else {
+    *aCharacter = mIntl.AsProxy()->CharAt(aOffset);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetTextAttributes(bool aIncludeDefAttrs,
                                           int32_t aOffset,
                                           int32_t* aStartOffset,
                                           int32_t* aEndOffset,
                                           nsIPersistentProperties** aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aStartOffset);
   NS_ENSURE_ARG_POINTER(aEndOffset);
   NS_ENSURE_ARG_POINTER(aAttributes);
   *aStartOffset = *aEndOffset = 0;
   *aAttributes = nullptr;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIPersistentProperties> attrs =
-   Intl()->TextAttributes(aIncludeDefAttrs, aOffset, aStartOffset, aEndOffset);
-  attrs.swap(*aAttributes);
+  nsCOMPtr<nsIPersistentProperties> props;
+  if (mIntl.IsAccessible()) {
+    props = Intl()->TextAttributes(aIncludeDefAttrs, aOffset, aStartOffset,
+                                   aEndOffset);
+  } else {
+    AutoTArray<Attribute, 10> attrs;
+    mIntl.AsProxy()->TextAttributes(aIncludeDefAttrs, aOffset, &attrs,
+        aStartOffset, aEndOffset);
+    uint32_t attrCount = attrs.Length();
+    nsAutoString unused;
+    for (uint32_t i = 0; i < attrCount; i++) {
+      props->SetStringProperty(attrs[i].Name(), attrs[i].Value(), unused);
+    }
+  }
+  props.forget(aAttributes);
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetDefaultTextAttributes(nsIPersistentProperties** aAttributes)
 {
   NS_ENSURE_ARG_POINTER(aAttributes);
   *aAttributes = nullptr;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  nsCOMPtr<nsIPersistentProperties> attrs = Intl()->DefaultTextAttributes();
-  attrs.swap(*aAttributes);
+  nsCOMPtr<nsIPersistentProperties> props;
+  if (mIntl.IsAccessible()) {
+    props = Intl()->DefaultTextAttributes();
+  } else {
+    AutoTArray<Attribute, 10> attrs;
+    mIntl.AsProxy()->DefaultTextAttributes(&attrs);
+    uint32_t attrCount = attrs.Length();
+    nsAutoString unused;
+    for (uint32_t i = 0; i < attrCount; i++) {
+      props->SetStringProperty(attrs[i].Name(), attrs[i].Value(), unused);
+    }
+  }
+  props.forget(aAttributes);
+
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetCharacterExtents(int32_t aOffset,
                                             int32_t* aX, int32_t* aY,
                                             int32_t* aWidth, int32_t* aHeight,
                                             uint32_t aCoordType)
 {
   NS_ENSURE_ARG_POINTER(aX);
   NS_ENSURE_ARG_POINTER(aY);
   NS_ENSURE_ARG_POINTER(aWidth);
   NS_ENSURE_ARG_POINTER(aHeight);
   *aX = *aY = *aWidth = *aHeight;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  nsIntRect rect = Intl()->CharBounds(aOffset, aCoordType);
+  nsIntRect rect;
+  if (mIntl.IsAccessible()) {
+    rect = Intl()->CharBounds(aOffset, aCoordType);
+  } else {
+    rect = mIntl.AsProxy()->CharBounds(aOffset, aCoordType);
+  }
   *aX = rect.x; *aY = rect.y;
   *aWidth = rect.width; *aHeight = rect.height;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetRangeExtents(int32_t aStartOffset, int32_t aEndOffset,
                                         int32_t* aX, int32_t* aY,
@@ -195,151 +262,209 @@ xpcAccessibleHyperText::GetRangeExtents(
                                         uint32_t aCoordType)
 {
   NS_ENSURE_ARG_POINTER(aX);
   NS_ENSURE_ARG_POINTER(aY);
   NS_ENSURE_ARG_POINTER(aWidth);
   NS_ENSURE_ARG_POINTER(aHeight);
   *aX = *aY = *aWidth = *aHeight = 0;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  nsIntRect rect = Intl()->TextBounds(aStartOffset, aEndOffset, aCoordType);
+  nsIntRect rect;
+  if (mIntl.IsAccessible()) {
+    rect = Intl()->TextBounds(aStartOffset, aEndOffset, aCoordType);
+  } else {
+    rect = mIntl.AsProxy()->TextBounds(aStartOffset, aEndOffset, aCoordType);
+  }
   *aX = rect.x; *aY = rect.y;
   *aWidth = rect.width; *aHeight = rect.height;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetOffsetAtPoint(int32_t aX, int32_t aY,
                                          uint32_t aCoordType, int32_t* aOffset)
 {
   NS_ENSURE_ARG_POINTER(aOffset);
   *aOffset = -1;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  *aOffset = Intl()->OffsetAtPoint(aX, aY, aCoordType);
+  if (mIntl.IsAccessible()) {
+    *aOffset = Intl()->OffsetAtPoint(aX, aY, aCoordType);
+  } else {
+    *aOffset = mIntl.AsProxy()->OffsetAtPoint(aX, aY, aCoordType);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetCaretOffset(int32_t* aCaretOffset)
 {
   NS_ENSURE_ARG_POINTER(aCaretOffset);
   *aCaretOffset = -1;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  *aCaretOffset = Intl()->CaretOffset();
+  if (mIntl.IsAccessible()) {
+    *aCaretOffset = Intl()->CaretOffset();
+  } else {
+    *aCaretOffset = mIntl.AsProxy()->CaretOffset();
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::SetCaretOffset(int32_t aCaretOffset)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->SetCaretOffset(aCaretOffset);
+  if (mIntl.IsAccessible()) {
+    Intl()->SetCaretOffset(aCaretOffset);
+  } else {
+    mIntl.AsProxy()->SetCaretOffset(aCaretOffset);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetSelectionCount(int32_t* aSelectionCount)
 {
   NS_ENSURE_ARG_POINTER(aSelectionCount);
   *aSelectionCount = 0;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  *aSelectionCount = Intl()->SelectionCount();
+  if (mIntl.IsAccessible()) {
+    *aSelectionCount = Intl()->SelectionCount();
+  } else {
+    *aSelectionCount = mIntl.AsProxy()->SelectionCount();
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetSelectionBounds(int32_t aSelectionNum,
                                            int32_t* aStartOffset,
                                            int32_t* aEndOffset)
 {
   NS_ENSURE_ARG_POINTER(aStartOffset);
   NS_ENSURE_ARG_POINTER(aEndOffset);
   *aStartOffset = *aEndOffset = 0;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  if (aSelectionNum < 0 || aSelectionNum >= Intl()->SelectionCount())
+  if (aSelectionNum < 0)
     return NS_ERROR_INVALID_ARG;
 
-  Intl()->SelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset);
+  if (mIntl.IsAccessible()) {
+    if (aSelectionNum >= Intl()->SelectionCount())
+      return NS_ERROR_INVALID_ARG;
+      
+    Intl()->SelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset);
+  } else {
+    nsString unused;
+    mIntl.AsProxy()->SelectionBoundsAt(aSelectionNum, unused, aStartOffset, 
+                                       aEndOffset);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::SetSelectionBounds(int32_t aSelectionNum,
                                            int32_t aStartOffset,
                                            int32_t aEndOffset)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  if (aSelectionNum < 0 ||
-      !Intl()->SetSelectionBoundsAt(aSelectionNum, aStartOffset, aEndOffset))
+  if (aSelectionNum < 0)
     return NS_ERROR_INVALID_ARG;
 
+  if (mIntl.IsAccessible()) {
+      if (!Intl()->SetSelectionBoundsAt(aSelectionNum, aStartOffset, 
+                                        aEndOffset)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+  } else {
+      if (!mIntl.AsProxy()->SetSelectionBoundsAt(aSelectionNum, aStartOffset, 
+                                                aEndOffset)) {
+        return NS_ERROR_INVALID_ARG;
+      }
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::AddSelection(int32_t aStartOffset, int32_t aEndOffset)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->AddToSelection(aStartOffset, aEndOffset);
+  if (mIntl.IsAccessible()) {
+    Intl()->AddToSelection(aStartOffset, aEndOffset);
+  } else {
+    mIntl.AsProxy()->AddToSelection(aStartOffset, aEndOffset);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::RemoveSelection(int32_t aSelectionNum)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->RemoveFromSelection(aSelectionNum);
+  if (mIntl.IsAccessible()) {
+    Intl()->RemoveFromSelection(aSelectionNum);
+  } else {
+    mIntl.AsProxy()->RemoveFromSelection(aSelectionNum);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::ScrollSubstringTo(int32_t aStartOffset,
                                           int32_t aEndOffset,
                                           uint32_t aScrollType)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->ScrollSubstringTo(aStartOffset, aEndOffset, aScrollType);
+  if (mIntl.IsAccessible()) {
+    Intl()->ScrollSubstringTo(aStartOffset, aEndOffset, aScrollType);
+  } else {
+    mIntl.AsProxy()->ScrollSubstringTo(aStartOffset, aEndOffset, aScrollType);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::ScrollSubstringToPoint(int32_t aStartOffset,
                                                int32_t aEndOffset,
                                                uint32_t aCoordinateType,
                                                int32_t aX, int32_t aY)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->ScrollSubstringToPoint(aStartOffset, aEndOffset, aCoordinateType, aX, aY);
+  if (mIntl.IsAccessible()) {
+    Intl()->ScrollSubstringToPoint(aStartOffset, aEndOffset, aCoordinateType,
+                                   aX, aY);
+  } else {
+    mIntl.AsProxy()->ScrollSubstringToPoint(aStartOffset, aEndOffset,
+                                            aCoordinateType, aX, aY);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetEnclosingRange(nsIAccessibleTextRange** aRange)
 {
   NS_ENSURE_ARG_POINTER(aRange);
   *aRange = nullptr;
@@ -447,126 +572,171 @@ xpcAccessibleHyperText::GetRangeAtPoint(
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibleEditableText
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::SetTextContents(const nsAString& aText)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->ReplaceText(aText);
+  if (mIntl.IsAccessible()) {
+    Intl()->ReplaceText(aText);
+  } else {
+    nsString text(aText);
+    mIntl.AsProxy()->ReplaceText(text);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::InsertText(const nsAString& aText, int32_t aOffset)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->InsertText(aText, aOffset);
+  if (mIntl.IsAccessible()) {
+    Intl()->InsertText(aText, aOffset);
+  } else {
+    nsString text(aText);
+    mIntl.AsProxy()->InsertText(text, aOffset);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::CopyText(int32_t aStartOffset, int32_t aEndOffset)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->CopyText(aStartOffset, aEndOffset);
+  if (mIntl.IsAccessible()) {
+    Intl()->CopyText(aStartOffset, aEndOffset);
+  } else {
+    mIntl.AsProxy()->CopyText(aStartOffset, aEndOffset);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::CutText(int32_t aStartOffset, int32_t aEndOffset)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->CutText(aStartOffset, aEndOffset);
+  if (mIntl.IsAccessible()) {
+    Intl()->CutText(aStartOffset, aEndOffset);
+  } else {
+    mIntl.AsProxy()->CutText(aStartOffset, aEndOffset);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::DeleteText(int32_t aStartOffset, int32_t aEndOffset)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->DeleteText(aStartOffset, aEndOffset);
+  if (mIntl.IsAccessible()) {
+    Intl()->DeleteText(aStartOffset, aEndOffset);
+  } else {
+    mIntl.AsProxy()->DeleteText(aStartOffset, aEndOffset);
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::PasteText(int32_t aOffset)
 {
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  Intl()->PasteText(aOffset);
+  if (mIntl.IsAccessible()) {
+    Intl()->PasteText(aOffset);
+  } else {
+    mIntl.AsProxy()->PasteText(aOffset);
+  }
   return NS_OK;
 }
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessibleHyperText
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetLinkCount(int32_t* aLinkCount)
 {
   NS_ENSURE_ARG_POINTER(aLinkCount);
   *aLinkCount = 0;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  *aLinkCount = Intl()->LinkCount();
+  if (mIntl.IsAccessible()) {
+    *aLinkCount = Intl()->LinkCount();
+  } else {
+    *aLinkCount = mIntl.AsProxy()->LinkCount();
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetLinkAt(int32_t aIndex, nsIAccessibleHyperLink** aLink)
 {
   NS_ENSURE_ARG_POINTER(aLink);
   *aLink = nullptr;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  NS_IF_ADDREF(*aLink = ToXPC(Intl()->LinkAt(aIndex)));
+  if (mIntl.IsAccessible()) {
+    NS_IF_ADDREF(*aLink = ToXPC(Intl()->LinkAt(aIndex)));
+  } else {
+    NS_IF_ADDREF(*aLink = ToXPC(mIntl.AsProxy()->LinkAt(aIndex)));
+  }
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetLinkIndex(nsIAccessibleHyperLink* aLink,
                                      int32_t* aIndex)
 {
   NS_ENSURE_ARG_POINTER(aLink);
   NS_ENSURE_ARG_POINTER(aIndex);
   *aIndex = -1;
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
   nsCOMPtr<nsIAccessible> xpcLink(do_QueryInterface(aLink));
-  Accessible* link = xpcLink->ToInternalAccessible();
-  if (link)
-    *aIndex = Intl()->LinkIndexOf(link);
+  if (Accessible* accLink = xpcLink->ToInternalAccessible()) {
+    *aIndex = Intl()->LinkIndexOf(accLink);
+  } else {
+    xpcAccessibleHyperText* linkHyperText =
+      static_cast<xpcAccessibleHyperText*>(xpcLink.get());
+    ProxyAccessible* proxyLink = linkHyperText->mIntl.AsProxy();
+    if (proxyLink) {
+      *aIndex = mIntl.AsProxy()->LinkIndexOf(proxyLink);
+    }
+  }
 
   return NS_OK;
 }
 
 NS_IMETHODIMP
 xpcAccessibleHyperText::GetLinkIndexAtOffset(int32_t aOffset,
                                              int32_t* aLinkIndex)
 {
   NS_ENSURE_ARG_POINTER(aLinkIndex);
   *aLinkIndex = -1; // API says this magic value means 'not found'
 
-  if (!Intl())
+  if (mIntl.IsNull())
     return NS_ERROR_FAILURE;
 
-  *aLinkIndex = Intl()->LinkIndexAtOffset(aOffset);
+  if (mIntl.IsAccessible()) {
+    *aLinkIndex = Intl()->LinkIndexAtOffset(aOffset);
+  } else {
+    *aLinkIndex = mIntl.AsProxy()->LinkIndexAtOffset(aOffset);
+  }
   return NS_OK;
 }
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -579,17 +579,19 @@ pref("mousewheel.with_meta.action", 1); 
 #endif
 pref("mousewheel.with_control.action",3);
 pref("mousewheel.with_win.action", 1);
 
 pref("browser.xul.error_pages.enabled", true);
 pref("browser.xul.error_pages.expert_bad_cert", false);
 
 // Enable captive portal detection.
+#ifdef NIGHTLY_BUILD
 pref("network.captive-portal-service.enabled", true);
+#endif
 
 // If true, network link events will change the value of navigator.onLine
 pref("network.manage-offline-status", true);
 
 // We want to make sure mail URLs are handled externally...
 pref("network.protocol-handler.external.mailto", true); // for mail
 pref("network.protocol-handler.external.news", true);   // for news
 pref("network.protocol-handler.external.snews", true);  // for secure news
@@ -1470,9 +1472,9 @@ pref("extensions.pocket.enabled", true);
 
 pref("signon.schemeUpgrades", true);
 
 // Enable the "Simplify Page" feature in Print Preview
 pref("print.use_simplify_page", true);
 
 // Space separated list of URLS that are allowed to send objects (instead of
 // only strings) through webchannels. This list is duplicated in mobile/android/app/mobile.js
-pref("webchannel.allowObject.urlWhitelist", "https://accounts.firefox.com https://content.cdn.mozilla.net https://hello.firefox.com https://input.mozilla.org https://support.mozilla.org https://install.mozilla.org");
+pref("webchannel.allowObject.urlWhitelist", "https://accounts.firefox.com https://content.cdn.mozilla.net https://input.mozilla.org https://support.mozilla.org https://install.mozilla.org");
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -290,28 +290,16 @@
            side="right"
            type="arrow"
            hidden="true"
            flip="slide"
            rolluponmousewheel="true"
            noautofocus="true"
            position="topcenter topright"/>
 
-    <panel id="loop-notification-panel"
-           class="loop-panel social-panel"
-           type="arrow"
-           hidden="true"
-           noautofocus="true"/>
-
-    <panel id="loop-panel"
-           class="loop-panel social-panel"
-           type="arrow"
-           orient="horizontal"
-           hidden="true"/>
-
     <menupopup id="toolbar-context-menu"
                onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('viewToolbarsMenuSeparator'));">
       <menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
                 accesskey="&customizeMenu.moveToPanel.accesskey;"
                 label="&customizeMenu.moveToPanel.label;"
                 contexttype="toolbaritem"
                 class="customize-context-moveToPanel"/>
       <menuitem oncommand="gCustomizeMode.removeFromArea(document.popupNode)"
@@ -405,17 +393,17 @@
                 accesskey="&showRecentlyBookmarked.accesskey;"
                 oncommand="BookmarkingUI.showRecentlyBookmarked();"
                 closemenu="single"
                 ignoreitem="true"
                 ordinal="2"
                 hidden="true"/>
     </menupopup>
 
-    <panel id="ctrlTab-panel" class="KUI-panel" hidden="true" norestorefocus="true" level="top">
+    <panel id="ctrlTab-panel" hidden="true" norestorefocus="true" level="top">
       <hbox>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
       </hbox>
--- a/browser/base/content/test/general/browser_parsable_css.js
+++ b/browser/base/content/test/general/browser_parsable_css.js
@@ -15,26 +15,16 @@ let whitelist = [
    isFromDevTools: true},
   // PDFjs is futureproofing its pseudoselectors, and those rules are dropped.
   {sourceName: /web\/viewer\.css$/i,
    errorMessage: /Unknown pseudo-class.*(fullscreen|selection)/i,
    isFromDevTools: false},
   // Tracked in bug 1004428.
   {sourceName: /aboutaccounts\/(main|normalize)\.css$/i,
     isFromDevTools: false},
-  // TokBox SDK assets, see bug 1032469.
-  {sourceName: /loop\/.*sdk-content\/.*\.css$/i,
-    isFromDevTools: false},
-  // Loop standalone client CSS uses placeholder cross browser pseudo-element
-  {sourceName: /loop\/.*\.css$/i,
-   errorMessage: /Unknown pseudo-class.*placeholder/i,
-   isFromDevTools: false},
-  {sourceName: /loop\/.*shared\/css\/common.css$/i,
-   errorMessage: /Unknown property .user-select./i,
-   isFromDevTools: false},
   // Highlighter CSS uses a UA-only pseudo-class, see bug 985597.
   {sourceName: /highlighters\.css$/i,
    errorMessage: /Unknown pseudo-class.*moz-native-anonymous/i,
    isFromDevTools: true},
   // Responsive Design Mode CSS uses a UA-only pseudo-class, see Bug 1241714.
   {sourceName: /responsive-ua\.css$/i,
    errorMessage: /Unknown pseudo-class.*moz-dropdown-list/i,
    isFromDevTools: true},
--- a/browser/base/content/test/webrtc/browser.ini
+++ b/browser/base/content/test/webrtc/browser.ini
@@ -1,12 +1,10 @@
 [DEFAULT]
 support-files =
   get_user_media.html
   get_user_media_content_script.js
   head.js
 
 [browser_devices_get_user_media.js]
 skip-if = buildapp == 'mulet' || (os == "linux" && debug) # linux: bug 976544
-[browser_devices_get_user_media_about_urls.js]
-skip-if = e10s && debug
 [browser_devices_get_user_media_anim.js]
 [browser_devices_get_user_media_in_frame.js]
deleted file mode 100644
--- a/browser/base/content/test/webrtc/browser_devices_get_user_media_about_urls.js
+++ /dev/null
@@ -1,219 +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/. */
-
-const PREF_LOOP_CSP = "loop.CSP";
-
-var gTab;
-
-// Taken from dom/media/tests/mochitest/head.js
-function isMacOSX10_6orOlder() {
-  var is106orOlder = false;
-
-  if (navigator.platform.indexOf("Mac") == 0) {
-    var version = Cc["@mozilla.org/system-info;1"]
-                    .getService(Ci.nsIPropertyBag2)
-                    .getProperty("version");
-    // the next line is correct: Mac OS 10.6 corresponds to Darwin version 10.x !
-    // Mac OS 10.7 is Darwin version 11.x. the |version| string we've got here
-    // is the Darwin version.
-    is106orOlder = (parseFloat(version) < 11.0);
-  }
-  return is106orOlder;
-}
-
-// Screensharing is disabled on older platforms (WinXP and Mac 10.6).
-function isOldPlatform() {
-  const isWinXP = navigator.userAgent.indexOf("Windows NT 5.1") != -1;
-  if (isMacOSX10_6orOlder() || isWinXP) {
-    info(true, "Screensharing disabled for OSX10.6 and WinXP");
-    return true;
-  }
-  return false;
-}
-
-// Linux prompts aren't working for screensharing.
-function isLinux() {
-  return navigator.platform.indexOf("Linux") != -1;
-}
-
-function loadPage(aUrl) {
-  let deferred = Promise.defer();
-
-  gTab.linkedBrowser.addEventListener("load", function onload() {
-    gTab.linkedBrowser.removeEventListener("load", onload, true);
-
-    is(PopupNotifications._currentNotifications.length, 0,
-       "should start the test without any prior popup notification");
-
-    deferred.resolve();
-  }, true);
-  content.location = aUrl;
-  return deferred.promise;
-}
-
-registerCleanupFunction(function() {
-  gBrowser.removeCurrentTab();
-});
-
-const permissionError = "error: NotAllowedError: The request is not allowed " +
-    "by the user agent or the platform in the current context.";
-
-var gTests = [
-
-{
-  desc: "getUserMedia about:loopconversation shouldn't prompt",
-  run: function checkAudioVideoLoop() {
-    yield SpecialPowers.pushPrefEnv({
-      "set": [[PREF_LOOP_CSP, "default-src 'unsafe-inline'"]],
-    });
-
-    yield loadPage("about:loopconversation");
-
-    info("requesting devices");
-    let promise = promiseObserverCalled("recording-device-events");
-    yield promiseRequestDevice(true, true);
-    yield promise;
-
-    // Wait for the devices to actually be captured and running before
-    // proceeding.
-    yield promisePopupNotification("webRTC-sharingDevices");
-
-    is((yield getMediaCaptureState()), "CameraAndMicrophone",
-       "expected camera and microphone to be shared");
-
-    yield closeStream();
-
-    yield SpecialPowers.popPrefEnv();
-  }
-},
-
-{
-  desc: "getUserMedia about:loopconversation should prompt for window sharing",
-  run: function checkShareScreenLoop() {
-    if (isOldPlatform() || isLinux()) {
-      return;
-    }
-
-    yield SpecialPowers.pushPrefEnv({
-      "set": [[PREF_LOOP_CSP, "default-src 'unsafe-inline'"]],
-    });
-
-    yield loadPage("about:loopconversation");
-
-    info("requesting screen");
-    let promise = promiseObserverCalled("getUserMedia:request");
-    yield promiseRequestDevice(false, true, null, "window");
-
-    // Wait for the devices to actually be captured and running before
-    // proceeding.
-    yield promisePopupNotification("webRTC-shareDevices");
-
-    is((yield getMediaCaptureState()), "none",
-       "expected camera and microphone not to be shared");
-
-    yield promiseMessage(permissionError, () => {
-      PopupNotifications.panel.firstChild.button.click();
-    });
-
-    yield expectObserverCalled("getUserMedia:response:deny");
-    yield expectObserverCalled("recording-window-ended");
-
-    yield SpecialPowers.popPrefEnv();
-  }
-},
-
-{
-  desc: "getUserMedia about:evil should prompt",
-  run: function checkAudioVideoNonLoop() {
-    yield loadPage("about:evil");
-
-    let promise = promiseObserverCalled("getUserMedia:request");
-    yield promiseRequestDevice(true, true);
-    yield promise;
-
-    is((yield getMediaCaptureState()), "none",
-       "expected camera and microphone not to be shared");
-  }
-},
-
-];
-
-function test() {
-  waitForExplicitFinish();
-
-  gTab = gBrowser.addTab();
-  gBrowser.selectedTab = gTab;
-
-  gTab.linkedBrowser.messageManager.loadFrameScript(CONTENT_SCRIPT_HELPER, true);
-
-  Task.spawn(function () {
-    yield ContentTask.spawn(gBrowser.selectedBrowser,
-                            getRootDirectory(gTestPath) + "get_user_media.html",
-                            function* (url) {
-      const Ci = Components.interfaces;
-      Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
-      Components.utils.import("resource://gre/modules/Services.jsm");
-
-      /* A fake about module to map get_user_media.html to different about urls. */
-      function fakeLoopAboutModule() {
-      }
-
-      fakeLoopAboutModule.prototype = {
-        QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
-        newChannel: function (aURI, aLoadInfo) {
-          let uri = Services.io.newURI(url, null, null);
-          let chan = Services.io.newChannelFromURIWithLoadInfo(uri, aLoadInfo);
-          chan.owner = Services.scriptSecurityManager.getSystemPrincipal();
-          return chan;
-        },
-        getURIFlags: function (aURI) {
-          return Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
-                 Ci.nsIAboutModule.ALLOW_SCRIPT |
-                 Ci.nsIAboutModule.URI_CAN_LOAD_IN_CHILD |
-                 Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT;
-        }
-      };
-
-      var factory = XPCOMUtils._getFactory(fakeLoopAboutModule);
-      var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
-      let UUIDGenerator = Components.classes["@mozilla.org/uuid-generator;1"]
-                                    .getService(Ci.nsIUUIDGenerator);
-      registrar.registerFactory(UUIDGenerator.generateUUID(), "",
-                                "@mozilla.org/network/protocol/about;1?what=loopconversation",
-                                factory);
-      registrar.registerFactory(UUIDGenerator.generateUUID(), "",
-                                "@mozilla.org/network/protocol/about;1?what=evil",
-                                factory);
-    });
-
-    yield SpecialPowers.pushPrefEnv({
-      "set": [[PREF_PERMISSION_FAKE, true],
-              ["media.getusermedia.screensharing.enabled", true]],
-    });
-
-    for (let test of gTests) {
-      info(test.desc);
-      yield test.run();
-
-      // Cleanup before the next test
-      expectNoObserverCalled();
-    }
-
-    yield ContentTask.spawn(gBrowser.selectedBrowser, null,
-                            function* () {
-      const Ci = Components.interfaces;
-      const Cc = Components.classes;
-      var registrar = Components.manager.QueryInterface(Ci.nsIComponentRegistrar);
-      let cid = Cc["@mozilla.org/network/protocol/about;1?what=loopconversation"];
-      registrar.unregisterFactory(cid,
-                                  registrar.getClassObject(cid, Ci.nsIFactory));
-      cid = Cc["@mozilla.org/network/protocol/about;1?what=evil"];
-      registrar.unregisterFactory(cid,
-                                  registrar.getClassObject(cid, Ci.nsIFactory));
-    });
-  }).then(finish, ex => {
-    ok(false, "Unexpected Exception: " + ex);
-    finish();
-  });
-}
--- a/browser/components/about/AboutRedirector.cpp
+++ b/browser/components/about/AboutRedirector.cpp
@@ -97,32 +97,16 @@ static RedirEntry kRedirMap[] = {
   { "downloads", "chrome://browser/content/downloads/contentAreaDownloadsView.xul",
     nsIAboutModule::ALLOW_SCRIPT },
 #ifdef MOZ_SERVICES_HEALTHREPORT
   { "healthreport", "chrome://browser/content/abouthealthreport/abouthealth.xhtml",
     nsIAboutModule::ALLOW_SCRIPT },
 #endif
   { "accounts", "chrome://browser/content/aboutaccounts/aboutaccounts.xhtml",
     nsIAboutModule::ALLOW_SCRIPT },
-  // Linkable because of indexeddb use (bug 1228118)
-  { "loopconversation", "chrome://loop/content/panels/conversation.html",
-    nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
-    nsIAboutModule::ALLOW_SCRIPT |
-    nsIAboutModule::HIDE_FROM_ABOUTABOUT |
-    nsIAboutModule::MAKE_LINKABLE |
-    nsIAboutModule::ENABLE_INDEXED_DB },
-  // Linkable because of indexeddb use (bug 1228118)
-  { "looppanel", "chrome://loop/content/panels/panel.html",
-    nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
-    nsIAboutModule::ALLOW_SCRIPT |
-    nsIAboutModule::HIDE_FROM_ABOUTABOUT |
-    nsIAboutModule::MAKE_LINKABLE |
-    nsIAboutModule::ENABLE_INDEXED_DB,
-    // Shares an IndexedDB origin with about:loopconversation.
-    "loopconversation" },
   { "reader", "chrome://global/content/reader/aboutReader.html",
     nsIAboutModule::URI_SAFE_FOR_UNTRUSTED_CONTENT |
     nsIAboutModule::ALLOW_SCRIPT |
     nsIAboutModule::URI_MUST_LOAD_IN_CHILD |
     nsIAboutModule::HIDE_FROM_ABOUTABOUT },
 };
 static const int kRedirTotal = ArrayLength(kRedirMap);
 
--- a/browser/components/build/nsModule.cpp
+++ b/browser/components/build/nsModule.cpp
@@ -103,18 +103,16 @@ static const mozilla::Module::ContractID
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "home", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "newtab", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "preferences", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "downloads", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "accounts", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
 #ifdef MOZ_SERVICES_HEALTHREPORT
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "healthreport", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
 #endif
-    { NS_ABOUT_MODULE_CONTRACTID_PREFIX "looppanel", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
-    { NS_ABOUT_MODULE_CONTRACTID_PREFIX "loopconversation", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
     { NS_ABOUT_MODULE_CONTRACTID_PREFIX "reader", &kNS_BROWSER_ABOUT_REDIRECTOR_CID },
 #if defined(XP_WIN)
     { NS_IEHISTORYENUMERATOR_CONTRACTID, &kNS_WINIEHISTORYENUMERATOR_CID },
 #elif defined(XP_MACOSX)
     { NS_SHELLSERVICE_CONTRACTID, &kNS_SHELLSERVICE_CID },
 #endif
     { nullptr }
 };
--- a/browser/components/customizableui/CustomizableUI.jsm
+++ b/browser/components/customizableui/CustomizableUI.jsm
@@ -59,17 +59,16 @@ const kSubviewEvents = [
 var kVersion = 6;
 
 /**
  * Buttons removed from built-ins by version they were removed. kVersion must be
  * bumped any time a new id is added to this. Use the button id as key, and
  * version the button is removed in as the value.  e.g. "pocket-button": 5
  */
 var ObsoleteBuiltinButtons = {
-  "loop-button": 5,
   "pocket-button": 6
 };
 
 /**
  * gPalette is a map of every widget that CustomizableUI.jsm knows about, keyed
  * on their IDs.
  */
 var gPalette = new Map();
@@ -233,17 +232,16 @@ var CustomizableUIInternal = {
     PanelWideWidgetTracker.init();
 
     let navbarPlacements = [
       "urlbar-container",
       "search-container",
       "bookmarks-menu-button",
       "downloads-button",
       "home-button",
-      "loop-button",
     ];
 
     if (AppConstants.MOZ_DEV_EDITION) {
       navbarPlacements.splice(2, 0, "developer-button");
     }
 
     if (Services.prefs.getBoolPref(kPrefWebIDEInNavbar)) {
       navbarPlacements.push("webide-button");
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -237,18 +237,16 @@
                      label="&showAllBookmarks2.label;"
                      class="subviewbutton panel-subview-footer"
                      command="Browser:ShowAllBookmarks"
                      onclick="PanelUI.hide();"/>
     </panelview>
 
     <panelview id="PanelUI-socialapi" flex="1"/>
 
-    <panelview id="PanelUI-loopapi" flex="1"/>
-
     <panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);">
       <label value="&feedsMenu2.label;" class="panel-subview-header"/>
     </panelview>
 
     <panelview id="PanelUI-containers" flex="1">
       <label value="&containersMenu.label;" class="panel-subview-header"/>
       <vbox id="PanelUI-containersItems"/>
     </panelview>
--- a/browser/components/extensions/ext-commands.js
+++ b/browser/components/extensions/ext-commands.js
@@ -121,17 +121,17 @@ CommandList.prototype = {
     // and it is currently ignored when set to the empty string.
     keyElement.setAttribute("oncommand", "//");
 
     /* eslint-disable mozilla/balanced-listeners */
     // We remove all references to the key elements when the extension is shutdown,
     // therefore the listeners for these elements will be garbage collected.
     keyElement.addEventListener("command", (event) => {
       if (name == "_execute_page_action") {
-        let win = event.target.ownerGlobal;
+        let win = event.target.ownerDocument.defaultView;
         pageActionFor(this.extension).triggerAction(win);
       } else {
         this.emit("command", name);
       }
     });
     /* eslint-enable mozilla/balanced-listeners */
 
     return keyElement;
--- a/browser/components/extensions/test/browser/browser_ext_commands_onCommand.js
+++ b/browser/components/extensions/test/browser/browser_ext_commands_onCommand.js
@@ -1,98 +1,229 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
+Cu.import("resource://gre/modules/AppConstants.jsm");
+
 add_task(function* test_user_defined_commands() {
+  const testCommands = [
+    // Ctrl Shortcuts
+    {
+      name: "toggle-ctrl-a",
+      shortcut: "Ctrl+A",
+      key: "A",
+      modifiers: {
+        accelKey: true,
+      },
+    },
+    {
+      name: "toggle-ctrl-up",
+      shortcut: "Ctrl+Up",
+      key: "VK_UP",
+      modifiers: {
+        accelKey: true,
+      },
+    },
+    // Alt Shortcuts
+    {
+      name: "toggle-alt-a",
+      shortcut: "Alt+A",
+      key: "A",
+      modifiers: {
+        altKey: true,
+      },
+    },
+    {
+      name: "toggle-alt-down",
+      shortcut: "Alt+Down",
+      key: "VK_DOWN",
+      modifiers: {
+        altKey: true,
+      },
+    },
+    // Mac Shortcuts
+    {
+      name: "toggle-command-shift-page-up",
+      shortcutMac: "Command+Shift+PageUp",
+      key: "VK_PAGE_UP",
+      modifiers: {
+        accelKey: true,
+        shiftKey: true,
+      },
+    },
+    {
+      name: "toggle-mac-control-shift+period",
+      shortcut: "Ctrl+Shift+Period",
+      shortcutMac: "MacCtrl+Shift+Period",
+      key: "VK_PERIOD",
+      modifiers: {
+        ctrlKey: true,
+        shiftKey: true,
+      },
+    },
+    // Ctrl+Shift Shortcuts
+    {
+      name: "toggle-ctrl-shift-left",
+      shortcut: "Ctrl+Shift+Left",
+      key: "VK_LEFT",
+      modifiers: {
+        accelKey: true,
+        shiftKey: true,
+      },
+    },
+    // Alt+Shift Shortcuts
+    {
+      name: "toggle-alt-shift-1",
+      shortcut: "Alt+Shift+1",
+      key: "1",
+      modifiers: {
+        altKey: true,
+        shiftKey: true,
+      },
+    },
+    {
+      name: "toggle-alt-shift-a",
+      shortcut: "Alt+Shift+A",
+      key: "A",
+      modifiers: {
+        altKey: true,
+        shiftKey: true,
+      },
+    },
+    {
+      name: "toggle-alt-shift-right",
+      shortcut: "Alt+Shift+Right",
+      key: "VK_RIGHT",
+      modifiers: {
+        altKey: true,
+        shiftKey: true,
+      },
+    },
+    // Misc Shortcuts
+    {
+      name: "valid-command-with-unrecognized-property-name",
+      shortcut: "Alt+Shift+3",
+      key: "3",
+      modifiers: {
+        altKey: true,
+        shiftKey: true,
+      },
+      unrecognized_property: "with-a-random-value",
+    },
+    {
+      name: "spaces-in-shortcut-name",
+      shortcut: "  Alt + Shift + 2  ",
+      key: "2",
+      modifiers: {
+        altKey: true,
+        shiftKey: true,
+      },
+    },
+  ];
+
   // Create a window before the extension is loaded.
   let win1 = yield BrowserTestUtils.openNewBrowserWindow();
   yield BrowserTestUtils.loadURI(win1.gBrowser.selectedBrowser, "about:robots");
   yield BrowserTestUtils.browserLoaded(win1.gBrowser.selectedBrowser);
 
+  let commands = {};
+  let isMac = AppConstants.platform == "macosx";
+  let totalMacOnlyCommands = 0;
+
+  for (let testCommand of testCommands) {
+    let command = {
+      suggested_key: {},
+    };
+
+    if (testCommand.shortcut) {
+      command.suggested_key.default = testCommand.shortcut;
+    }
+
+    if (testCommand.shortcutMac) {
+      command.suggested_key.mac = testCommand.shortcutMac;
+    }
+
+    if (testCommand.shortcutMac && !testCommand.shortcut) {
+      totalMacOnlyCommands++;
+    }
+
+    if (testCommand.unrecognized_property) {
+      command.unrecognized_property = testCommand.unrecognized_property;
+    }
+
+    commands[testCommand.name] = command;
+  }
+
   let extension = ExtensionTestUtils.loadExtension({
     manifest: {
-      "commands": {
-        "toggle-feature-using-alt-shift-3": {
-          "suggested_key": {
-            "default": "Alt+Shift+3",
-          },
-        },
-        "toggle-feature-using-alt-shift-comma": {
-          "suggested_key": {
-            "default": "Alt+Shift+Comma",
-          },
-          "unrecognized_property": "with-a-random-value",
-        },
-        "toggle-feature-with-whitespace-in-suggested-key": {
-          "suggested_key": {
-            "default": "  Alt + Shift + 2  ",
-          },
-        },
-      },
+      "commands": commands,
     },
 
     background: function() {
       browser.commands.onCommand.addListener(commandName => {
         browser.test.sendMessage("oncommand", commandName);
       });
       browser.test.sendMessage("ready");
     },
   });
 
-
   SimpleTest.waitForExplicitFinish();
   let waitForConsole = new Promise(resolve => {
     SimpleTest.monitorConsole(resolve, [{
       message: /Reading manifest: Error processing commands.*.unrecognized_property: An unexpected property was found/,
     }]);
   });
 
   yield extension.startup();
   yield extension.awaitMessage("ready");
 
+  function* runTest() {
+    for (let testCommand of testCommands) {
+      if (testCommand.shortcutMac && !testCommand.shortcut && !isMac) {
+        continue;
+      }
+      EventUtils.synthesizeKey(testCommand.key, testCommand.modifiers);
+      let message = yield extension.awaitMessage("oncommand");
+      is(message, testCommand.name, `Expected onCommand listener to fire with the correct name: ${testCommand.name}`);
+    }
+  }
+
   // Create another window after the extension is loaded.
   let win2 = yield BrowserTestUtils.openNewBrowserWindow();
   yield BrowserTestUtils.loadURI(win2.gBrowser.selectedBrowser, "about:config");
   yield BrowserTestUtils.browserLoaded(win2.gBrowser.selectedBrowser);
 
+  let totalTestCommands = Object.keys(testCommands).length;
+  let expectedCommandsRegistered = isMac ? totalTestCommands : totalTestCommands - totalMacOnlyCommands;
+
   // Confirm the keysets have been added to both windows.
   let keysetID = `ext-keyset-id-${makeWidgetId(extension.id)}`;
   let keyset = win1.document.getElementById(keysetID);
   ok(keyset != null, "Expected keyset to exist");
-  is(keyset.childNodes.length, 3, "Expected keyset to have 3 children");
+  is(keyset.childNodes.length, expectedCommandsRegistered, "Expected keyset to have the correct number of children");
 
   keyset = win2.document.getElementById(keysetID);
   ok(keyset != null, "Expected keyset to exist");
-  is(keyset.childNodes.length, 3, "Expected keyset to have 3 children");
+  is(keyset.childNodes.length, expectedCommandsRegistered, "Expected keyset to have the correct number of children");
 
   // Confirm that the commands are registered to both windows.
   yield focusWindow(win1);
-  EventUtils.synthesizeKey("3", {altKey: true, shiftKey: true});
-  let message = yield extension.awaitMessage("oncommand");
-  is(message, "toggle-feature-using-alt-shift-3", "Expected onCommand listener to fire with correct message");
+  yield runTest();
 
   yield focusWindow(win2);
-  EventUtils.synthesizeKey("VK_COMMA", {altKey: true, shiftKey: true});
-  message = yield extension.awaitMessage("oncommand");
-  is(message, "toggle-feature-using-alt-shift-comma", "Expected onCommand listener to fire with correct message");
-
-  EventUtils.synthesizeKey("2", {altKey: true, shiftKey: true});
-  message = yield extension.awaitMessage("oncommand");
-  is(message, "toggle-feature-with-whitespace-in-suggested-key", "Expected onCommand listener to fire with correct message");
+  yield runTest();
 
   yield extension.unload();
 
   // Confirm that the keysets have been removed from both windows after the extension is unloaded.
   keyset = win1.document.getElementById(keysetID);
   is(keyset, null, "Expected keyset to be removed from the window");
 
   keyset = win2.document.getElementById(keysetID);
   is(keyset, null, "Expected keyset to be removed from the window");
 
   yield BrowserTestUtils.closeWindow(win1);
   yield BrowserTestUtils.closeWindow(win2);
 
   SimpleTest.endMonitorConsole();
   yield waitForConsole;
 });
-
-
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -3365,16 +3365,19 @@ var SessionStoreInternal = {
     let window = aTab.ownerGlobal;
     let tabbrowser = window.gBrowser;
     let tabData = TabState.clone(aTab);
     let activeIndex = tabData.index - 1;
     let activePageData = tabData.entries[activeIndex] || null;
     let uri = activePageData ? activePageData.url || null : null;
     if (aLoadArguments) {
       uri = aLoadArguments.uri;
+      if (aLoadArguments.userContextId) {
+        browser.setAttribute("usercontextid", aLoadArguments.userContextId);
+      }
     }
 
     // We have to mark this tab as restoring first, otherwise
     // the "pending" attribute will be applied to the linked
     // browser, which removes it from the display list. We cannot
     // flip the remoteness of any browser that is not being displayed.
     this.markTabAsRestoring(aTab);
 
--- a/browser/components/uitour/UITour.jsm
+++ b/browser/components/uitour/UITour.jsm
@@ -148,64 +148,16 @@ this.UITour = {
     ["devtools",    {query: "#developer-button"}],
     ["help",        {query: "#PanelUI-help"}],
     ["home",        {query: "#home-button"}],
     ["forget", {
       allowAdd: true,
       query: "#panic-button",
       widgetName: "panic-button",
     }],
-    ["loop",        {
-      allowAdd: true,
-      query: "#loop-button",
-      widgetName: "loop-button",
-    }],
-    ["loop-newRoom", {
-      infoPanelPosition: "leftcenter topright",
-      query: (aDocument) => {
-        let loopUI = aDocument.defaultView.LoopUI;
-        // Use the parentElement full-width container of the button so our arrow
-        // doesn't overlap the panel contents much.
-        return loopUI.browser.contentDocument.querySelector(".new-room-button").parentElement;
-      },
-    }],
-    ["loop-roomList", {
-      infoPanelPosition: "leftcenter topright",
-      query: (aDocument) => {
-        let loopUI = aDocument.defaultView.LoopUI;
-        return loopUI.browser.contentDocument.querySelector(".room-list");
-      },
-    }],
-    ["loop-selectedRoomButtons", {
-      infoPanelOffsetY: -20,
-      infoPanelPosition: "start_after",
-      query: (aDocument) => {
-        let chatbox = aDocument.querySelector("chatbox[src^='about\:loopconversation'][selected]");
-
-        // Check that the real target actually exists
-        if (!chatbox || !chatbox.contentDocument ||
-            !chatbox.contentDocument.querySelector(".call-action-group")) {
-          return null;
-        }
-
-        // But anchor on the <browser> in the chatbox so the panel doesn't jump to undefined
-        // positions when the copy/email buttons disappear e.g. when the feedback form opens or
-        // somebody else joins the room.
-        return chatbox.content;
-      },
-    }],
-    ["loop-signInUpLink", {
-      query: (aDocument) => {
-        let loopBrowser = aDocument.defaultView.LoopUI.browser;
-        if (!loopBrowser) {
-          return null;
-        }
-        return loopBrowser.contentDocument.querySelector(".signin-link");
-      },
-    }],
     ["pocket", {
       allowAdd: true,
       query: "#pocket-button",
       widgetName: "pocket-button",
     }],
     ["privateWindow",  {query: "#privatebrowsing-button"}],
     ["quit",        {query: "#PanelUI-quit"}],
     ["readerMode-urlBar", {query: "#reader-mode-button"}],
@@ -890,26 +842,22 @@ this.UITour = {
     if (aTourPageClosing && openTourBrowsers) {
       openTourBrowsers.delete(aBrowser);
     }
 
     this.hideHighlight(aWindow);
     this.hideInfo(aWindow);
     // Ensure the menu panel is hidden before calling recreatePopup so popup events occur.
     this.hideMenu(aWindow, "appMenu");
-    this.hideMenu(aWindow, "loop");
     this.hideMenu(aWindow, "controlCenter");
 
     // Clean up panel listeners after calling hideMenu above.
     aWindow.PanelUI.panel.removeEventListener("popuphiding", this.hideAppMenuAnnotations);
     aWindow.PanelUI.panel.removeEventListener("ViewShowing", this.hideAppMenuAnnotations);
     aWindow.PanelUI.panel.removeEventListener("popuphidden", this.onPanelHidden);
-    let loopPanel = aWindow.document.getElementById("loop-notification-panel");
-    loopPanel.removeEventListener("popuphidden", this.onPanelHidden);
-    loopPanel.removeEventListener("popuphiding", this.hideLoopPanelAnnotations);
     let controlCenterPanel = aWindow.gIdentityHandler._identityPopup;
     controlCenterPanel.removeEventListener("popuphidden", this.onPanelHidden);
     controlCenterPanel.removeEventListener("popuphiding", this.hideControlCenterAnnotations);
 
     this.resetTheme();
 
     // If there are no more tour tabs left in the window, teardown the tour for the whole window.
     if (!openTourBrowsers || openTourBrowsers.size == 0) {
@@ -1730,41 +1678,16 @@ this.UITour = {
 
       this.recreatePopup(popup);
 
       // Open the control center
       if (aOpenCallback) {
         popup.addEventListener("popupshown", onPopupShown);
       }
       aWindow.document.getElementById("identity-box").click();
-    } else if (aMenuName == "loop") {
-      let toolbarButton = aWindow.LoopUI.toolbarButton;
-      // It's possible to have a node that isn't placed anywhere
-      if (!toolbarButton || !toolbarButton.node ||
-          !CustomizableUI.getPlacementOfWidget(toolbarButton.node.id)) {
-        log.debug("Can't show the Loop menu since the toolbarButton isn't placed");
-        return;
-      }
-
-      let panel = aWindow.document.getElementById("loop-notification-panel");
-      panel.setAttribute("noautohide", true);
-      if (panel.state != "open") {
-        this.recreatePopup(panel);
-        this.clearAvailableTargetsCache();
-      }
-
-      // An event object is expected but we don't want to toggle the panel with a click if the panel
-      // is already open.
-      aWindow.LoopUI.openPanel({ target: toolbarButton.node, }, "rooms").then(() => {
-        if (aOpenCallback) {
-          aOpenCallback();
-        }
-      });
-      panel.addEventListener("popuphidden", this.onPanelHidden);
-      panel.addEventListener("popuphiding", this.hideLoopPanelAnnotations);
     } else if (aMenuName == "pocket") {
       this.getTarget(aWindow, "pocket").then(Task.async(function* onPocketTarget(target) {
         let widgetGroupWrapper = CustomizableUI.getWidget(target.widgetName);
         if (widgetGroupWrapper.type != "view" || !widgetGroupWrapper.viewId) {
           log.error("Can't open the pocket menu without a view");
           return;
         }
         let placement = CustomizableUI.getPlacementOfWidget(target.widgetName);
@@ -1813,19 +1736,16 @@ this.UITour = {
     if (aMenuName == "appMenu") {
       aWindow.PanelUI.hide();
     } else if (aMenuName == "bookmarks") {
       let menuBtn = aWindow.document.getElementById("bookmarks-menu-button");
       closeMenuButton(menuBtn);
     } else if (aMenuName == "controlCenter") {
       let panel = aWindow.gIdentityHandler._identityPopup;
       panel.hidePopup();
-    } else if (aMenuName == "loop") {
-      let panel = aWindow.document.getElementById("loop-notification-panel");
-      panel.hidePopup();
     }
   },
 
   hideAnnotationsForPanel: function(aEvent, aTargetPositionCallback) {
     let win = aEvent.target.ownerGlobal;
     let annotationElements = new Map([
       // [annotationElement (panel), method to hide the annotation]
       [win.document.getElementById("UITourHighlightContainer"), UITour.hideHighlight.bind(UITour)],
@@ -1848,22 +1768,16 @@ this.UITour = {
     });
     UITour.appMenuOpenForAnnotation.clear();
   },
 
   hideAppMenuAnnotations: function(aEvent) {
     UITour.hideAnnotationsForPanel(aEvent, UITour.targetIsInAppMenu);
   },
 
-  hideLoopPanelAnnotations: function(aEvent) {
-    UITour.hideAnnotationsForPanel(aEvent, (aTarget) => {
-      return aTarget.targetName.startsWith("loop-") && aTarget.targetName != "loop-selectedRoomButtons";
-    });
-  },
-
   hideControlCenterAnnotations(aEvent) {
     UITour.hideAnnotationsForPanel(aEvent, (aTarget) => {
       return aTarget.targetName.startsWith("controlCenter-");
     });
   },
 
   onPanelHidden: function(aEvent) {
     aEvent.target.removeAttribute("noautohide");
@@ -1926,22 +1840,16 @@ this.UITour = {
         appinfo["canSetDefaultBrowserInBackground"] =
           canSetDefaultBrowserInBackground;
 
         this.sendPageCallback(aMessageManager, aCallbackID, appinfo);
         break;
       case "availableTargets":
         this.getAvailableTargets(aMessageManager, aWindow, aCallbackID);
         break;
-      case "loop":
-        const FTU_VERSION = 1;
-        this.sendPageCallback(aMessageManager, aCallbackID, {
-          gettingStartedSeen: (Services.prefs.getIntPref("loop.gettingStarted.latestFTUVersion") >= FTU_VERSION),
-        });
-        break;
       case "search":
       case "selectedSearchEngine":
         Services.search.init(rv => {
           let data;
           if (Components.isSuccessCode(rv)) {
             let engines = Services.search.getVisibleEngines();
             data = {
               searchEngineIdentifier: Services.search.defaultEngine.identifier,
@@ -1975,20 +1883,16 @@ this.UITour = {
         // be set, not unset.
         try {
           let shell = aWindow.getShellService();
           if (shell) {
             shell.setDefaultBrowser(true, false);
           }
         } catch (e) {}
         break;
-      case "Loop:ResumeTourOnFirstJoin":
-        // Ignore aValue in this case to avoid accidentally setting it to false.
-        Services.prefs.setBoolPref("loop.gettingStarted.resumeOnFirstJoin", true);
-        break;
       default:
         log.error("setConfiguration: Unknown configuration requested: " + aConfiguration);
         break;
     }
   },
 
   getAvailableTargets: function(aMessageManager, aChromeWindow, aCallbackID) {
     Task.spawn(function*() {
--- a/browser/components/uitour/test/browser.ini
+++ b/browser/components/uitour/test/browser.ini
@@ -26,19 +26,16 @@ skip-if = os == "linux" # Intermittent f
 [browser_UITour3.js]
 skip-if = os == "linux" # Linux: Bug 986760, Bug 989101.
 [browser_UITour_availableTargets.js]
 [browser_UITour_annotation_size_attributes.js]
 [browser_UITour_defaultBrowser.js]
 [browser_UITour_detach_tab.js]
 [browser_UITour_forceReaderMode.js]
 [browser_UITour_heartbeat.js]
-[browser_UITour_loop.js]
-skip-if = true # Bug 1225832 - New Loop architecture is not compatible with test.
-[browser_UITour_loop_panel.js]
 [browser_UITour_modalDialog.js]
 skip-if = os != "mac" # modal dialog disabling only working on OS X.
 [browser_UITour_observe.js]
 [browser_UITour_panel_close_annotation.js]
 skip-if = true # Disabled due to frequent failures, bugs 1026310 and 1032137
 [browser_UITour_pocket.js]
 skip-if = true # Disabled pending removal of pocket UI Tour
 [browser_UITour_registerPageID.js]
--- a/browser/components/uitour/test/browser_UITour_availableTargets.js
+++ b/browser/components/uitour/test/browser_UITour_availableTargets.js
@@ -16,17 +16,16 @@ add_UITour_task(function* test_available
     "accountStatus",
     "addons",
     "appMenu",
     "backForward",
     "bookmarks",
     "customize",
     "help",
     "home",
-    "loop",
     "devtools",
       ...(hasPocket ? ["pocket"] : []),
     "privateWindow",
     "quit",
     "readerMode-urlBar",
     "search",
     "searchIcon",
     "trackingProtection",
@@ -45,17 +44,16 @@ add_UITour_task(function* test_available
   let data = yield getConfigurationPromise("availableTargets");
   ok_targets(data, [
     "accountStatus",
     "addons",
     "appMenu",
     "backForward",
     "customize",
     "help",
-    "loop",
     "devtools",
     "home",
       ...(hasPocket ? ["pocket"] : []),
     "privateWindow",
     "quit",
     "readerMode-urlBar",
     "search",
     "searchIcon",
@@ -81,17 +79,16 @@ add_UITour_task(function* test_available
     "accountStatus",
     "addons",
     "appMenu",
     "backForward",
     "bookmarks",
     "customize",
     "help",
     "home",
-    "loop",
     "devtools",
       ...(hasPocket ? ["pocket"] : []),
     "privateWindow",
     "quit",
     "readerMode-urlBar",
     "trackingProtection",
     "urlbar",
       ...(hasWebIDE ? ["webide"] : [])
deleted file mode 100644
--- a/browser/components/uitour/test/browser_UITour_loop.js
+++ /dev/null
@@ -1,414 +0,0 @@
-/* Any copyright is dedicated to the Public Domain.
- * http://creativecommons.org/publicdomain/zero/1.0/ */
-
-"use strict";
-
-var gTestTab;
-var gContentAPI;
-var gContentWindow;
-var gMessageHandlers;
-var loopButton;
-var fakeRoom;
-var loopPanel = document.getElementById("loop-notification-panel");
-
-const { LoopAPI } = Cu.import("chrome://loop/content/modules/MozLoopAPI.jsm", {});
-const { LoopRooms } = Cu.import("chrome://loop/content/modules/LoopRooms.jsm", {});
-const { MozLoopServiceInternal } = Cu.import("chrome://loop/content/modules/MozLoopService.jsm", {});
-
-const FTU_VERSION = 1;
-
-function test() {
-  UITourTest();
-}
-
-function runOffline(fun) {
-  return (done) => {
-    Services.io.offline = true;
-    fun(function onComplete() {
-      Services.io.offline = false;
-      done();
-    });
-  }
-}
-
-var tests = [
-  taskify(function* test_gettingStartedClicked_linkOpenedWithExpectedParams() {
-    // Set latestFTUVersion to lower number to show FTU panel.
-    Services.prefs.setIntPref("loop.gettingStarted.latestFTUVersion", 0);
-    Services.prefs.setCharPref("loop.gettingStarted.url", "http://example.com");
-    is(loopButton.open, false, "Menu should initially be closed");
-    loopButton.click();
-
-    yield waitForConditionPromise(() => {
-      return loopButton.open;
-    }, "Menu should be visible after showMenu()");
-
-    gContentAPI.registerPageID("hello-tour_OpenPanel_testPage");
-    yield new Promise(resolve => {
-      gContentAPI.ping(() => resolve());
-    });
-
-    let loopDoc = document.getElementById("loop-notification-panel").children[0].contentDocument;
-    yield waitForConditionPromise(() => {
-      return loopDoc.readyState == 'complete';
-    }, "Loop notification panel document should be fully loaded.", 50);
-    let gettingStartedButton = loopDoc.getElementById("fte-button");
-    ok(gettingStartedButton, "Getting Started button should be found");
-
-    let newTabPromise = waitForConditionPromise(() => {
-      return gBrowser.currentURI.path.includes("utm_source=firefox-browser");
-    }, "New tab with utm_content=testPageNewID should have opened");
-
-    gettingStartedButton.click();
-    yield newTabPromise;
-    ok(gBrowser.currentURI.path.includes("utm_content=hello-tour_OpenPanel_testPage"),
-        "Expected URL opened (" + gBrowser.currentURI.path + ")");
-    yield gBrowser.removeCurrentTab();
-
-    checkLoopPanelIsHidden();
-  }),
-  taskify(function* test_gettingStartedClicked_linkOpenedWithExpectedParams2() {
-    // Set latestFTUVersion to lower number to show FTU panel.
-    Services.prefs.setIntPref("loop.gettingStarted.latestFTUVersion", 0);
-    // Force a refresh of the loop panel since going from seen -> unseen doesn't trigger
-    // automatic re-rendering.
-    let loopWin = document.getElementById("loop-notification-panel").children[0].contentWindow;
-    var event = new loopWin.CustomEvent("GettingStartedSeen", { detail: false });
-    loopWin.dispatchEvent(event);
-
-    UITour.pageIDsForSession.clear();
-    Services.prefs.setCharPref("loop.gettingStarted.url", "http://example.com");
-    is(loopButton.open, false, "Menu should initially be closed");
-    loopButton.click();
-
-    yield waitForConditionPromise(() => {
-      return loopButton.open;
-    }, "Menu should be visible after showMenu()");
-
-
-    gContentAPI.registerPageID("hello-tour_OpenPanel_testPageOldId");
-    yield new Promise(resolve => {
-      gContentAPI.ping(() => resolve());
-    });
-    // Set the time of the page ID to 10 hours earlier, so that it is considered "expired".
-    UITour.pageIDsForSession.set("hello-tour_OpenPanel_testPageOldId",
-                                   {lastSeen: Date.now() - (10 * 60 * 60 * 1000)});
-
-    let loopDoc = loopWin.document;
-    let gettingStartedButton = loopDoc.getElementById("fte-button");
-    ok(gettingStartedButton, "Getting Started button should be found");
-
-    let newTabPromise = waitForConditionPromise(() => {
-      Services.console.logStringMessage(gBrowser.currentURI.path);
-      return gBrowser.currentURI.path.includes("utm_source=firefox-browser");
-    }, "New tab with utm_content=testPageNewID should have opened");
-
-    gettingStartedButton.click();
-    yield newTabPromise;
-    ok(!gBrowser.currentURI.path.includes("utm_content=hello-tour_OpenPanel_testPageOldId"),
-       "Expected URL opened without the utm_content parameter (" +
-        gBrowser.currentURI.path + ")");
-    yield gBrowser.removeCurrentTab();
-
-    checkLoopPanelIsHidden();
-  }),
-  // Test the menu was cleaned up in teardown.
-  taskify(function* setup_menu_cleanup() {
-    gContentAPI.showMenu("loop");
-
-    yield waitForConditionPromise(() => {
-      return loopButton.open;
-    }, "Menu should be visible after showMenu()");
-
-    // Leave it open so it gets torn down and we can test below that teardown was succesful.
-  }),
-  taskify(function* test_menu_cleanup() {
-    // Test that the open menu from above was torn down fully.
-    checkLoopPanelIsHidden();
-  }),
-  function test_availableTargets(done) {
-    gContentAPI.showMenu("loop");
-    gContentAPI.getConfiguration("availableTargets", (data) => {
-      for (let targetName of ["loop-newRoom", "loop-roomList", "loop-signInUpLink"]) {
-        isnot(data.targets.indexOf(targetName), -1, targetName + " should exist");
-      }
-      done();
-    });
-  },
-  function test_getConfigurationLoop(done) {
-    let gettingStartedSeen = Services.prefs.getIntPref("loop.gettingStarted.latestFTUVersion") >= FTU_VERSION;
-    gContentAPI.getConfiguration("loop", (data) => {
-      is(data.gettingStartedSeen, gettingStartedSeen,
-         "The configuration property should equal that of the pref");
-      done();
-    });
-  },
-  function test_hideMenuHidesAnnotations(done) {
-    let infoPanel = document.getElementById("UITourTooltip");
-    let highlightPanel = document.getElementById("UITourHighlightContainer");
-
-    gContentAPI.showMenu("loop", function menuCallback() {
-      gContentAPI.showHighlight("loop-roomList");
-      gContentAPI.showInfo("loop-newRoom", "Make a new room", "AKA. conversation");
-      UITour.getTarget(window, "loop-newRoom").then((target) => {
-        waitForPopupAtAnchor(infoPanel, target.node, Task.async(function* checkPanelIsOpen() {
-          isnot(loopPanel.state, "closed", "Loop panel should still be open");
-          ok(loopPanel.hasAttribute("noautohide"), "@noautohide should still be on the loop panel");
-          is(highlightPanel.getAttribute("targetName"), "loop-roomList", "Check highlight @targetname");
-          is(infoPanel.getAttribute("targetName"), "loop-newRoom", "Check info panel @targetname");
-
-          info("Close the loop menu and make sure the annotations inside disappear");
-          let hiddenPromises = [promisePanelElementHidden(window, infoPanel),
-                                promisePanelElementHidden(window, highlightPanel)];
-          gContentAPI.hideMenu("loop");
-          yield Promise.all(hiddenPromises);
-          isnot(infoPanel.state, "open", "Info panel should have automatically hid");
-          isnot(highlightPanel.state, "open", "Highlight panel should have automatically hid");
-          done();
-        }), "Info panel should be anchored to the new room button");
-      });
-    });
-  },
-  runOffline(function test_notifyLoopChatWindowOpenedClosed(done) {
-    gContentAPI.observe((event, params) => {
-      is(event, "Loop:ChatWindowOpened", "Check Loop:ChatWindowOpened notification");
-      gContentAPI.observe((event, params) => {
-        is(event, "Loop:ChatWindowShown", "Check Loop:ChatWindowShown notification");
-        gContentAPI.observe((event, params) => {
-          is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification");
-          gContentAPI.observe((event, params) => {
-            ok(false, "No more notifications should have arrived");
-          });
-        });
-        done();
-      });
-      document.querySelector("#pinnedchats > chatbox").close();
-    });
-    LoopRooms.open("fakeTourRoom");
-  }),
-  runOffline(function test_notifyLoopRoomURLCopied(done) {
-    gContentAPI.observe((event, params) => {
-      is(event, "Loop:ChatWindowOpened", "Loop chat window should've opened");
-      gContentAPI.observe((event, params) => {
-        is(event, "Loop:ChatWindowShown", "Check Loop:ChatWindowShown notification");
-
-        let chat = document.querySelector("#pinnedchats > chatbox");
-        gContentAPI.observe((event, params) => {
-          is(event, "Loop:RoomURLCopied", "Check Loop:RoomURLCopied notification");
-          gContentAPI.observe((event, params) => {
-            is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification");
-          });
-          chat.close();
-          done();
-        });
-
-        let window = chat.content.contentWindow;
-        waitForConditionPromise(
-          () => chat.content.contentDocument.querySelector(".btn-copy"),
-          "Copy button should be there"
-        ).then(() => chat.content.contentDocument.querySelector(".btn-copy").click());
-      });
-    });
-    LoopRooms.open("fakeTourRoom");
-  }),
-  runOffline(function test_notifyLoopRoomURLEmailed(done) {
-    gContentAPI.observe((event, params) => {
-      is(event, "Loop:ChatWindowOpened", "Loop chat window should've opened");
-      gContentAPI.observe((event, params) => {
-        is(event, "Loop:ChatWindowShown", "Check Loop:ChatWindowShown notification");
-
-        let chat = document.querySelector("#pinnedchats > chatbox");
-        let composeEmailCalled = false;
-
-        gContentAPI.observe((event, params) => {
-          is(event, "Loop:RoomURLEmailed", "Check Loop:RoomURLEmailed notification");
-          ok(composeEmailCalled, "mozLoop.composeEmail should be called");
-          gContentAPI.observe((event, params) => {
-            is(event, "Loop:ChatWindowClosed", "Check Loop:ChatWindowClosed notification");
-          });
-          chat.close();
-          done();
-        });
-
-        gMessageHandlers.ComposeEmail = function(message, reply) {
-          let [subject, body, recipient] = message.data;
-          ok(subject, "composeEmail should be invoked with at least a subject value");
-          composeEmailCalled = true;
-          reply();
-        };
-
-        waitForConditionPromise(
-          () => chat.content.contentDocument.querySelector(".btn-email"),
-          "Email button should be there"
-        ).then(() => chat.content.contentDocument.querySelector(".btn-email").click());
-      });
-    });
-    LoopRooms.open("fakeTourRoom");
-  }),
-  taskify(function* test_arrow_panel_position() {
-    is(loopButton.open, false, "Menu should initially be closed");
-    let popup = document.getElementById("UITourTooltip");
-
-    yield showMenuPromise("loop");
-
-    let currentTarget = "loop-newRoom";
-    yield showInfoPromise(currentTarget, "This is " + currentTarget, "My arrow should be on the side");
-    is(popup.popupBoxObject.alignmentPosition, "start_before", "Check " + currentTarget + " position");
-
-    currentTarget = "loop-roomList";
-    yield showInfoPromise(currentTarget, "This is " + currentTarget, "My arrow should be on the side");
-    is(popup.popupBoxObject.alignmentPosition, "start_before", "Check " + currentTarget + " position");
-
-    currentTarget = "loop-signInUpLink";
-    yield showInfoPromise(currentTarget, "This is " + currentTarget, "My arrow should be underneath");
-    is(popup.popupBoxObject.alignmentPosition, "after_end", "Check " + currentTarget + " position");
-  }),
-  taskify(function* test_setConfiguration() {
-    is(Services.prefs.getBoolPref("loop.gettingStarted.resumeOnFirstJoin"), false, "pref should be false but exist");
-    gContentAPI.setConfiguration("Loop:ResumeTourOnFirstJoin", true);
-
-    yield waitForConditionPromise(() => {
-      return Services.prefs.getBoolPref("loop.gettingStarted.resumeOnFirstJoin");
-    }, "Pref should change to true via setConfiguration");
-
-    Services.prefs.clearUserPref("loop.gettingStarted.resumeOnFirstJoin");
-  }),
-  taskify(function* test_resumeViaMenuPanel_roomClosedTabOpen() {
-    Services.prefs.setBoolPref("loop.gettingStarted.resumeOnFirstJoin", true);
-
-    // Create a fake room and then add a fake non-owner participant
-    let roomsMap = setupFakeRoom();
-    roomsMap.get("fakeTourRoom").participants = [{
-      owner: false,
-    }];
-
-    // Set the tour URL to be the current page with a different query param
-    let gettingStartedURL = gTestTab.linkedBrowser.currentURI.resolve("?gettingstarted=1");
-    Services.prefs.setCharPref("loop.gettingStarted.url", gettingStartedURL);
-
-    let observationPromise = new Promise((resolve) => {
-      gContentAPI.observe((event, params) => {
-        is(event, "Loop:IncomingConversation", "Page should have been notified about incoming conversation");
-        is(params.conversationOpen, false, "conversationOpen should be false");
-        is(gBrowser.selectedTab, gTestTab, "The same tab should be selected");
-        resolve();
-      });
-    });
-
-    // Now open the menu while that non-owner is in the fake room to trigger resuming the tour
-    yield showMenuPromise("loop");
-
-    yield observationPromise;
-    Services.prefs.clearUserPref("loop.gettingStarted.resumeOnFirstJoin");
-  }),
-  taskify(function* test_resumeViaMenuPanel_roomClosedTabClosed() {
-    Services.prefs.setBoolPref("loop.gettingStarted.resumeOnFirstJoin", true);
-
-    // Create a fake room and then add a fake non-owner participant
-    let roomsMap = setupFakeRoom();
-    roomsMap.get("fakeTourRoom").participants = [{
-      owner: false,
-    }];
-
-    // Set the tour URL to a page that's not open yet
-    Services.prefs.setCharPref("loop.gettingStarted.url", gBrowser.currentURI.prePath);
-
-    let newTabPromise = waitForConditionPromise(() => {
-      return gBrowser.currentURI.path.includes("incomingConversation=waiting");
-    }, "New tab with incomingConversation=waiting should have opened");
-
-    // Now open the menu while that non-owner is in the fake room to trigger resuming the tour
-    yield showMenuPromise("loop");
-
-    yield newTabPromise;
-
-    yield gBrowser.removeCurrentTab();
-    Services.prefs.clearUserPref("loop.gettingStarted.resumeOnFirstJoin");
-  }),
-];
-
-// End tests
-
-function checkLoopPanelIsHidden() {
-  ok(!loopPanel.hasAttribute("noautohide"), "@noautohide on the loop panel should have been cleaned up");
-  ok(!loopPanel.hasAttribute("panelopen"), "The panel shouldn't have @panelopen");
-  isnot(loopPanel.state, "open", "The panel shouldn't be open");
-  is(loopButton.hasAttribute("open"), false, "Loop button should know that the panel is closed");
-}
-
-function setupFakeRoom() {
-  let room = Object.create(fakeRoom);
-  let roomsMap = new Map([
-    [room.roomToken, room]
-  ]);
-  LoopRooms.stubCache(roomsMap);
-  return roomsMap;
-}
-
-if (Services.prefs.getBoolPref("loop.enabled")) {
-  loopButton = window.LoopUI.toolbarButton.node;
-
-  fakeRoom = {
-    decryptedContext: { roomName: "fakeTourRoom" },
-    participants: [],
-    maxSize: 2,
-    ctime: Date.now()
-  };
-  for (let prop of ["roomToken", "roomOwner", "roomUrl"])
-    fakeRoom[prop] = "fakeTourRoom";
-
-  LoopAPI.stubMessageHandlers(gMessageHandlers = {
-    // Stub the rooms object API to fully control the test behavior.
-    "Rooms:*": function(action, message, reply) {
-      switch (action.split(":").pop()) {
-        case "GetAll":
-          reply([fakeRoom]);
-          break;
-        case "Get":
-          reply(fakeRoom);
-          break;
-        case "Join":
-          reply({
-            apiKey: "fakeTourRoom",
-            sessionToken: "fakeTourRoom",
-            sessionId: "fakeTourRoom",
-            expires: Date.now() + 240000
-          });
-          break;
-        case "RefreshMembership":
-          reply({ expires: Date.now() + 240000 });
-        default:
-          reply();
-      }
-    },
-    // Stub the metadata retrieval to suppress console warnings and return faster.
-    GetSelectedTabMetadata: function(message, reply) {
-      reply({ favicon: null });
-    }
-  });
-
-  registerCleanupFunction(() => {
-    Services.prefs.clearUserPref("loop.gettingStarted.resumeOnFirstJoin");
-    Services.prefs.clearUserPref("loop.gettingStarted.latestFTUVersion");
-    Services.prefs.clearUserPref("loop.gettingStarted.url");
-    Services.io.offline = false;
-
-    // Copied from browser/components/loop/test/mochitest/head.js
-    // Remove the iframe after each test. This also avoids mochitest complaining
-    // about leaks on shutdown as we intentionally hold the iframe open for the
-    // life of the application.
-    let frameId = loopButton.getAttribute("notificationFrameId");
-    let frame = document.getElementById(frameId);
-    if (frame) {
-      frame.remove();
-    }
-
-    // Remove the stubbed rooms.
-    LoopRooms.stubCache(null);
-    // Restore the stubbed handlers.
-    LoopAPI.restore();
-  });
-} else {
-  ok(true, "Loop is disabled so skip the UITour Loop tests");
-  tests = [];
-}
deleted file mode 100644
--- a/browser/components/uitour/test/browser_UITour_loop_panel.js
+++ /dev/null
@@ -1,67 +0,0 @@
-"use strict";
-
-var gTestTab;
-var gContentAPI;
-var gContentWindow;
-var gMessageHandlers;
-var loopButton;
-var fakeRoom;
-var loopPanel = document.getElementById("loop-notification-panel");
-
-const { LoopAPI } = Cu.import("chrome://loop/content/modules/MozLoopAPI.jsm", {});
-const { LoopRooms } = Cu.import("chrome://loop/content/modules/LoopRooms.jsm", {});
-
-if (!Services.prefs.getBoolPref("loop.enabled")) {
-  ok(true, "Loop is disabled so skip the UITour Loop tests");
-} else {
-  function checkLoopPanelIsHidden() {
-    ok(!loopPanel.hasAttribute("noautohide"), "@noautohide on the loop panel should have been cleaned up");
-    ok(!loopPanel.hasAttribute("panelopen"), "The panel shouldn't have @panelopen");
-    isnot(loopPanel.state, "open", "The panel shouldn't be open");
-    is(loopButton.hasAttribute("open"), false, "Loop button should know that the panel is closed");
-  }
-
-  add_task(setup_UITourTest);
-
-  add_task(function() {
-    loopButton = window.LoopUI.toolbarButton.node;
-
-    registerCleanupFunction(() => {
-      Services.prefs.clearUserPref("loop.gettingStarted.latestFTUVersion");
-      Services.io.offline = false;
-
-      // Copied from browser/components/loop/test/mochitest/head.js
-      // Remove the iframe after each test. This also avoids mochitest complaining
-      // about leaks on shutdown as we intentionally hold the iframe open for the
-      // life of the application.
-      let frameId = loopButton.getAttribute("notificationFrameId");
-      let frame = document.getElementById(frameId);
-      if (frame) {
-        frame.remove();
-      }
-    });
-  });
-
-  add_UITour_task(function* test_menu_show_hide() {
-    // The targets to highlight only appear after getting started is launched.
-    // Set latestFTUVersion to lower number to show FTU panel.
-    Services.prefs.setIntPref("loop.gettingStarted.latestFTUVersion", 0);
-    is(loopButton.open, false, "Menu should initially be closed");
-    gContentAPI.showMenu("loop");
-
-    yield waitForConditionPromise(() => {
-      return loopPanel.state == "open";
-    }, "Menu should be visible after showMenu()");
-
-    ok(loopPanel.hasAttribute("noautohide"), "@noautohide should be on the loop panel");
-    ok(loopPanel.hasAttribute("panelopen"), "The panel should have @panelopen");
-    ok(loopButton.hasAttribute("open"), "Loop button should know that the menu is open");
-
-    gContentAPI.hideMenu("loop");
-    yield waitForConditionPromise(() => {
-        return !loopButton.open;
-    }, "Menu should be hidden after hideMenu()");
-
-    checkLoopPanelIsHidden();
-  });
-}
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() {