Bug 1232707 - General renames and deletes preparing for Loop being imported from external repo. r=mikedeboer
authorMark Banner <standard8@mozilla.com>
Thu, 14 Jan 2016 17:53:34 +0000
changeset 280128 55af065de40efae8994228830bbb8daeabf595b5
parent 280127 adbce5cdc59284f846ef6efd3f0ecd773fbe94e7
child 280129 18cbd790875ff7b6fd5ed221a457c31d543d25ed
push id70334
push usercbook@mozilla.com
push dateFri, 15 Jan 2016 10:48:53 +0000
treeherdermozilla-inbound@de9a0fc7828d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmikedeboer
bugs1232707
milestone46.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1232707 - General renames and deletes preparing for Loop being imported from external repo. r=mikedeboer
browser/extensions/loop/.eslintrc
browser/extensions/loop/.eslintrc-gecko
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/panels/conversation.html
browser/extensions/loop/chrome/content/panels/css/panel.css
browser/extensions/loop/chrome/content/panels/js/.eslintrc
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/feedbackViews.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/panel.html
browser/extensions/loop/chrome/content/panels/test/.eslintrc
browser/extensions/loop/chrome/content/panels/test/README.md
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/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/test_desktop_all.py
browser/extensions/loop/chrome/content/panels/vendor/l10n.js
browser/extensions/loop/chrome/content/preferences/prefs.js
browser/extensions/loop/chrome/content/shared/README.md
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/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.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/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-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-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/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/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.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/models.js
browser/extensions/loop/chrome/content/shared/js/otSdkDriver.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/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/models_test.js
browser/extensions/loop/chrome/content/shared/test/otSdkDriver_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/views_test.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/skin/linux/menuPanel.png
browser/extensions/loop/chrome/skin/linux/menuPanel@2x.png
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-win10.png
browser/extensions/loop/chrome/skin/windows/toolbar-win10@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_fxa_login.js
browser/extensions/loop/chrome/test/mochitest/browser_loop_fxa_server.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_sharingListeners.js
browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_socialShare.js
browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_telemetry.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_doNotDisturb.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/content/modules/.eslintrc
browser/extensions/loop/content/modules/LoopRooms.jsm
browser/extensions/loop/content/modules/LoopRoomsCache.jsm
browser/extensions/loop/content/modules/MozLoopAPI.jsm
browser/extensions/loop/content/modules/MozLoopPushHandler.jsm
browser/extensions/loop/content/modules/MozLoopService.jsm
browser/extensions/loop/content/modules/MozLoopWorker.js
browser/extensions/loop/content/panels/conversation.html
browser/extensions/loop/content/panels/css/panel.css
browser/extensions/loop/content/panels/js/.eslintrc
browser/extensions/loop/content/panels/js/conversation.js
browser/extensions/loop/content/panels/js/conversation.jsx
browser/extensions/loop/content/panels/js/conversationAppStore.js
browser/extensions/loop/content/panels/js/feedbackViews.js
browser/extensions/loop/content/panels/js/feedbackViews.jsx
browser/extensions/loop/content/panels/js/otconfig.js
browser/extensions/loop/content/panels/js/panel.js
browser/extensions/loop/content/panels/js/panel.jsx
browser/extensions/loop/content/panels/js/roomStore.js
browser/extensions/loop/content/panels/js/roomViews.js
browser/extensions/loop/content/panels/js/roomViews.jsx
browser/extensions/loop/content/panels/panel.html
browser/extensions/loop/content/panels/vendor/l10n.js
browser/extensions/loop/content/preferences/prefs.js
browser/extensions/loop/content/shared/README.md
browser/extensions/loop/content/shared/css/common.css
browser/extensions/loop/content/shared/css/conversation.css
browser/extensions/loop/content/shared/css/reset.css
browser/extensions/loop/content/shared/img/02.png
browser/extensions/loop/content/shared/img/02@2x.png
browser/extensions/loop/content/shared/img/animated-spinner.svg
browser/extensions/loop/content/shared/img/audio-call-avatar.svg
browser/extensions/loop/content/shared/img/audio-default-16x16@1.5x.png
browser/extensions/loop/content/shared/img/audio-default-16x16@2x.png
browser/extensions/loop/content/shared/img/audio-hover.svg
browser/extensions/loop/content/shared/img/audio-mute-hover.svg
browser/extensions/loop/content/shared/img/audio-mute.svg
browser/extensions/loop/content/shared/img/audio.svg
browser/extensions/loop/content/shared/img/avatars.svg
browser/extensions/loop/content/shared/img/beta-ribbon.svg
browser/extensions/loop/content/shared/img/cam_audio-no.svg
browser/extensions/loop/content/shared/img/cam_audio.svg
browser/extensions/loop/content/shared/img/cam_audio_h.svg
browser/extensions/loop/content/shared/img/chatbubble-arrow-left.svg
browser/extensions/loop/content/shared/img/chatbubble-arrow-right.svg
browser/extensions/loop/content/shared/img/check.svg
browser/extensions/loop/content/shared/img/ellipsis-v.svg
browser/extensions/loop/content/shared/img/empty_conversations.svg
browser/extensions/loop/content/shared/img/empty_search.svg
browser/extensions/loop/content/shared/img/exit.svg
browser/extensions/loop/content/shared/img/facemute-14x14.png
browser/extensions/loop/content/shared/img/facemute-14x14@2x.png
browser/extensions/loop/content/shared/img/firefox-avatar.svg
browser/extensions/loop/content/shared/img/firefox-logo.png
browser/extensions/loop/content/shared/img/glyph-email-16x16.svg
browser/extensions/loop/content/shared/img/glyph-facebook-16x16.svg
browser/extensions/loop/content/shared/img/glyph-help-16x16.svg
browser/extensions/loop/content/shared/img/glyph-link-16x16.svg
browser/extensions/loop/content/shared/img/glyph-user-16x16.svg
browser/extensions/loop/content/shared/img/hangup-inverse-14x14.png
browser/extensions/loop/content/shared/img/hangup-inverse-14x14@2x.png
browser/extensions/loop/content/shared/img/happy.png
browser/extensions/loop/content/shared/img/hello-web-share.svg
browser/extensions/loop/content/shared/img/hello_logo.svg
browser/extensions/loop/content/shared/img/helloicon.svg
browser/extensions/loop/content/shared/img/icon_32.png
browser/extensions/loop/content/shared/img/icon_64.png
browser/extensions/loop/content/shared/img/icons-10x10.svg
browser/extensions/loop/content/shared/img/icons-14x14.svg
browser/extensions/loop/content/shared/img/icons-16x16.svg
browser/extensions/loop/content/shared/img/media-group-left-hover.svg
browser/extensions/loop/content/shared/img/media-group-right-hover.svg
browser/extensions/loop/content/shared/img/media-group.svg
browser/extensions/loop/content/shared/img/movistar.png
browser/extensions/loop/content/shared/img/movistar@2x.png
browser/extensions/loop/content/shared/img/mute-inverse-14x14.png
browser/extensions/loop/content/shared/img/mute-inverse-14x14@2x.png
browser/extensions/loop/content/shared/img/pause-12x12.svg
browser/extensions/loop/content/shared/img/play-12x12.svg
browser/extensions/loop/content/shared/img/sad.png
browser/extensions/loop/content/shared/img/sad_hello_icon_64x64.svg
browser/extensions/loop/content/shared/img/settings-hover.svg
browser/extensions/loop/content/shared/img/settings.svg
browser/extensions/loop/content/shared/img/sharing-active.svg
browser/extensions/loop/content/shared/img/sharing-hover.svg
browser/extensions/loop/content/shared/img/sharing-pending.svg
browser/extensions/loop/content/shared/img/sharing.svg
browser/extensions/loop/content/shared/img/spinner.png
browser/extensions/loop/content/shared/img/spinner.svg
browser/extensions/loop/content/shared/img/spinner@2x.png
browser/extensions/loop/content/shared/img/stop-12x12.svg
browser/extensions/loop/content/shared/img/telefonica-logo.svg
browser/extensions/loop/content/shared/img/telefonica.png
browser/extensions/loop/content/shared/img/telefonica@2x.png
browser/extensions/loop/content/shared/img/video-hover.svg
browser/extensions/loop/content/shared/img/video-mute-hover.svg
browser/extensions/loop/content/shared/img/video-mute.svg
browser/extensions/loop/content/shared/img/video.svg
browser/extensions/loop/content/shared/img/vivo.png
browser/extensions/loop/content/shared/img/vivo@2x.png
browser/extensions/loop/content/shared/js/actions.js
browser/extensions/loop/content/shared/js/activeRoomStore.js
browser/extensions/loop/content/shared/js/crypto.js
browser/extensions/loop/content/shared/js/dispatcher.js
browser/extensions/loop/content/shared/js/linkifiedTextView.js
browser/extensions/loop/content/shared/js/linkifiedTextView.jsx
browser/extensions/loop/content/shared/js/loopapi-client.js
browser/extensions/loop/content/shared/js/mixins.js
browser/extensions/loop/content/shared/js/models.js
browser/extensions/loop/content/shared/js/otSdkDriver.js
browser/extensions/loop/content/shared/js/store.js
browser/extensions/loop/content/shared/js/textChatStore.js
browser/extensions/loop/content/shared/js/textChatView.js
browser/extensions/loop/content/shared/js/textChatView.jsx
browser/extensions/loop/content/shared/js/urlRegExps.js
browser/extensions/loop/content/shared/js/utils.js
browser/extensions/loop/content/shared/js/validate.js
browser/extensions/loop/content/shared/js/views.js
browser/extensions/loop/content/shared/js/views.jsx
browser/extensions/loop/content/shared/sounds/connected.ogg
browser/extensions/loop/content/shared/sounds/connecting.ogg
browser/extensions/loop/content/shared/sounds/failure.ogg
browser/extensions/loop/content/shared/sounds/message.ogg
browser/extensions/loop/content/shared/sounds/ringtone.ogg
browser/extensions/loop/content/shared/sounds/room-joined-in.ogg
browser/extensions/loop/content/shared/sounds/room-joined.ogg
browser/extensions/loop/content/shared/sounds/room-left.ogg
browser/extensions/loop/content/shared/sounds/terminated.ogg
browser/extensions/loop/content/shared/vendor/backbone-1.2.1.js
browser/extensions/loop/content/shared/vendor/classnames-2.2.0.js
browser/extensions/loop/content/shared/vendor/lodash-3.9.3.js
browser/extensions/loop/content/shared/vendor/react-0.13.3-prod.js
browser/extensions/loop/content/shared/vendor/react-0.13.3.js
browser/extensions/loop/content/shared/vendor/sdk-content/css/ot.css
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/access-denied-chrome.png
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/access-denied-copy-firefox.png
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/access-denied-firefox.png
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/access-predenied-chrome.png
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/access-prompt-chrome.png
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/audioonly-publisher.png
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/audioonly-subscriber.png
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/buttons.png
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/loader.gif
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/mic-off.png
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/mic-on.png
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/speaker-off.png
browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/speaker-on.png
browser/extensions/loop/content/shared/vendor/sdk-content/js/dynamic_config.min.js
browser/extensions/loop/content/shared/vendor/sdk.js
browser/extensions/loop/skin/linux/menuPanel.png
browser/extensions/loop/skin/linux/menuPanel@2x.png
browser/extensions/loop/skin/linux/toolbar-inverted.png
browser/extensions/loop/skin/linux/toolbar-inverted@2x.png
browser/extensions/loop/skin/linux/toolbar.png
browser/extensions/loop/skin/linux/toolbar@2x.png
browser/extensions/loop/skin/osx/menuPanel-yosemite.png
browser/extensions/loop/skin/osx/menuPanel-yosemite@2x.png
browser/extensions/loop/skin/osx/menuPanel.png
browser/extensions/loop/skin/osx/menuPanel@2x.png
browser/extensions/loop/skin/osx/platform.css
browser/extensions/loop/skin/osx/toolbar-inverted.png
browser/extensions/loop/skin/osx/toolbar-inverted@2x.png
browser/extensions/loop/skin/osx/toolbar-yosemite.png
browser/extensions/loop/skin/osx/toolbar-yosemite@2x.png
browser/extensions/loop/skin/osx/toolbar.png
browser/extensions/loop/skin/osx/toolbar@2x.png
browser/extensions/loop/skin/shared/loop.css
browser/extensions/loop/skin/windows/menuPanel-aero.png
browser/extensions/loop/skin/windows/menuPanel-aero@2x.png
browser/extensions/loop/skin/windows/menuPanel.png
browser/extensions/loop/skin/windows/menuPanel@2x.png
browser/extensions/loop/skin/windows/platform.css
browser/extensions/loop/skin/windows/toolbar-XP.png
browser/extensions/loop/skin/windows/toolbar-XP@2x.png
browser/extensions/loop/skin/windows/toolbar-aero.png
browser/extensions/loop/skin/windows/toolbar-aero@2x.png
browser/extensions/loop/skin/windows/toolbar-inverted.png
browser/extensions/loop/skin/windows/toolbar-inverted@2x.png
browser/extensions/loop/skin/windows/toolbar-lunaSilver.png
browser/extensions/loop/skin/windows/toolbar-lunaSilver@2x.png
browser/extensions/loop/skin/windows/toolbar-win10.png
browser/extensions/loop/skin/windows/toolbar-win10@2x.png
browser/extensions/loop/skin/windows/toolbar.png
browser/extensions/loop/skin/windows/toolbar@2x.png
browser/extensions/loop/standalone/.gitignore
browser/extensions/loop/standalone/Makefile
browser/extensions/loop/standalone/README.md
browser/extensions/loop/standalone/content/css/webapp.css
browser/extensions/loop/standalone/content/favicon.ico
browser/extensions/loop/standalone/content/img/gum-chrome.svg
browser/extensions/loop/standalone/content/img/gum-firefox.svg
browser/extensions/loop/standalone/content/img/gum-opera.svg
browser/extensions/loop/standalone/content/img/gum-others.svg
browser/extensions/loop/standalone/content/img/hello-logo-text.svg
browser/extensions/loop/standalone/content/img/invitation.png
browser/extensions/loop/standalone/content/img/logo.png
browser/extensions/loop/standalone/content/img/mozilla-logo.svg
browser/extensions/loop/standalone/content/index.html
browser/extensions/loop/standalone/content/js/standaloneAppStore.js
browser/extensions/loop/standalone/content/js/standaloneMetricsStore.js
browser/extensions/loop/standalone/content/js/standaloneMozLoop.js
browser/extensions/loop/standalone/content/js/standaloneRoomViews.js
browser/extensions/loop/standalone/content/js/standaloneRoomViews.jsx
browser/extensions/loop/standalone/content/js/webapp.js
browser/extensions/loop/standalone/content/js/webapp.jsx
browser/extensions/loop/standalone/content/l10n/en-US/loop.properties
browser/extensions/loop/standalone/content/robots.txt
browser/extensions/loop/standalone/content/vendor/l10n-gaia-02ca67948fe8.js
browser/extensions/loop/standalone/content/vendor/l10n-gaia-upstream.txt
browser/extensions/loop/standalone/content/webappEntryPoint.js
browser/extensions/loop/standalone/package.json
browser/extensions/loop/standalone/server.js
browser/extensions/loop/standalone/webpack.config.js
browser/extensions/loop/test/.eslintrc
browser/extensions/loop/test/coverage/index.html
browser/extensions/loop/test/desktop-local/.eslintrc
browser/extensions/loop/test/desktop-local/README.md
browser/extensions/loop/test/desktop-local/conversationAppStore_test.js
browser/extensions/loop/test/desktop-local/conversation_test.js
browser/extensions/loop/test/desktop-local/feedbackViews_test.js
browser/extensions/loop/test/desktop-local/index.html
browser/extensions/loop/test/desktop-local/l10n_test.js
browser/extensions/loop/test/desktop-local/panel_test.js
browser/extensions/loop/test/desktop-local/roomStore_test.js
browser/extensions/loop/test/desktop-local/roomViews_test.js
browser/extensions/loop/test/desktop-local/test_desktop_all.py
browser/extensions/loop/test/index.html
browser/extensions/loop/test/karma/head.js
browser/extensions/loop/test/karma/karma.conf.base.js
browser/extensions/loop/test/karma/karma.coverage.desktop.js
browser/extensions/loop/test/karma/karma.coverage.shared_standalone.js
browser/extensions/loop/test/mochitest/.eslintrc
browser/extensions/loop/test/mochitest/browser.ini
browser/extensions/loop/test/mochitest/browser_LoopRooms_channel.js
browser/extensions/loop/test/mochitest/browser_fxa_login.js
browser/extensions/loop/test/mochitest/browser_loop_fxa_server.js
browser/extensions/loop/test/mochitest/browser_mozLoop_appVersionInfo.js
browser/extensions/loop/test/mochitest/browser_mozLoop_chat.js
browser/extensions/loop/test/mochitest/browser_mozLoop_context.js
browser/extensions/loop/test/mochitest/browser_mozLoop_sharingListeners.js
browser/extensions/loop/test/mochitest/browser_mozLoop_socialShare.js
browser/extensions/loop/test/mochitest/browser_mozLoop_telemetry.js
browser/extensions/loop/test/mochitest/browser_toolbarbutton.js
browser/extensions/loop/test/mochitest/head.js
browser/extensions/loop/test/mochitest/loop_fxa.sjs
browser/extensions/loop/test/mochitest/test_loopLinkClicker_channel.html
browser/extensions/loop/test/package.json
browser/extensions/loop/test/shared/activeRoomStore_test.js
browser/extensions/loop/test/shared/crypto_test.js
browser/extensions/loop/test/shared/dispatcher_test.js
browser/extensions/loop/test/shared/frontend_tester.py
browser/extensions/loop/test/shared/index.html
browser/extensions/loop/test/shared/linkifiedTextView_test.js
browser/extensions/loop/test/shared/loop_mocha_utils.js
browser/extensions/loop/test/shared/loopapi-client_test.js
browser/extensions/loop/test/shared/mixins_test.js
browser/extensions/loop/test/shared/models_test.js
browser/extensions/loop/test/shared/otSdkDriver_test.js
browser/extensions/loop/test/shared/sdk_mock.js
browser/extensions/loop/test/shared/store_test.js
browser/extensions/loop/test/shared/test_shared_all.py
browser/extensions/loop/test/shared/textChatStore_test.js
browser/extensions/loop/test/shared/textChatView_test.js
browser/extensions/loop/test/shared/utils_test.js
browser/extensions/loop/test/shared/validate_test.js
browser/extensions/loop/test/shared/vendor/chai-3.0.0.js
browser/extensions/loop/test/shared/vendor/chai-as-promised-5.1.0.js
browser/extensions/loop/test/shared/vendor/mocha-2.2.5.css
browser/extensions/loop/test/shared/vendor/mocha-2.2.5.js
browser/extensions/loop/test/shared/vendor/sinon-1.16.1.js
browser/extensions/loop/test/shared/views_test.js
browser/extensions/loop/test/standalone/index.html
browser/extensions/loop/test/standalone/standaloneAppStore_test.js
browser/extensions/loop/test/standalone/standaloneMetricsStore_test.js
browser/extensions/loop/test/standalone/standaloneMozLoop_test.js
browser/extensions/loop/test/standalone/standaloneRoomViews_test.js
browser/extensions/loop/test/standalone/test_standalone_all.py
browser/extensions/loop/test/standalone/webapp_test.js
browser/extensions/loop/test/ui-showcase/test_ui-showcase.py
browser/extensions/loop/test/visual-regression/README.md
browser/extensions/loop/test/visual-regression/screenshot
browser/extensions/loop/test/xpcshell/.eslintrc
browser/extensions/loop/test/xpcshell/head.js
browser/extensions/loop/test/xpcshell/test_loopapi_doNotDisturb.js
browser/extensions/loop/test/xpcshell/test_loopapi_internal.js
browser/extensions/loop/test/xpcshell/test_loopapi_prefs.js
browser/extensions/loop/test/xpcshell/test_looppush_initialize.js
browser/extensions/loop/test/xpcshell/test_looprooms.js
browser/extensions/loop/test/xpcshell/test_looprooms_encryption_in_fxa.js
browser/extensions/loop/test/xpcshell/test_looprooms_first_notification.js
browser/extensions/loop/test/xpcshell/test_looprooms_getall.js
browser/extensions/loop/test/xpcshell/test_looprooms_upgrade_to_encryption.js
browser/extensions/loop/test/xpcshell/test_loopservice_dnd.js
browser/extensions/loop/test/xpcshell/test_loopservice_encryptionkey.js
browser/extensions/loop/test/xpcshell/test_loopservice_hawk_errors.js
browser/extensions/loop/test/xpcshell/test_loopservice_hawk_request.js
browser/extensions/loop/test/xpcshell/test_loopservice_initialize.js
browser/extensions/loop/test/xpcshell/test_loopservice_locales.js
browser/extensions/loop/test/xpcshell/test_loopservice_loop_prefs.js
browser/extensions/loop/test/xpcshell/test_loopservice_registration.js
browser/extensions/loop/test/xpcshell/test_loopservice_registration_retry.js
browser/extensions/loop/test/xpcshell/test_loopservice_restart.js
browser/extensions/loop/test/xpcshell/test_loopservice_token_invalid.js
browser/extensions/loop/test/xpcshell/test_loopservice_token_save.js
browser/extensions/loop/test/xpcshell/test_loopservice_token_send.js
browser/extensions/loop/test/xpcshell/test_loopservice_token_validation.js
browser/extensions/loop/test/xpcshell/xpcshell.ini
browser/extensions/loop/ui/README.md
browser/extensions/loop/ui/fake-l10n.js
browser/extensions/loop/ui/fake-mozLoop.js
browser/extensions/loop/ui/index.html
browser/extensions/loop/ui/react-frame-component.js
browser/extensions/loop/ui/sample-img/video-screen-local.png
browser/extensions/loop/ui/sample-img/video-screen-remote.png
browser/extensions/loop/ui/sample-img/video-screen-terminal.png
browser/extensions/loop/ui/ui-showcase.css
browser/extensions/loop/ui/ui-showcase.js
browser/extensions/loop/ui/ui-showcase.jsx
deleted file mode 100644
--- a/browser/extensions/loop/.eslintrc
+++ /dev/null
@@ -1,160 +0,0 @@
-// Note: there are extra allowances for files used solely in Firefox desktop,
-// see content/js/.eslintrc and modules/.eslintrc
-{
-  "plugins": [
-    "react"
-  ],
-  "ecmaFeatures": {
-    // Allow these.
-    "forOf": true,
-    "jsx": true,
-    // Disallow due to content.
-    "arrowFunctions": false,
-    "blockBindings": false,
-    "destructuring": false,
-    "generators": false,
-    "objectLiteralShorthandMethods": false,
-    "restParams": false,
-    "spread": false,
-    "templateStrings": false,
-  },
-  "env": {
-    "browser": true,
-    "es6": false,
-    "mocha": true,
-  },
-  "extends": "eslint:recommended",
-  "globals": {
-    "_": false,
-    "Backbone": false,
-    "chai": false,
-    "classNames": false,
-    "console": false,
-    "loop": true,
-    "LoopMochaUtils": true,
-    "MozActivity": false,
-    "RTCSessionDescription": false,
-    "OT": false,
-    "performance": false,
-    "Promise": false,
-    "React": false,
-    "sinon": false
-  },
-  "rules": {
-    // turn off all kinds of stuff that we actually do want, because
-    // right now, we're bootstrapping the linting infrastructure.  We'll
-    // want to audit these rules, and start turning them on and fixing the
-    // problems they find, one at a time.
-
-    // Eslint built-in rules are documented at <http://eslint.org/docs/rules/>
-    "array-bracket-spacing": [2, "never"],
-    "block-spacing": [2, "always"],
-    "callback-return": 0,         // TBD
-    "camelcase": 0,               // TODO: set to 2
-    "comma-spacing": 2,
-    "comma-style": 2,
-    "computed-property-spacing": [2, "never"],
-    "consistent-return": 2,
-    "curly": [2, "all"],
-    "dot-location": [2, "property"],
-    "eol-last": 2,
-    "eqeqeq": [2, "smart"],
-    "generator-star-spacing": [2, {"before": false, "after": true}],
-    "jsx-quotes": [2, "prefer-double"],
-    "key-spacing": [2, {"beforeColon": false, "afterColon": true }],
-    "linebreak-style": [2, "unix"],
-    "new-cap": 0,                 // TODO: set to 2
-    "new-parens": 2,
-    "no-alert": 2,
-    "no-array-constructor": 2,
-    "no-caller": 2,
-    "no-catch-shadow": 2,
-    "no-class-assign": 2,
-    "no-const-assign": 2,
-    "no-console": 0,              // Leave as 0. We use console logging in content code.
-    "no-duplicate-case": 2,
-    "no-else-return": 2,
-    "no-empty": 2,
-    "no-empty-label": 2,
-    "no-eval": 2,
-    "no-extend-native": 2, // XXX
-    "no-extra-bind": 0,           // Leave as 0
-    "no-extra-parens": 0,         // TODO: (bug?) [2, "functions"],
-    "no-extra-semi": 2,
-    "no-implied-eval": 2,
-    "no-invalid-this": 0,         // TBD
-    "no-iterator": 2,
-    "no-label-var": 2,
-    "no-labels": 2,
-    "no-lone-blocks": 2,
-    "no-loop-func": 2,
-    "no-mixed-spaces-and-tabs": 2,
-    "no-multi-spaces": 2,
-    "no-multi-str": 2,
-    "no-multiple-empty-lines": 2,
-    "no-native-reassign": 2,
-    "no-new": 2,
-    "no-new-func": 2,
-    "no-new-object": 2,
-    "no-new-wrappers": 2,
-    "no-octal-escape": 2,
-    "no-process-exit": 2,
-    "no-proto": 2,
-    "no-return-assign": 2,
-    "no-script-url": 2,
-    "no-self-compare": 2,
-    "no-sequences": 2,
-    "no-shadow": 2,
-    "no-shadow-restricted-names": 2,
-    "no-spaced-func": 2,
-    "no-trailing-spaces": 2,
-    "no-undef-init": 2,
-    "no-underscore-dangle": 0,    // Leave as 0. Commonly used for private variables.
-    "no-unexpected-multiline": 2,
-    "no-unneeded-ternary": 2,
-    "no-unused-expressions": 0,   // TODO: Set to 2
-    "no-unused-vars": 0,          // TODO: Set to 2
-    "no-use-before-define": 0,    // TODO: Set to 2
-    "no-useless-call": 2,
-    "no-with": 2,
-    "object-curly-spacing": [2, "always"],
-    "operator-assignment": [2, "always"],
-    "quotes": [2, "double", "avoid-escape"],
-    "semi": 2,
-    "semi-spacing": [2, {"before": false, "after": true}],
-    "space-after-keywords": 2,
-    "space-before-blocks": 2,
-    "space-before-function-paren": [2, "never"],
-    "space-before-keywords": 2,
-    "space-infix-ops": 2,
-    "space-in-parens": [2, "never"],
-    "space-return-throw-case": 2,
-    "space-unary-ops": [2, {"words": true, "nonwords": false}],
-    "spaced-comment": [2, "always"],
-    "strict": [2, "function"],
-    "yoda": [2, "never"],
-    // eslint-plugin-react rules. These are documented at
-    // <https://github.com/yannickcr/eslint-plugin-react#list-of-supported-rules>
-    "react/jsx-curly-spacing": [2, "never"],
-    "react/jsx-no-bind": 2,
-    "react/jsx-no-duplicate-props": 2,
-    "react/jsx-no-undef": 2,
-    "react/jsx-sort-props": 2,
-    "react/jsx-sort-prop-types": 2,
-    "react/jsx-uses-vars": 2,
-    "react/no-did-mount-set-state": 2,
-    "react/no-did-update-set-state": 2,
-    "react/no-unknown-property": 2,
-    "react/prop-types": 2,
-    "react/self-closing-comp": 2,
-    "react/wrap-multilines": 2,
-    // Not worth it: React is defined globally
-    "react/jsx-uses-react": 0,
-    "react/react-in-jsx-scope": 0,
-    // These ones we don't want to ever enable
-    "react/display-name": 0,
-    "react/jsx-boolean-value": 0,
-    "react/no-danger": 0,
-    "react/no-multi-comp": 0
-  }
-}
deleted file mode 100644
--- a/browser/extensions/loop/.eslintrc-gecko
+++ /dev/null
@@ -1,69 +0,0 @@
-// This file defines additional items and rules specific for gecko files.
-// This is applied on top of the basic .eslintrc for gecko specific directories
-// e.g. the modules directory.
-{
-  "ecmaFeatures": {
-    "arrowFunctions": true,
-    "blockBindings": true,
-    "destructuring": true,
-    "generators": true,
-    "objectLiteralShorthandMethods": true,
-    "restParams": true,
-    "spread": true,
-    "templateStrings": true,
-  },
-  "globals": {
-    // Gecko + Loop Globals.
-    "Chat": false,
-    "ChromeWorker": false,
-    "CommonUtils": false,
-    "Components": false,
-    "convertToRTCStatsReport": false,
-    "CustomizableUI": false,
-    "deriveHawkCredentials": false,
-    "eventEmitter": false,
-    "FxAccountsOAuthClient": false,
-    "FxAccountsProfileClient": false,
-    "gBrowser": false,
-    "gDNSService": false,
-    "gLoopBundle": false,
-    "gWM": false,
-    "HawkClient": false,
-    "hookWindowCloseForPanelClose": true,
-    "Iterator": false,
-    "Log": false,
-    "log": true,
-    "LOOP_SESSION_TYPE": true,
-    "LoopAPI": true,
-    "LoopCalls": true,
-    "loopCrypto": false,
-    "LoopRooms": true,
-    "LoopRoomsCache": true,
-    "MozLoopPushHandler": true,
-    "MozLoopService": true,
-    "OS": false,
-    "PrivateBrowsingUtils": false,
-    "roomsPushNotification": true,
-    "Services": false,
-    "Social": false,
-    "SocialShare": false,
-    "Task": false,
-    "UITour": false,
-    "WebChannel": false,
-    "XPCOMUtils": false,
-    "uuidgen": true,
-    // Test Related
-    "Assert": false,
-  },
-  "rules": {
-    "arrow-parens": 0,         // TBD
-    "arrow-spacing": 2,
-    "eqeqeq": 0,               // TBD
-    "generator-star-spacing": [2, "after"],
-    // We should fix the errors and enable this (set to 2)
-    "no-var": 0,
-    "prefer-arrow-callback": 0,// TODO: Set to 2.
-    "require-yield": 0,        // TODO: Set to 2.
-    "strict": [2, "global"]
-  }
-}
rename from browser/extensions/loop/content/modules/LoopRooms.jsm
rename to browser/extensions/loop/chrome/content/modules/LoopRooms.jsm
rename from browser/extensions/loop/content/modules/LoopRoomsCache.jsm
rename to browser/extensions/loop/chrome/content/modules/LoopRoomsCache.jsm
rename from browser/extensions/loop/content/modules/MozLoopAPI.jsm
rename to browser/extensions/loop/chrome/content/modules/MozLoopAPI.jsm
rename from browser/extensions/loop/content/modules/MozLoopPushHandler.jsm
rename to browser/extensions/loop/chrome/content/modules/MozLoopPushHandler.jsm
rename from browser/extensions/loop/content/modules/MozLoopService.jsm
rename to browser/extensions/loop/chrome/content/modules/MozLoopService.jsm
rename from browser/extensions/loop/content/modules/MozLoopWorker.js
rename to browser/extensions/loop/chrome/content/modules/MozLoopWorker.js
rename from browser/extensions/loop/content/panels/conversation.html
rename to browser/extensions/loop/chrome/content/panels/conversation.html
rename from browser/extensions/loop/content/panels/css/panel.css
rename to browser/extensions/loop/chrome/content/panels/css/panel.css
rename from browser/extensions/loop/content/panels/js/.eslintrc
rename to browser/extensions/loop/chrome/content/panels/js/.eslintrc
rename from browser/extensions/loop/content/panels/js/conversation.js
rename to browser/extensions/loop/chrome/content/panels/js/conversation.js
rename from browser/extensions/loop/content/panels/js/conversationAppStore.js
rename to browser/extensions/loop/chrome/content/panels/js/conversationAppStore.js
rename from browser/extensions/loop/content/panels/js/feedbackViews.js
rename to browser/extensions/loop/chrome/content/panels/js/feedbackViews.js
rename from browser/extensions/loop/content/panels/js/otconfig.js
rename to browser/extensions/loop/chrome/content/panels/js/otconfig.js
rename from browser/extensions/loop/content/panels/js/panel.js
rename to browser/extensions/loop/chrome/content/panels/js/panel.js
rename from browser/extensions/loop/content/panels/js/roomStore.js
rename to browser/extensions/loop/chrome/content/panels/js/roomStore.js
rename from browser/extensions/loop/content/panels/js/roomViews.js
rename to browser/extensions/loop/chrome/content/panels/js/roomViews.js
rename from browser/extensions/loop/content/panels/panel.html
rename to browser/extensions/loop/chrome/content/panels/panel.html
rename from browser/extensions/loop/test/desktop-local/.eslintrc
rename to browser/extensions/loop/chrome/content/panels/test/.eslintrc
rename from browser/extensions/loop/test/desktop-local/README.md
rename to browser/extensions/loop/chrome/content/panels/test/README.md
rename from browser/extensions/loop/test/desktop-local/conversationAppStore_test.js
rename to browser/extensions/loop/chrome/content/panels/test/conversationAppStore_test.js
rename from browser/extensions/loop/test/desktop-local/conversation_test.js
rename to browser/extensions/loop/chrome/content/panels/test/conversation_test.js
rename from browser/extensions/loop/test/desktop-local/feedbackViews_test.js
rename to browser/extensions/loop/chrome/content/panels/test/feedbackViews_test.js
rename from browser/extensions/loop/test/desktop-local/index.html
rename to browser/extensions/loop/chrome/content/panels/test/index.html
rename from browser/extensions/loop/test/desktop-local/l10n_test.js
rename to browser/extensions/loop/chrome/content/panels/test/l10n_test.js
rename from browser/extensions/loop/test/desktop-local/panel_test.js
rename to browser/extensions/loop/chrome/content/panels/test/panel_test.js
rename from browser/extensions/loop/test/desktop-local/roomStore_test.js
rename to browser/extensions/loop/chrome/content/panels/test/roomStore_test.js
rename from browser/extensions/loop/test/desktop-local/roomViews_test.js
rename to browser/extensions/loop/chrome/content/panels/test/roomViews_test.js
rename from browser/extensions/loop/test/desktop-local/test_desktop_all.py
rename to browser/extensions/loop/chrome/content/panels/test/test_desktop_all.py
rename from browser/extensions/loop/content/panels/vendor/l10n.js
rename to browser/extensions/loop/chrome/content/panels/vendor/l10n.js
rename from browser/extensions/loop/content/preferences/prefs.js
rename to browser/extensions/loop/chrome/content/preferences/prefs.js
rename from browser/extensions/loop/content/shared/README.md
rename to browser/extensions/loop/chrome/content/shared/README.md
rename from browser/extensions/loop/content/shared/css/common.css
rename to browser/extensions/loop/chrome/content/shared/css/common.css
rename from browser/extensions/loop/content/shared/css/conversation.css
rename to browser/extensions/loop/chrome/content/shared/css/conversation.css
rename from browser/extensions/loop/content/shared/css/reset.css
rename to browser/extensions/loop/chrome/content/shared/css/reset.css
rename from browser/extensions/loop/content/shared/img/02.png
rename to browser/extensions/loop/chrome/content/shared/img/02.png
rename from browser/extensions/loop/content/shared/img/02@2x.png
rename to browser/extensions/loop/chrome/content/shared/img/02@2x.png
rename from browser/extensions/loop/content/shared/img/animated-spinner.svg
rename to browser/extensions/loop/chrome/content/shared/img/animated-spinner.svg
rename from browser/extensions/loop/content/shared/img/audio-call-avatar.svg
rename to browser/extensions/loop/chrome/content/shared/img/audio-call-avatar.svg
rename from browser/extensions/loop/content/shared/img/audio-default-16x16@1.5x.png
rename to browser/extensions/loop/chrome/content/shared/img/audio-default-16x16@1.5x.png
rename from browser/extensions/loop/content/shared/img/audio-default-16x16@2x.png
rename to browser/extensions/loop/chrome/content/shared/img/audio-default-16x16@2x.png
rename from browser/extensions/loop/content/shared/img/audio-hover.svg
rename to browser/extensions/loop/chrome/content/shared/img/audio-hover.svg
rename from browser/extensions/loop/content/shared/img/audio-mute-hover.svg
rename to browser/extensions/loop/chrome/content/shared/img/audio-mute-hover.svg
rename from browser/extensions/loop/content/shared/img/audio-mute.svg
rename to browser/extensions/loop/chrome/content/shared/img/audio-mute.svg
rename from browser/extensions/loop/content/shared/img/audio.svg
rename to browser/extensions/loop/chrome/content/shared/img/audio.svg
rename from browser/extensions/loop/content/shared/img/avatars.svg
rename to browser/extensions/loop/chrome/content/shared/img/avatars.svg
rename from browser/extensions/loop/content/shared/img/beta-ribbon.svg
rename to browser/extensions/loop/chrome/content/shared/img/beta-ribbon.svg
rename from browser/extensions/loop/content/shared/img/cam_audio-no.svg
rename to browser/extensions/loop/chrome/content/shared/img/cam_audio-no.svg
rename from browser/extensions/loop/content/shared/img/cam_audio.svg
rename to browser/extensions/loop/chrome/content/shared/img/cam_audio.svg
rename from browser/extensions/loop/content/shared/img/cam_audio_h.svg
rename to browser/extensions/loop/chrome/content/shared/img/cam_audio_h.svg
rename from browser/extensions/loop/content/shared/img/chatbubble-arrow-left.svg
rename to browser/extensions/loop/chrome/content/shared/img/chatbubble-arrow-left.svg
rename from browser/extensions/loop/content/shared/img/chatbubble-arrow-right.svg
rename to browser/extensions/loop/chrome/content/shared/img/chatbubble-arrow-right.svg
rename from browser/extensions/loop/content/shared/img/check.svg
rename to browser/extensions/loop/chrome/content/shared/img/check.svg
rename from browser/extensions/loop/content/shared/img/ellipsis-v.svg
rename to browser/extensions/loop/chrome/content/shared/img/ellipsis-v.svg
rename from browser/extensions/loop/content/shared/img/empty_search.svg
rename to browser/extensions/loop/chrome/content/shared/img/empty_search.svg
rename from browser/extensions/loop/content/shared/img/exit.svg
rename to browser/extensions/loop/chrome/content/shared/img/exit.svg
rename from browser/extensions/loop/content/shared/img/facemute-14x14.png
rename to browser/extensions/loop/chrome/content/shared/img/facemute-14x14.png
rename from browser/extensions/loop/content/shared/img/facemute-14x14@2x.png
rename to browser/extensions/loop/chrome/content/shared/img/facemute-14x14@2x.png
rename from browser/extensions/loop/content/shared/img/firefox-avatar.svg
rename to browser/extensions/loop/chrome/content/shared/img/firefox-avatar.svg
rename from browser/extensions/loop/content/shared/img/firefox-logo.png
rename to browser/extensions/loop/chrome/content/shared/img/firefox-logo.png
rename from browser/extensions/loop/content/shared/img/glyph-email-16x16.svg
rename to browser/extensions/loop/chrome/content/shared/img/glyph-email-16x16.svg
rename from browser/extensions/loop/content/shared/img/glyph-facebook-16x16.svg
rename to browser/extensions/loop/chrome/content/shared/img/glyph-facebook-16x16.svg
rename from browser/extensions/loop/content/shared/img/glyph-help-16x16.svg
rename to browser/extensions/loop/chrome/content/shared/img/glyph-help-16x16.svg
rename from browser/extensions/loop/content/shared/img/glyph-link-16x16.svg
rename to browser/extensions/loop/chrome/content/shared/img/glyph-link-16x16.svg
rename from browser/extensions/loop/content/shared/img/glyph-user-16x16.svg
rename to browser/extensions/loop/chrome/content/shared/img/glyph-user-16x16.svg
rename from browser/extensions/loop/content/shared/img/hangup-inverse-14x14.png
rename to browser/extensions/loop/chrome/content/shared/img/hangup-inverse-14x14.png
rename from browser/extensions/loop/content/shared/img/hangup-inverse-14x14@2x.png
rename to browser/extensions/loop/chrome/content/shared/img/hangup-inverse-14x14@2x.png
rename from browser/extensions/loop/content/shared/img/happy.png
rename to browser/extensions/loop/chrome/content/shared/img/happy.png
rename from browser/extensions/loop/content/shared/img/hello-web-share.svg
rename to browser/extensions/loop/chrome/content/shared/img/hello-web-share.svg
rename from browser/extensions/loop/content/shared/img/hello_logo.svg
rename to browser/extensions/loop/chrome/content/shared/img/hello_logo.svg
rename from browser/extensions/loop/content/shared/img/helloicon.svg
rename to browser/extensions/loop/chrome/content/shared/img/helloicon.svg
rename from browser/extensions/loop/content/shared/img/icon_32.png
rename to browser/extensions/loop/chrome/content/shared/img/icon_32.png
rename from browser/extensions/loop/content/shared/img/icon_64.png
rename to browser/extensions/loop/chrome/content/shared/img/icon_64.png
rename from browser/extensions/loop/content/shared/img/icons-10x10.svg
rename to browser/extensions/loop/chrome/content/shared/img/icons-10x10.svg
rename from browser/extensions/loop/content/shared/img/icons-14x14.svg
rename to browser/extensions/loop/chrome/content/shared/img/icons-14x14.svg
rename from browser/extensions/loop/content/shared/img/icons-16x16.svg
rename to browser/extensions/loop/chrome/content/shared/img/icons-16x16.svg
rename from browser/extensions/loop/content/shared/img/media-group-left-hover.svg
rename to browser/extensions/loop/chrome/content/shared/img/media-group-left-hover.svg
rename from browser/extensions/loop/content/shared/img/media-group-right-hover.svg
rename to browser/extensions/loop/chrome/content/shared/img/media-group-right-hover.svg
rename from browser/extensions/loop/content/shared/img/media-group.svg
rename to browser/extensions/loop/chrome/content/shared/img/media-group.svg
rename from browser/extensions/loop/content/shared/img/movistar.png
rename to browser/extensions/loop/chrome/content/shared/img/movistar.png
rename from browser/extensions/loop/content/shared/img/movistar@2x.png
rename to browser/extensions/loop/chrome/content/shared/img/movistar@2x.png
rename from browser/extensions/loop/content/shared/img/mute-inverse-14x14.png
rename to browser/extensions/loop/chrome/content/shared/img/mute-inverse-14x14.png
rename from browser/extensions/loop/content/shared/img/mute-inverse-14x14@2x.png
rename to browser/extensions/loop/chrome/content/shared/img/mute-inverse-14x14@2x.png
rename from browser/extensions/loop/content/shared/img/pause-12x12.svg
rename to browser/extensions/loop/chrome/content/shared/img/pause-12x12.svg
rename from browser/extensions/loop/content/shared/img/play-12x12.svg
rename to browser/extensions/loop/chrome/content/shared/img/play-12x12.svg
rename from browser/extensions/loop/content/shared/img/sad.png
rename to browser/extensions/loop/chrome/content/shared/img/sad.png
rename from browser/extensions/loop/content/shared/img/sad_hello_icon_64x64.svg
rename to browser/extensions/loop/chrome/content/shared/img/sad_hello_icon_64x64.svg
rename from browser/extensions/loop/content/shared/img/settings-hover.svg
rename to browser/extensions/loop/chrome/content/shared/img/settings-hover.svg
rename from browser/extensions/loop/content/shared/img/settings.svg
rename to browser/extensions/loop/chrome/content/shared/img/settings.svg
rename from browser/extensions/loop/content/shared/img/sharing-active.svg
rename to browser/extensions/loop/chrome/content/shared/img/sharing-active.svg
rename from browser/extensions/loop/content/shared/img/sharing-hover.svg
rename to browser/extensions/loop/chrome/content/shared/img/sharing-hover.svg
rename from browser/extensions/loop/content/shared/img/sharing-pending.svg
rename to browser/extensions/loop/chrome/content/shared/img/sharing-pending.svg
rename from browser/extensions/loop/content/shared/img/sharing.svg
rename to browser/extensions/loop/chrome/content/shared/img/sharing.svg
rename from browser/extensions/loop/content/shared/img/spinner.png
rename to browser/extensions/loop/chrome/content/shared/img/spinner.png
rename from browser/extensions/loop/content/shared/img/spinner.svg
rename to browser/extensions/loop/chrome/content/shared/img/spinner.svg
rename from browser/extensions/loop/content/shared/img/spinner@2x.png
rename to browser/extensions/loop/chrome/content/shared/img/spinner@2x.png
rename from browser/extensions/loop/content/shared/img/stop-12x12.svg
rename to browser/extensions/loop/chrome/content/shared/img/stop-12x12.svg
rename from browser/extensions/loop/content/shared/img/telefonica-logo.svg
rename to browser/extensions/loop/chrome/content/shared/img/telefonica-logo.svg
rename from browser/extensions/loop/content/shared/img/video-hover.svg
rename to browser/extensions/loop/chrome/content/shared/img/video-hover.svg
rename from browser/extensions/loop/content/shared/img/video-mute-hover.svg
rename to browser/extensions/loop/chrome/content/shared/img/video-mute-hover.svg
rename from browser/extensions/loop/content/shared/img/video-mute.svg
rename to browser/extensions/loop/chrome/content/shared/img/video-mute.svg
rename from browser/extensions/loop/content/shared/img/video.svg
rename to browser/extensions/loop/chrome/content/shared/img/video.svg
rename from browser/extensions/loop/content/shared/img/vivo.png
rename to browser/extensions/loop/chrome/content/shared/img/vivo.png
rename from browser/extensions/loop/content/shared/img/vivo@2x.png
rename to browser/extensions/loop/chrome/content/shared/img/vivo@2x.png
rename from browser/extensions/loop/content/shared/js/actions.js
rename to browser/extensions/loop/chrome/content/shared/js/actions.js
rename from browser/extensions/loop/content/shared/js/activeRoomStore.js
rename to browser/extensions/loop/chrome/content/shared/js/activeRoomStore.js
rename from browser/extensions/loop/content/shared/js/crypto.js
rename to browser/extensions/loop/chrome/content/shared/js/crypto.js
rename from browser/extensions/loop/content/shared/js/dispatcher.js
rename to browser/extensions/loop/chrome/content/shared/js/dispatcher.js
rename from browser/extensions/loop/content/shared/js/linkifiedTextView.js
rename to browser/extensions/loop/chrome/content/shared/js/linkifiedTextView.js
rename from browser/extensions/loop/content/shared/js/loopapi-client.js
rename to browser/extensions/loop/chrome/content/shared/js/loopapi-client.js
rename from browser/extensions/loop/content/shared/js/mixins.js
rename to browser/extensions/loop/chrome/content/shared/js/mixins.js
rename from browser/extensions/loop/content/shared/js/models.js
rename to browser/extensions/loop/chrome/content/shared/js/models.js
rename from browser/extensions/loop/content/shared/js/otSdkDriver.js
rename to browser/extensions/loop/chrome/content/shared/js/otSdkDriver.js
rename from browser/extensions/loop/content/shared/js/store.js
rename to browser/extensions/loop/chrome/content/shared/js/store.js
rename from browser/extensions/loop/content/shared/js/textChatStore.js
rename to browser/extensions/loop/chrome/content/shared/js/textChatStore.js
rename from browser/extensions/loop/content/shared/js/textChatView.js
rename to browser/extensions/loop/chrome/content/shared/js/textChatView.js
rename from browser/extensions/loop/content/shared/js/urlRegExps.js
rename to browser/extensions/loop/chrome/content/shared/js/urlRegExps.js
rename from browser/extensions/loop/content/shared/js/utils.js
rename to browser/extensions/loop/chrome/content/shared/js/utils.js
rename from browser/extensions/loop/content/shared/js/validate.js
rename to browser/extensions/loop/chrome/content/shared/js/validate.js
rename from browser/extensions/loop/content/shared/js/views.js
rename to browser/extensions/loop/chrome/content/shared/js/views.js
rename from browser/extensions/loop/content/shared/sounds/connected.ogg
rename to browser/extensions/loop/chrome/content/shared/sounds/connected.ogg
rename from browser/extensions/loop/content/shared/sounds/connecting.ogg
rename to browser/extensions/loop/chrome/content/shared/sounds/connecting.ogg
rename from browser/extensions/loop/content/shared/sounds/failure.ogg
rename to browser/extensions/loop/chrome/content/shared/sounds/failure.ogg
rename from browser/extensions/loop/content/shared/sounds/message.ogg
rename to browser/extensions/loop/chrome/content/shared/sounds/message.ogg
rename from browser/extensions/loop/content/shared/sounds/room-joined-in.ogg
rename to browser/extensions/loop/chrome/content/shared/sounds/room-joined-in.ogg
rename from browser/extensions/loop/content/shared/sounds/room-joined.ogg
rename to browser/extensions/loop/chrome/content/shared/sounds/room-joined.ogg
rename from browser/extensions/loop/content/shared/sounds/room-left.ogg
rename to browser/extensions/loop/chrome/content/shared/sounds/room-left.ogg
rename from browser/extensions/loop/content/shared/sounds/terminated.ogg
rename to browser/extensions/loop/chrome/content/shared/sounds/terminated.ogg
rename from browser/extensions/loop/test/shared/activeRoomStore_test.js
rename to browser/extensions/loop/chrome/content/shared/test/activeRoomStore_test.js
rename from browser/extensions/loop/test/shared/crypto_test.js
rename to browser/extensions/loop/chrome/content/shared/test/crypto_test.js
rename from browser/extensions/loop/test/shared/dispatcher_test.js
rename to browser/extensions/loop/chrome/content/shared/test/dispatcher_test.js
rename from browser/extensions/loop/test/shared/frontend_tester.py
rename to browser/extensions/loop/chrome/content/shared/test/frontend_tester.py
rename from browser/extensions/loop/test/shared/index.html
rename to browser/extensions/loop/chrome/content/shared/test/index.html
rename from browser/extensions/loop/test/shared/linkifiedTextView_test.js
rename to browser/extensions/loop/chrome/content/shared/test/linkifiedTextView_test.js
rename from browser/extensions/loop/test/shared/loop_mocha_utils.js
rename to browser/extensions/loop/chrome/content/shared/test/loop_mocha_utils.js
rename from browser/extensions/loop/test/shared/loopapi-client_test.js
rename to browser/extensions/loop/chrome/content/shared/test/loopapi-client_test.js
rename from browser/extensions/loop/test/shared/mixins_test.js
rename to browser/extensions/loop/chrome/content/shared/test/mixins_test.js
rename from browser/extensions/loop/test/shared/models_test.js
rename to browser/extensions/loop/chrome/content/shared/test/models_test.js
rename from browser/extensions/loop/test/shared/otSdkDriver_test.js
rename to browser/extensions/loop/chrome/content/shared/test/otSdkDriver_test.js
rename from browser/extensions/loop/test/shared/sdk_mock.js
rename to browser/extensions/loop/chrome/content/shared/test/sdk_mock.js
rename from browser/extensions/loop/test/shared/store_test.js
rename to browser/extensions/loop/chrome/content/shared/test/store_test.js
rename from browser/extensions/loop/test/shared/test_shared_all.py
rename to browser/extensions/loop/chrome/content/shared/test/test_shared_all.py
rename from browser/extensions/loop/test/shared/textChatStore_test.js
rename to browser/extensions/loop/chrome/content/shared/test/textChatStore_test.js
rename from browser/extensions/loop/test/shared/textChatView_test.js
rename to browser/extensions/loop/chrome/content/shared/test/textChatView_test.js
rename from browser/extensions/loop/test/shared/utils_test.js
rename to browser/extensions/loop/chrome/content/shared/test/utils_test.js
rename from browser/extensions/loop/test/shared/validate_test.js
rename to browser/extensions/loop/chrome/content/shared/test/validate_test.js
rename from browser/extensions/loop/test/shared/views_test.js
rename to browser/extensions/loop/chrome/content/shared/test/views_test.js
rename from browser/extensions/loop/content/shared/vendor/sdk-content/css/ot.css
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/css/ot.css
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/access-denied-chrome.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/access-denied-chrome.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/access-denied-copy-firefox.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/access-denied-copy-firefox.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/access-denied-firefox.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/access-denied-firefox.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/access-predenied-chrome.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/access-predenied-chrome.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/access-prompt-chrome.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/access-prompt-chrome.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/audioonly-publisher.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/audioonly-publisher.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/audioonly-subscriber.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/audioonly-subscriber.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/buttons.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/buttons.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/loader.gif
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/loader.gif
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/mic-off.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/mic-off.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/mic-on.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/mic-on.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/speaker-off.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/speaker-off.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/images/rtc/speaker-on.png
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/images/rtc/speaker-on.png
rename from browser/extensions/loop/content/shared/vendor/sdk-content/js/dynamic_config.min.js
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk-content/js/dynamic_config.min.js
rename from browser/extensions/loop/content/shared/vendor/sdk.js
rename to browser/extensions/loop/chrome/content/shared/vendor/sdk.js
rename from browser/extensions/loop/skin/windows/menuPanel.png
rename to browser/extensions/loop/chrome/skin/linux/menuPanel.png
rename from browser/extensions/loop/skin/windows/menuPanel@2x.png
rename to browser/extensions/loop/chrome/skin/linux/menuPanel@2x.png
rename from browser/extensions/loop/skin/windows/toolbar-inverted.png
rename to browser/extensions/loop/chrome/skin/linux/toolbar-inverted.png
rename from browser/extensions/loop/skin/windows/toolbar-inverted@2x.png
rename to browser/extensions/loop/chrome/skin/linux/toolbar-inverted@2x.png
rename from browser/extensions/loop/skin/linux/toolbar.png
rename to browser/extensions/loop/chrome/skin/linux/toolbar.png
rename from browser/extensions/loop/skin/linux/toolbar@2x.png
rename to browser/extensions/loop/chrome/skin/linux/toolbar@2x.png
rename from browser/extensions/loop/skin/osx/menuPanel-yosemite.png
rename to browser/extensions/loop/chrome/skin/osx/menuPanel-yosemite.png
rename from browser/extensions/loop/skin/osx/menuPanel-yosemite@2x.png
rename to browser/extensions/loop/chrome/skin/osx/menuPanel-yosemite@2x.png
rename from browser/extensions/loop/skin/osx/menuPanel.png
rename to browser/extensions/loop/chrome/skin/osx/menuPanel.png
rename from browser/extensions/loop/skin/osx/menuPanel@2x.png
rename to browser/extensions/loop/chrome/skin/osx/menuPanel@2x.png
rename from browser/extensions/loop/skin/osx/platform.css
rename to browser/extensions/loop/chrome/skin/osx/platform.css
rename from browser/extensions/loop/skin/osx/toolbar-inverted.png
rename to browser/extensions/loop/chrome/skin/osx/toolbar-inverted.png
rename from browser/extensions/loop/skin/osx/toolbar-inverted@2x.png
rename to browser/extensions/loop/chrome/skin/osx/toolbar-inverted@2x.png
rename from browser/extensions/loop/skin/osx/toolbar-yosemite.png
rename to browser/extensions/loop/chrome/skin/osx/toolbar-yosemite.png
rename from browser/extensions/loop/skin/osx/toolbar-yosemite@2x.png
rename to browser/extensions/loop/chrome/skin/osx/toolbar-yosemite@2x.png
rename from browser/extensions/loop/skin/osx/toolbar.png
rename to browser/extensions/loop/chrome/skin/osx/toolbar.png
rename from browser/extensions/loop/skin/osx/toolbar@2x.png
rename to browser/extensions/loop/chrome/skin/osx/toolbar@2x.png
rename from browser/extensions/loop/skin/shared/loop.css
rename to browser/extensions/loop/chrome/skin/shared/loop.css
rename from browser/extensions/loop/skin/windows/menuPanel-aero.png
rename to browser/extensions/loop/chrome/skin/windows/menuPanel-aero.png
rename from browser/extensions/loop/skin/windows/menuPanel-aero@2x.png
rename to browser/extensions/loop/chrome/skin/windows/menuPanel-aero@2x.png
rename from browser/extensions/loop/skin/linux/menuPanel.png
rename to browser/extensions/loop/chrome/skin/windows/menuPanel.png
rename from browser/extensions/loop/skin/linux/menuPanel@2x.png
rename to browser/extensions/loop/chrome/skin/windows/menuPanel@2x.png
rename from browser/extensions/loop/skin/windows/platform.css
rename to browser/extensions/loop/chrome/skin/windows/platform.css
rename from browser/extensions/loop/skin/windows/toolbar-XP.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar-XP.png
rename from browser/extensions/loop/skin/windows/toolbar-XP@2x.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar-XP@2x.png
rename from browser/extensions/loop/skin/windows/toolbar-aero.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar-aero.png
rename from browser/extensions/loop/skin/windows/toolbar-aero@2x.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar-aero@2x.png
rename from browser/extensions/loop/skin/linux/toolbar-inverted.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar-inverted.png
rename from browser/extensions/loop/skin/linux/toolbar-inverted@2x.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar-inverted@2x.png
rename from browser/extensions/loop/skin/windows/toolbar-lunaSilver.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar-lunaSilver.png
rename from browser/extensions/loop/skin/windows/toolbar-lunaSilver@2x.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar-lunaSilver@2x.png
rename from browser/extensions/loop/skin/windows/toolbar-win10.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar-win10.png
rename from browser/extensions/loop/skin/windows/toolbar-win10@2x.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar-win10@2x.png
rename from browser/extensions/loop/skin/windows/toolbar.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar.png
rename from browser/extensions/loop/skin/windows/toolbar@2x.png
rename to browser/extensions/loop/chrome/skin/windows/toolbar@2x.png
rename from browser/extensions/loop/test/mochitest/.eslintrc
rename to browser/extensions/loop/chrome/test/mochitest/.eslintrc
rename from browser/extensions/loop/test/mochitest/browser.ini
rename to browser/extensions/loop/chrome/test/mochitest/browser.ini
rename from browser/extensions/loop/test/mochitest/browser_LoopRooms_channel.js
rename to browser/extensions/loop/chrome/test/mochitest/browser_LoopRooms_channel.js
rename from browser/extensions/loop/test/mochitest/browser_fxa_login.js
rename to browser/extensions/loop/chrome/test/mochitest/browser_fxa_login.js
rename from browser/extensions/loop/test/mochitest/browser_loop_fxa_server.js
rename to browser/extensions/loop/chrome/test/mochitest/browser_loop_fxa_server.js
rename from browser/extensions/loop/test/mochitest/browser_mozLoop_appVersionInfo.js
rename to browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_appVersionInfo.js
rename from browser/extensions/loop/test/mochitest/browser_mozLoop_chat.js
rename to browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_chat.js
rename from browser/extensions/loop/test/mochitest/browser_mozLoop_context.js
rename to browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_context.js
rename from browser/extensions/loop/test/mochitest/browser_mozLoop_sharingListeners.js
rename to browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_sharingListeners.js
rename from browser/extensions/loop/test/mochitest/browser_mozLoop_socialShare.js
rename to browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_socialShare.js
rename from browser/extensions/loop/test/mochitest/browser_mozLoop_telemetry.js
rename to browser/extensions/loop/chrome/test/mochitest/browser_mozLoop_telemetry.js
rename from browser/extensions/loop/test/mochitest/browser_toolbarbutton.js
rename to browser/extensions/loop/chrome/test/mochitest/browser_toolbarbutton.js
rename from browser/extensions/loop/test/mochitest/head.js
rename to browser/extensions/loop/chrome/test/mochitest/head.js
rename from browser/extensions/loop/test/mochitest/loop_fxa.sjs
rename to browser/extensions/loop/chrome/test/mochitest/loop_fxa.sjs
rename from browser/extensions/loop/test/mochitest/test_loopLinkClicker_channel.html
rename to browser/extensions/loop/chrome/test/mochitest/test_loopLinkClicker_channel.html
rename from browser/extensions/loop/test/xpcshell/.eslintrc
rename to browser/extensions/loop/chrome/test/xpcshell/.eslintrc
rename from browser/extensions/loop/test/xpcshell/head.js
rename to browser/extensions/loop/chrome/test/xpcshell/head.js
rename from browser/extensions/loop/test/xpcshell/test_loopapi_doNotDisturb.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopapi_doNotDisturb.js
rename from browser/extensions/loop/test/xpcshell/test_loopapi_internal.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopapi_internal.js
rename from browser/extensions/loop/test/xpcshell/test_loopapi_prefs.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopapi_prefs.js
rename from browser/extensions/loop/test/xpcshell/test_looppush_initialize.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_looppush_initialize.js
rename from browser/extensions/loop/test/xpcshell/test_looprooms.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_looprooms.js
rename from browser/extensions/loop/test/xpcshell/test_looprooms_encryption_in_fxa.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_looprooms_encryption_in_fxa.js
rename from browser/extensions/loop/test/xpcshell/test_looprooms_first_notification.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_looprooms_first_notification.js
rename from browser/extensions/loop/test/xpcshell/test_looprooms_getall.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_looprooms_getall.js
rename from browser/extensions/loop/test/xpcshell/test_looprooms_upgrade_to_encryption.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_looprooms_upgrade_to_encryption.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_dnd.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_dnd.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_encryptionkey.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_encryptionkey.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_hawk_errors.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_hawk_errors.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_hawk_request.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_hawk_request.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_initialize.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_initialize.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_locales.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_locales.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_loop_prefs.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_loop_prefs.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_registration.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_registration.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_registration_retry.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_registration_retry.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_restart.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_restart.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_token_invalid.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_token_invalid.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_token_save.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_token_save.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_token_send.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_token_send.js
rename from browser/extensions/loop/test/xpcshell/test_loopservice_token_validation.js
rename to browser/extensions/loop/chrome/test/xpcshell/test_loopservice_token_validation.js
rename from browser/extensions/loop/test/xpcshell/xpcshell.ini
rename to browser/extensions/loop/chrome/test/xpcshell/xpcshell.ini
deleted file mode 100644
--- a/browser/extensions/loop/content/modules/.eslintrc
+++ /dev/null
@@ -1,3 +0,0 @@
-{
-  "extends": "../../.eslintrc-gecko"
-}
deleted file mode 100644
--- a/browser/extensions/loop/content/panels/js/conversation.jsx
+++ /dev/null
@@ -1,227 +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/. */
-
-var loop = loop || {};
-loop.conversation = (function(mozL10n) {
-  "use strict";
-
-  var sharedMixins = loop.shared.mixins;
-  var sharedActions = loop.shared.actions;
-  var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
-
-  var DesktopRoomConversationView = loop.roomViews.DesktopRoomConversationView;
-  var FeedbackView = loop.feedbackViews.FeedbackView;
-  var RoomFailureView = loop.roomViews.RoomFailureView;
-
-  /**
-   * Master controller view for handling if incoming or outgoing calls are
-   * in progress, and hence, which view to display.
-   */
-  var AppControllerView = React.createClass({
-    mixins: [
-      Backbone.Events,
-      loop.store.StoreMixin("conversationAppStore"),
-      sharedMixins.DocumentTitleMixin,
-      sharedMixins.WindowCloseMixin
-    ],
-
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      roomStore: React.PropTypes.instanceOf(loop.store.RoomStore)
-    },
-
-    getInitialState: function() {
-      return this.getStoreState();
-    },
-
-    _renderFeedbackForm: function() {
-      this.setTitle(mozL10n.get("conversation_has_ended"));
-
-      return (<FeedbackView
-        onAfterFeedbackReceived={this.closeWindow} />);
-    },
-
-    /**
-     * We only show the feedback for once every 6 months, otherwise close
-     * the window.
-     */
-    handleCallTerminated: function() {
-      var delta = new Date() - new Date(this.state.feedbackTimestamp);
-
-      // Show timestamp if feedback period (6 months) passed.
-      // 0 is default value for pref. Always show feedback form on first use.
-      if (this.state.feedbackTimestamp === 0 ||
-          delta >= this.state.feedbackPeriod) {
-        this.props.dispatcher.dispatch(new sharedActions.ShowFeedbackForm());
-        return;
-      }
-
-      this.closeWindow();
-    },
-
-    render: function() {
-      if (this.state.showFeedbackForm) {
-        return this._renderFeedbackForm();
-      }
-
-      switch (this.state.windowType) {
-        case "room": {
-          return (<DesktopRoomConversationView
-            chatWindowDetached={this.state.chatWindowDetached}
-            dispatcher={this.props.dispatcher}
-            onCallTerminated={this.handleCallTerminated}
-            roomStore={this.props.roomStore} />);
-        }
-        case "failed": {
-          return (<RoomFailureView
-            dispatcher={this.props.dispatcher}
-            failureReason={FAILURE_DETAILS.UNKNOWN} />);
-        }
-        default: {
-          // If we don't have a windowType, we don't know what we are yet,
-          // so don't display anything.
-          return null;
-        }
-      }
-    }
-  });
-
-  /**
-   * Conversation initialisation.
-   */
-  function init() {
-    // Obtain the windowId and pass it through
-    var locationHash = loop.shared.utils.locationData().hash;
-    var windowId;
-
-    var hash = locationHash.match(/#(.*)/);
-    if (hash) {
-      windowId = hash[1];
-    }
-
-    var requests = [
-      ["GetAllConstants"],
-      ["GetAllStrings"],
-      ["GetLocale"],
-      ["GetLoopPref", "ot.guid"],
-      ["GetLoopPref", "textChat.enabled"],
-      ["GetLoopPref", "feedback.periodSec"],
-      ["GetLoopPref", "feedback.dateLastSeenSec"]
-    ];
-    var prefetch = [
-      ["GetConversationWindowData", windowId]
-    ];
-
-    return loop.requestMulti.apply(null, requests.concat(prefetch)).then(function(results) {
-      // `requestIdx` is keyed off the order of the `requests` and `prefetch`
-      // arrays. Be careful to update both when making changes.
-      var requestIdx = 0;
-      var constants = results[requestIdx];
-      // Do the initial L10n setup, we do this before anything
-      // else to ensure the L10n environment is setup correctly.
-      var stringBundle = results[++requestIdx];
-      var locale = results[++requestIdx];
-      mozL10n.initialize({
-        locale: locale,
-        getStrings: function(key) {
-          if (!(key in stringBundle)) {
-            console.error("No string found for key: ", key);
-            return "{ textContent: '' }";
-          }
-
-          return JSON.stringify({ textContent: stringBundle[key] });
-        }
-      });
-
-      // Plug in an alternate client ID mechanism, as localStorage and cookies
-      // don't work in the conversation window
-      var currGuid = results[++requestIdx];
-      window.OT.overrideGuidStorage({
-        get: function(callback) {
-          callback(null, currGuid);
-        },
-        set: function(guid, callback) {
-          // See nsIPrefBranch
-          var PREF_STRING = 32;
-          currGuid = guid;
-          loop.request("SetLoopPref", "ot.guid", guid, PREF_STRING);
-          callback(null);
-        }
-      });
-
-      // We want data channels only if the text chat preference is enabled.
-      var useDataChannels = results[++requestIdx];
-
-      var dispatcher = new loop.Dispatcher();
-      var sdkDriver = new loop.OTSdkDriver({
-        constants: constants,
-        isDesktop: true,
-        useDataChannels: useDataChannels,
-        dispatcher: dispatcher,
-        sdk: OT
-      });
-
-      // expose for functional tests
-      loop.conversation._sdkDriver = sdkDriver;
-
-      // Create the stores.
-      var activeRoomStore = new loop.store.ActiveRoomStore(dispatcher, {
-        isDesktop: true,
-        sdkDriver: sdkDriver
-      });
-      var conversationAppStore = new loop.store.ConversationAppStore({
-        activeRoomStore: activeRoomStore,
-        dispatcher: dispatcher,
-        feedbackPeriod: results[++requestIdx],
-        feedbackTimestamp: results[++requestIdx]
-      });
-
-      prefetch.forEach(function(req) {
-        req.shift();
-        loop.storeRequest(req, results[++requestIdx]);
-      });
-
-      var roomStore = new loop.store.RoomStore(dispatcher, {
-        activeRoomStore: activeRoomStore,
-        constants: constants
-      });
-      var textChatStore = new loop.store.TextChatStore(dispatcher, {
-        sdkDriver: sdkDriver
-      });
-
-      loop.store.StoreMixin.register({
-        conversationAppStore: conversationAppStore,
-        textChatStore: textChatStore
-      });
-
-      React.render(
-        <AppControllerView
-          dispatcher={dispatcher}
-          roomStore={roomStore} />, document.querySelector("#main"));
-
-      document.documentElement.setAttribute("lang", mozL10n.getLanguage());
-      document.documentElement.setAttribute("dir", mozL10n.getDirection());
-      document.body.setAttribute("platform", loop.shared.utils.getPlatform());
-
-      dispatcher.dispatch(new sharedActions.GetWindowData({
-        windowId: windowId
-      }));
-    });
-  }
-
-  return {
-    AppControllerView: AppControllerView,
-    init: init,
-
-    /**
-     * Exposed for the use of functional tests to be able to check
-     * metric-related execution as the call sequence progresses.
-     *
-     * @type loop.OTSdkDriver
-     */
-    _sdkDriver: null
-  };
-})(document.mozL10n);
-
-document.addEventListener("DOMContentLoaded", loop.conversation.init);
deleted file mode 100644
--- a/browser/extensions/loop/content/panels/js/feedbackViews.jsx
+++ /dev/null
@@ -1,49 +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/. */
-
-var loop = loop || {};
-loop.feedbackViews = (function(_, mozL10n) {
-  "use strict";
-
-  /**
-   * Feedback view is displayed once every 6 months (loop.feedback.periodSec)
-   * after a conversation has ended.
-   */
-  var FeedbackView = React.createClass({
-    propTypes: {
-      onAfterFeedbackReceived: React.PropTypes.func.isRequired
-    },
-
-    /**
-     * Pressing the button to leave feedback will open the form in a new page
-     * and close the conversation window.
-     */
-    onFeedbackButtonClick: function() {
-      loop.request("GetLoopPref", "feedback.formURL").then(function(url) {
-        loop.request("OpenURL", url).then(this.props.onAfterFeedbackReceived);
-      }.bind(this));
-    },
-
-    render: function() {
-      return (
-        <div className="feedback-view-container">
-          <h2 className="feedback-heading">
-            {mozL10n.get("feedback_window_heading")}
-          </h2>
-          <div className="feedback-hello-logo" />
-          <div className="feedback-button-container">
-            <button onClick={this.onFeedbackButtonClick}
-              ref="feedbackFormBtn">
-              {mozL10n.get("feedback_request_button")}
-            </button>
-          </div>
-        </div>
-      );
-    }
-  });
-
-  return {
-    FeedbackView: FeedbackView
-  };
-})(_, navigator.mozL10n || document.mozL10n);
deleted file mode 100644
--- a/browser/extensions/loop/content/panels/js/panel.jsx
+++ /dev/null
@@ -1,1151 +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/. */
-
-var loop = loop || {};
-loop.panel = (function(_, mozL10n) {
-  "use strict";
-
-  var sharedViews = loop.shared.views;
-  var sharedModels = loop.shared.models;
-  var sharedMixins = loop.shared.mixins;
-  var sharedActions = loop.shared.actions;
-  var Button = sharedViews.Button;
-  var Checkbox = sharedViews.Checkbox;
-
-  var FTU_VERSION = 1;
-
-  var GettingStartedView = React.createClass({
-    mixins: [sharedMixins.WindowCloseMixin],
-
-    handleButtonClick: function() {
-      loop.requestMulti(
-        ["OpenGettingStartedTour", "getting-started"],
-        ["SetLoopPref", "gettingStarted.latestFTUVersion", FTU_VERSION],
-        ["SetPanelHeight"]).then(function() {
-          var event = new CustomEvent("GettingStartedSeen");
-          window.dispatchEvent(event);
-        }.bind(this));
-      this.closeWindow();
-    },
-
-    componentWillMount: function() {
-      // Set 553 pixel height to show the full FTU panel content.
-      loop.request("SetPanelHeight", 553);
-    },
-
-    render: function() {
-      return (
-        <div className="fte-get-started-content">
-          <div className="fte-title">
-            <img className="fte-logo" src="shared/img/hello_logo.svg" />
-            <div className="fte-subheader">
-              {mozL10n.get("first_time_experience_subheading2")}
-            </div>
-            <hr className="fte-separator"/>
-            <div className="fte-content">
-              {mozL10n.get("first_time_experience_content")}
-            </div>
-            <img className="fte-hello-web-share" src="shared/img/hello-web-share.svg" />
-          </div>
-          <div className="fte-button-container">
-            <Button additionalClass="fte-get-started-button"
-                    caption={mozL10n.get("first_time_experience_button_label2")}
-                    htmlId="fte-button"
-                    onClick={this.handleButtonClick} />
-          </div>
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Displays a view requesting the user to sign-in again.
-   */
-  var SignInRequestView = React.createClass({
-    mixins: [sharedMixins.WindowCloseMixin],
-
-    handleSignInClick: function(event) {
-      event.preventDefault();
-      loop.request("LoginToFxA", true);
-      this.closeWindow();
-    },
-
-    handleGuestClick: function(event) {
-      loop.request("LogoutFromFxA");
-    },
-
-    render: function() {
-      var shortname = mozL10n.get("clientShortname2");
-      var line1 = mozL10n.get("sign_in_again_title_line_one", {
-        clientShortname2: shortname
-      });
-      var line2 = mozL10n.get("sign_in_again_title_line_two2", {
-        clientShortname2: shortname
-      });
-      var useGuestString = mozL10n.get("sign_in_again_use_as_guest_button2", {
-        clientSuperShortname: mozL10n.get("clientSuperShortname")
-      });
-
-      return (
-        <div className="sign-in-request">
-          <h1>{line1}</h1>
-          <h2>{line2}</h2>
-          <div>
-            <button className="btn btn-info sign-in-request-button"
-                    onClick={this.handleSignInClick}>
-              {mozL10n.get("sign_in_again_button")}
-            </button>
-          </div>
-          <a onClick={this.handleGuestClick}>
-            {useGuestString}
-          </a>
-        </div>
-      );
-    }
-  });
-
-  var ToSView = React.createClass({
-    mixins: [sharedMixins.WindowCloseMixin],
-
-    getInitialState: function() {
-      return {
-        terms_of_use_url: loop.getStoredRequest(["GetLoopPref", "legal.ToS_url"]),
-        privacy_notice_url: loop.getStoredRequest(["GetLoopPref", "legal.privacy_url"])
-      };
-    },
-
-    handleLinkClick: function(event) {
-      if (!event.target || !event.target.href) {
-        return;
-      }
-
-      event.preventDefault();
-      loop.request("OpenURL", event.target.href);
-      this.closeWindow();
-    },
-
-    render: function() {
-      var locale = mozL10n.getLanguage();
-      var tosHTML = mozL10n.get("legal_text_and_links3", {
-        "clientShortname": mozL10n.get("clientShortname2"),
-        "terms_of_use": React.renderToStaticMarkup(
-          <a href={this.state.terms_of_use_url} target="_blank">
-            {mozL10n.get("legal_text_tos")}
-          </a>
-        ),
-        "privacy_notice": React.renderToStaticMarkup(
-          <a href={this.state.privacy_notice_url} target="_blank">
-            {mozL10n.get("legal_text_privacy")}
-          </a>
-        )
-      });
-
-      return (
-        <div className="powered-by-wrapper" id="powered-by-wrapper">
-          <p className="powered-by" id="powered-by">
-            {mozL10n.get("powered_by_beforeLogo")}
-            <span className={locale} id="powered-by-logo"/>
-            {mozL10n.get("powered_by_afterLogo")}
-          </p>
-          <p className="terms-service"
-             dangerouslySetInnerHTML={{ __html: tosHTML }}
-             onClick={this.handleLinkClick}></p>
-         </div>
-      );
-    }
-  });
-
-  /**
-   * Panel settings (gear) menu entry.
-   */
-  var SettingsDropdownEntry = React.createClass({
-    propTypes: {
-      displayed: React.PropTypes.bool,
-      extraCSSClass: React.PropTypes.string,
-      label: React.PropTypes.string.isRequired,
-      onClick: React.PropTypes.func.isRequired
-    },
-
-    getDefaultProps: function() {
-      return { displayed: true };
-    },
-
-    render: function() {
-      var cx = classNames;
-
-      if (!this.props.displayed) {
-        return null;
-      }
-
-      var extraCSSClass = {
-        "dropdown-menu-item": true
-      };
-      if (this.props.extraCSSClass) {
-        extraCSSClass[this.props.extraCSSClass] = true;
-      }
-
-      return (
-        <li className={cx(extraCSSClass)} onClick={this.props.onClick}>
-          {this.props.label}
-        </li>
-      );
-    }
-  });
-
-  /**
-   * Panel settings (gear) menu.
-   */
-  var SettingsDropdown = React.createClass({
-    mixins: [sharedMixins.DropdownMenuMixin(), sharedMixins.WindowCloseMixin],
-
-    getInitialState: function() {
-      return {
-        signedIn: !!loop.getStoredRequest(["GetUserProfile"]),
-        fxAEnabled: loop.getStoredRequest(["GetFxAEnabled"]),
-        doNotDisturb: loop.getStoredRequest(["GetDoNotDisturb"])
-      };
-    },
-
-    componentWillUpdate: function(nextProps, nextState) {
-      if (nextState.showMenu !== this.state.showMenu) {
-        loop.requestMulti(
-          ["GetUserProfile"],
-          ["GetFxAEnabled"],
-          ["GetDoNotDisturb"]
-        ).then(function(results) {
-          this.setState({
-            signedIn: !!results[0],
-            fxAEnabled: results[1],
-            doNotDisturb: results[2]
-          });
-        }.bind(this));
-      }
-    },
-
-    handleClickSettingsEntry: function() {
-      // XXX to be implemented at the same time as unhiding the entry
-    },
-
-    handleClickAccountEntry: function() {
-      loop.request("OpenFxASettings");
-      this.closeWindow();
-    },
-
-    handleClickAuthEntry: function() {
-      if (this.state.signedIn) {
-        loop.request("LogoutFromFxA");
-      } else {
-        loop.request("LoginToFxA");
-      }
-    },
-
-    handleHelpEntry: function(event) {
-      event.preventDefault();
-      loop.request("GetLoopPref", "support_url").then(function(helloSupportUrl) {
-        loop.request("OpenURL", helloSupportUrl);
-        this.closeWindow();
-      }.bind(this));
-    },
-
-    handleToggleNotifications: function() {
-      loop.request("GetDoNotDisturb").then(function(result) {
-        loop.request("SetDoNotDisturb", !result);
-      });
-      this.hideDropdownMenu();
-    },
-
-    /**
-     * Load on the browser the feedback url from prefs
-     */
-    handleSubmitFeedback: function(event) {
-      event.preventDefault();
-      loop.request("GetLoopPref", "feedback.manualFormURL").then(function(helloFeedbackUrl) {
-        loop.request("OpenURL", helloFeedbackUrl);
-        this.closeWindow();
-      }.bind(this));
-    },
-
-    openGettingStartedTour: function() {
-      loop.request("OpenGettingStartedTour", "settings-menu");
-      this.closeWindow();
-    },
-
-    render: function() {
-      var cx = classNames;
-      var accountEntryCSSClass = this.state.signedIn ? "entry-settings-signout" :
-                                                       "entry-settings-signin";
-      var notificationsLabel = this.state.doNotDisturb ? "settings_menu_item_turnnotificationson" :
-                                                         "settings_menu_item_turnnotificationsoff";
-
-      return (
-        <div className="settings-menu dropdown">
-          <button className="button-settings"
-             onClick={this.toggleDropdownMenu}
-             ref="menu-button"
-             title={mozL10n.get("settings_menu_button_tooltip")} />
-          <ul className={cx({ "dropdown-menu": true, hide: !this.state.showMenu })}>
-            <SettingsDropdownEntry
-                extraCSSClass="entry-settings-notifications entries-divider"
-                label={mozL10n.get(notificationsLabel)}
-                onClick={this.handleToggleNotifications} />
-            <SettingsDropdownEntry
-                displayed={this.state.signedIn && this.state.fxAEnabled}
-                extraCSSClass="entry-settings-account"
-                label={mozL10n.get("settings_menu_item_account")}
-                onClick={this.handleClickAccountEntry} />
-            <SettingsDropdownEntry displayed={false}
-                                   label={mozL10n.get("settings_menu_item_settings")}
-                                   onClick={this.handleClickSettingsEntry} />
-            <SettingsDropdownEntry label={mozL10n.get("tour_label")}
-                                   onClick={this.openGettingStartedTour} />
-            <SettingsDropdownEntry extraCSSClass="entry-settings-feedback"
-                                   label={mozL10n.get("settings_menu_item_feedback")}
-                                   onClick={this.handleSubmitFeedback} />
-            <SettingsDropdownEntry displayed={this.state.fxAEnabled}
-                                   extraCSSClass={accountEntryCSSClass}
-                                   label={this.state.signedIn ?
-                                          mozL10n.get("settings_menu_item_signout") :
-                                          mozL10n.get("settings_menu_item_signin")}
-                                   onClick={this.handleClickAuthEntry} />
-            <SettingsDropdownEntry extraCSSClass="entry-settings-help"
-                                   label={mozL10n.get("help_label")}
-                                   onClick={this.handleHelpEntry} />
-          </ul>
-        </div>
-      );
-    }
-  });
-
-  /**
-   * FxA sign in/up link component.
-   */
-  var AccountLink = React.createClass({
-    mixins: [sharedMixins.WindowCloseMixin],
-
-    propTypes: {
-      fxAEnabled: React.PropTypes.bool.isRequired,
-      userProfile: userProfileValidator
-    },
-
-    handleSignInLinkClick: function() {
-      loop.request("LoginToFxA");
-      this.closeWindow();
-    },
-
-    render: function() {
-      if (!this.props.fxAEnabled) {
-        return null;
-      }
-
-      if (this.props.userProfile && this.props.userProfile.email) {
-        return (
-          <div className="user-identity">
-            {loop.shared.utils.truncate(this.props.userProfile.email, 24)}
-          </div>
-        );
-      }
-
-      return (
-        <p className="signin-link">
-          <a href="#" onClick={this.handleSignInLinkClick}>
-            {mozL10n.get("panel_footer_signin_or_signup_link")}
-          </a>
-        </p>
-      );
-    }
-  });
-
-  var RoomEntryContextItem = React.createClass({
-    mixins: [loop.shared.mixins.WindowCloseMixin],
-
-    propTypes: {
-      roomUrls: React.PropTypes.array
-    },
-
-    handleClick: function(event) {
-      event.stopPropagation();
-      event.preventDefault();
-      if (event.currentTarget.href) {
-        loop.request("OpenURL", event.currentTarget.href);
-        this.closeWindow();
-      }
-    },
-
-    _renderDefaultIcon: function() {
-      return (
-        <div className="room-entry-context-item">
-          <img src="shared/img/icons-16x16.svg#globe" />
-        </div>
-      );
-    },
-
-    _renderIcon: function(roomUrl) {
-      return (
-        <div className="room-entry-context-item">
-          <a href={roomUrl.location}
-            onClick={this.handleClick}
-            title={roomUrl.description}>
-            <img src={roomUrl.thumbnail || "shared/img/icons-16x16.svg#globe"} />
-          </a>
-        </div>
-      );
-    },
-
-    render: function() {
-      var roomUrl = this.props.roomUrls && this.props.roomUrls[0];
-      if (roomUrl && roomUrl.location) {
-        return this._renderIcon(roomUrl);
-      }
-
-      return this._renderDefaultIcon();
-    }
-  });
-
-  /**
-   * Room list entry.
-   *
-   * Active Room means there are participants in the room.
-   * Opened Room means the user is in the room.
-   */
-  var RoomEntry = React.createClass({
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      isOpenedRoom: React.PropTypes.bool.isRequired,
-      room: React.PropTypes.instanceOf(loop.store.Room).isRequired
-    },
-
-    mixins: [
-      loop.shared.mixins.WindowCloseMixin,
-      sharedMixins.DropdownMenuMixin()
-    ],
-
-    getInitialState: function() {
-      return {
-        eventPosY: 0
-      };
-    },
-
-    _isActive: function() {
-      return this.props.room.participants.length > 0;
-    },
-
-    handleClickEntry: function(event) {
-      event.preventDefault();
-
-      this.props.dispatcher.dispatch(new sharedActions.OpenRoom({
-        roomToken: this.props.room.roomToken
-      }));
-
-      // Open url if needed.
-      loop.request("getSelectedTabMetadata").then(function(metadata) {
-        var contextURL = this.props.room.decryptedContext.urls &&
-          this.props.room.decryptedContext.urls[0].location;
-        if (contextURL && metadata.url !== contextURL) {
-          loop.request("OpenURL", contextURL);
-        }
-        this.closeWindow();
-      }.bind(this));
-    },
-
-    handleClick: function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-
-      this.setState({
-        eventPosY: e.pageY
-      });
-
-      this.toggleDropdownMenu();
-    },
-
-    /**
-     * Callback called when moving cursor away from the conversation entry.
-     * Will close the dropdown menu.
-     */
-    _handleMouseOut: function() {
-      if (this.state.showMenu) {
-        this.toggleDropdownMenu();
-      }
-    },
-
-    render: function() {
-      var roomClasses = classNames({
-        "room-entry": true,
-        "room-active": this._isActive(),
-        "room-opened": this.props.isOpenedRoom
-      });
-      var urlData = (this.props.room.decryptedContext.urls || [])[0] || {};
-      var roomTitle = this.props.room.decryptedContext.roomName ||
-        urlData.description || urlData.location ||
-        mozL10n.get("room_name_untitled_page");
-
-      return (
-        <div className={roomClasses}
-          onClick={this.props.isOpenedRoom ? null : this.handleClickEntry}
-          onMouseLeave={this.props.isOpenedRoom ? null : this._handleMouseOut}
-          ref="roomEntry">
-          <RoomEntryContextItem
-            roomUrls={this.props.room.decryptedContext.urls} />
-          <h2>{roomTitle}</h2>
-          {this.props.isOpenedRoom ? null :
-            <RoomEntryContextButtons
-              dispatcher={this.props.dispatcher}
-              eventPosY={this.state.eventPosY}
-              handleClick={this.handleClick}
-              ref="contextActions"
-              room={this.props.room}
-              showMenu={this.state.showMenu}
-              toggleDropdownMenu={this.toggleDropdownMenu} />}
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Buttons corresponding to each conversation entry.
-   * This component renders the edit button for displaying contextual dropdown
-   * menu for conversation entries. It also holds the dropdown menu.
-   */
-  var RoomEntryContextButtons = React.createClass({
-    propTypes: {
-      dispatcher: React.PropTypes.object.isRequired,
-      eventPosY: React.PropTypes.number.isRequired,
-      handleClick: React.PropTypes.func.isRequired,
-      room: React.PropTypes.object.isRequired,
-      showMenu: React.PropTypes.bool.isRequired,
-      toggleDropdownMenu: React.PropTypes.func.isRequired
-    },
-
-    handleEmailButtonClick: function(event) {
-      event.preventDefault();
-      event.stopPropagation();
-
-      this.props.dispatcher.dispatch(
-        new sharedActions.EmailRoomUrl({
-          roomUrl: this.props.room.roomUrl,
-          from: "panel"
-        })
-      );
-
-      this.props.toggleDropdownMenu();
-    },
-
-    handleCopyButtonClick: function(event) {
-      event.stopPropagation();
-      event.preventDefault();
-
-      this.props.dispatcher.dispatch(new sharedActions.CopyRoomUrl({
-        roomUrl: this.props.room.roomUrl,
-        from: "panel"
-      }));
-
-      this.props.toggleDropdownMenu();
-    },
-
-    handleDeleteButtonClick: function(event) {
-      event.stopPropagation();
-      event.preventDefault();
-
-      this.props.dispatcher.dispatch(new sharedActions.DeleteRoom({
-        roomToken: this.props.room.roomToken
-      }));
-
-      this.props.toggleDropdownMenu();
-    },
-
-    render: function() {
-      return (
-        <div className="room-entry-context-actions">
-          <div
-            className="room-entry-context-edit-btn dropdown-menu-button"
-            onClick={this.props.handleClick}
-            ref="menu-button" />
-          {this.props.showMenu ?
-            <ConversationDropdown
-              eventPosY={this.props.eventPosY}
-              handleCopyButtonClick={this.handleCopyButtonClick}
-              handleDeleteButtonClick={this.handleDeleteButtonClick}
-              handleEmailButtonClick={this.handleEmailButtonClick}
-              ref="menu" /> :
-            null}
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Dropdown menu for each conversation entry.
-   * Because the container element has overflow we need to position the menu
-   * absolutely and have a different element as offset parent for it. We need
-   * eventPosY to make sure the position on the Y Axis is correct while for the
-   * X axis there can be only 2 different positions based on being RTL or not.
-   */
-  var ConversationDropdown = React.createClass({
-    propTypes: {
-      eventPosY: React.PropTypes.number.isRequired,
-      handleCopyButtonClick: React.PropTypes.func.isRequired,
-      handleDeleteButtonClick: React.PropTypes.func.isRequired,
-      handleEmailButtonClick: React.PropTypes.func.isRequired
-    },
-
-    getInitialState: function() {
-      return {
-        openDirUp: false
-      };
-    },
-
-    componentDidMount: function() {
-      var menuNode = this.getDOMNode();
-      var menuNodeRect = menuNode.getBoundingClientRect();
-
-      // Get the parent element and make sure the menu does not overlow its
-      // container.
-      var listNode = loop.shared.utils.findParentNode(this.getDOMNode(),
-                                                      "rooms");
-      var listNodeRect = listNode.getBoundingClientRect();
-
-      // Click offset to not display the menu right next to the area clicked.
-      var offset = 10;
-
-      if (this.props.eventPosY + menuNodeRect.height >=
-          listNodeRect.top + listNodeRect.height) {
-        // Position above click area.
-        menuNode.style.top = this.props.eventPosY - menuNodeRect.height -
-                             listNodeRect.top - offset + "px";
-      } else {
-        // Position below click area.
-        menuNode.style.top = this.props.eventPosY - listNodeRect.top +
-                             offset + "px";
-      }
-    },
-
-    render: function() {
-      var dropdownClasses = classNames({
-        "dropdown-menu": true,
-        "dropdown-menu-up": this.state.openDirUp
-      });
-
-      return (
-        <ul className={dropdownClasses}>
-          <li
-            className="dropdown-menu-item"
-            onClick={this.props.handleCopyButtonClick}
-            ref="copyButton">
-            {mozL10n.get("copy_link_menuitem")}
-          </li>
-          <li
-            className="dropdown-menu-item"
-            onClick={this.props.handleEmailButtonClick}
-            ref="emailButton">
-            {mozL10n.get("email_link_menuitem")}
-          </li>
-          <li
-            className="dropdown-menu-item"
-            onClick={this.props.handleDeleteButtonClick}
-            ref="deleteButton">
-            {mozL10n.get("delete_conversation_menuitem2")}
-          </li>
-        </ul>
-      );
-    }
-  });
-
-  /**
-   * User profile prop can be either an object or null as per mozLoopAPI
-   * and there is no way to express this with React 0.13.3
-   */
-  function userProfileValidator(props, propName, componentName) {
-    if (Object.prototype.toString.call(props[propName]) !== "[object Object]" &&
-        !_.isNull(props[propName])) {
-      return new Error("Required prop `" + propName +
-        "` was not correctly specified in `" + componentName + "`.");
-    }
-  }
-
-  /**
-   * Room list.
-   */
-  var RoomList = React.createClass({
-    mixins: [Backbone.Events, sharedMixins.WindowCloseMixin],
-
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      store: React.PropTypes.instanceOf(loop.store.RoomStore).isRequired
-    },
-
-    getInitialState: function() {
-      return this.props.store.getStoreState();
-    },
-
-    componentDidMount: function() {
-      this.listenTo(this.props.store, "change", this._onStoreStateChanged);
-
-      // XXX this should no longer be necessary once have a better mechanism
-      // for updating the list (possibly as part of the content side of bug
-      // 1074665.
-      this.props.dispatcher.dispatch(new sharedActions.GetAllRooms());
-    },
-
-    componentWillUnmount: function() {
-      this.stopListening(this.props.store);
-    },
-
-    componentWillUpdate: function(nextProps, nextState) {
-      // If we've just created a room, close the panel - the store will open
-      // the room.
-      if (this.state.pendingCreation &&
-          !nextState.pendingCreation && !nextState.error) {
-        this.closeWindow();
-      }
-    },
-
-    _onStoreStateChanged: function() {
-      this.setState(this.props.store.getStoreState());
-    },
-
-    /**
-     * Let the user know we're loading rooms
-     * @returns {Object} React render
-     */
-    _renderLoadingRoomsView: function() {
-      return (
-        <div className="room-list">
-          {this._renderNewRoomButton()}
-          <div className="room-list-loading">
-            <img src="shared/img/animated-spinner.svg" />
-          </div>
-        </div>
-      );
-    },
-
-    _renderNoRoomsView: function() {
-      return (
-        <div className="rooms">
-          {this._renderNewRoomButton()}
-          <div className="room-list-empty">
-            <div className="no-conversations-message">
-              <p className="panel-text-medium">
-                {mozL10n.get("no_conversations_message_heading2")}
-              </p>
-              <p className="panel-text-medium">
-                {mozL10n.get("no_conversations_start_message2")}
-              </p>
-            </div>
-          </div>
-        </div>
-      );
-    },
-
-    _renderNewRoomButton: function() {
-      return (
-        <NewRoomView dispatcher={this.props.dispatcher}
-          inRoom={this.state.openedRoom !== null}
-          pendingOperation={this.state.pendingCreation ||
-                            this.state.pendingInitialRetrieval} />
-      );
-    },
-
-    render: function() {
-      if (this.state.error) {
-        // XXX Better end user reporting of errors.
-        console.error("RoomList error", this.state.error);
-      }
-
-      if (this.state.pendingInitialRetrieval) {
-        return this._renderLoadingRoomsView();
-      }
-
-      if (!this.state.rooms.length) {
-        return this._renderNoRoomsView();
-      }
-
-      return (
-        <div className="rooms">
-          {this._renderNewRoomButton()}
-          <h1>{mozL10n.get(this.state.openedRoom === null ?
-                "rooms_list_recently_browsed" :
-                "rooms_list_currently_browsing")}</h1>
-          <div className="room-list">{
-            this.state.rooms.map(function(room, i) {
-              if (this.state.openedRoom !== null &&
-                room.roomToken !== this.state.openedRoom) {
-                return null;
-              }
-
-              return (
-                <RoomEntry
-                  dispatcher={this.props.dispatcher}
-                  isOpenedRoom={room.roomToken === this.state.openedRoom}
-                  key={room.roomToken}
-                  room={room} />
-              );
-            }, this)
-          }</div>
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Used for creating a new room with or without context.
-   */
-  var NewRoomView = React.createClass({
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      inRoom: React.PropTypes.bool.isRequired,
-      pendingOperation: React.PropTypes.bool.isRequired
-    },
-
-    mixins: [
-      sharedMixins.DocumentVisibilityMixin,
-      React.addons.PureRenderMixin
-    ],
-
-    getInitialState: function() {
-      return {
-        previewImage: "",
-        description: "",
-        url: ""
-      };
-    },
-
-    onDocumentVisible: function() {
-      // We would use onDocumentHidden to null out the data ready for the next
-      // opening. However, this seems to cause an awkward glitch in the display
-      // when opening the panel, and it seems cleaner just to update the data
-      // even if there's a small delay.
-
-      loop.request("GetSelectedTabMetadata").then(function(metadata) {
-        // Bail out when the component is not mounted (anymore).
-        // This occurs during test runs. See bug 1174611 for more info.
-        if (!this.isMounted() || !metadata) {
-          return;
-        }
-
-        var previewImage = metadata.favicon || "";
-        var description = metadata.title || metadata.description;
-        var url = metadata.url;
-        this.setState({
-          previewImage: previewImage,
-          description: description,
-          url: url
-        });
-      }.bind(this));
-    },
-
-    handleCreateButtonClick: function() {
-      var createRoomAction = new sharedActions.CreateRoom();
-
-      createRoomAction.urls = [{
-        location: this.state.url,
-        description: this.state.description,
-        thumbnail: this.state.previewImage
-      }];
-      this.props.dispatcher.dispatch(createRoomAction);
-    },
-
-    handleStopSharingButtonClick: function() {
-      loop.request("HangupAllChatWindows");
-    },
-
-    render: function() {
-      return (
-        <div className="new-room-view">
-          {this.props.inRoom ?
-            <button className="btn btn-info stop-sharing-button"
-              disabled={this.props.pendingOperation}
-              onClick={this.handleStopSharingButtonClick}>
-              {mozL10n.get("panel_stop_sharing_tabs_button")}
-            </button> :
-            <button className="btn btn-info new-room-button"
-              disabled={this.props.pendingOperation}
-              onClick={this.handleCreateButtonClick}>
-              {mozL10n.get("panel_browse_with_friend_button")}
-            </button>}
-        </div>
-      );
-    }
-  });
-
-  /**
-   * E10s not supported view
-   */
-  var E10sNotSupported = React.createClass({
-    propTypes: {
-      onClick: React.PropTypes.func.isRequired
-    },
-
-    render: function() {
-      return (
-        <div className="error-content">
-          <header className="error-title">
-            <img src="shared/img/sad_hello_icon_64x64.svg" />
-            <p className="error-subheader">
-              {mozL10n.get("e10s_not_supported_subheading", {
-                brandShortname: mozL10n.get("clientShortname2")
-              })}
-            </p>
-          </header>
-          <Button additionalClass="e10s-not-supported-button"
-                  caption={mozL10n.get("e10s_not_supported_button_label")}
-                  onClick={this.props.onClick} />
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Panel view.
-   */
-  var PanelView = React.createClass({
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      // Only used for the ui-showcase:
-      gettingStartedSeen: React.PropTypes.bool,
-      notifications: React.PropTypes.object.isRequired,
-      roomStore:
-        React.PropTypes.instanceOf(loop.store.RoomStore).isRequired,
-      // Only used for the ui-showcase:
-      userProfile: React.PropTypes.object
-    },
-
-    getDefaultProps: function() {
-      return {
-        gettingStartedSeen: true
-      };
-    },
-
-    getInitialState: function() {
-      return {
-        fxAEnabled: loop.getStoredRequest(["GetFxAEnabled"]),
-        hasEncryptionKey: loop.getStoredRequest(["GetHasEncryptionKey"]),
-        userProfile: loop.getStoredRequest(["GetUserProfile"]),
-        gettingStartedSeen: loop.getStoredRequest(["GetLoopPref", "gettingStarted.latestFTUVersion"]) >= FTU_VERSION,
-        multiProcessEnabled: loop.getStoredRequest(["IsMultiProcessEnabled"])
-      };
-    },
-
-    _serviceErrorToShow: function(callback) {
-      return new Promise(function(resolve) {
-        loop.request("GetErrors").then(function(errors) {
-          if (!errors || !Object.keys(errors).length) {
-            resolve(null);
-            return;
-          }
-          // Just get the first error for now since more than one should be rare.
-          var firstErrorKey = Object.keys(errors)[0];
-          resolve({
-            type: firstErrorKey,
-            error: errors[firstErrorKey]
-          });
-        });
-      });
-    },
-
-    updateServiceErrors: function() {
-      this._serviceErrorToShow().then(function(serviceError) {
-        if (serviceError) {
-          this.props.notifications.set({
-            id: "service-error",
-            level: "error",
-            message: serviceError.error.friendlyMessage,
-            details: serviceError.error.friendlyDetails,
-            detailsButtonLabel: serviceError.error.friendlyDetailsButtonLabel,
-            detailsButtonCallback: serviceError.error.friendlyDetailsButtonCallback
-          });
-        } else {
-          this.props.notifications.remove(this.props.notifications.get("service-error"));
-        }
-      }.bind(this));
-    },
-
-    _onStatusChanged: function() {
-      loop.requestMulti(
-        ["GetUserProfile"],
-        ["GetHasEncryptionKey"]
-      ).then(function(results) {
-        var profile = results[0];
-        var hasEncryptionKey = results[1];
-        var currUid = this.state.userProfile ? this.state.userProfile.uid : null;
-        var newUid = profile ? profile.uid : null;
-        if (currUid === newUid) {
-          // Update the state of hasEncryptionKey as this might have changed now.
-          this.setState({ hasEncryptionKey: hasEncryptionKey });
-        } else {
-          this.setState({ userProfile: profile });
-        }
-        this.updateServiceErrors();
-      }.bind(this));
-    },
-
-    _gettingStartedSeen: function() {
-      loop.request("GetLoopPref", "gettingStarted.latestFTUVersion").then(function(result) {
-        this.setState({
-          gettingStartedSeen: result >= FTU_VERSION
-        });
-      }.bind(this));
-    },
-
-    componentWillMount: function() {
-      this.updateServiceErrors();
-    },
-
-    componentDidMount: function() {
-      loop.subscribe("LoopStatusChanged", this._onStatusChanged);
-      window.addEventListener("GettingStartedSeen", this._gettingStartedSeen);
-    },
-
-    componentWillUnmount: function() {
-      loop.unsubscribe("LoopStatusChanged", this._onStatusChanged);
-      window.removeEventListener("GettingStartedSeen", this._gettingStartedSeen);
-    },
-
-    handleContextMenu: function(e) {
-      e.preventDefault();
-    },
-
-    launchNonE10sWindow: function(e) {
-      loop.request("GetSelectedTabMetadata").then(function(metadata) {
-        loop.request("OpenNonE10sWindow", metadata.url);
-      });
-    },
-
-    render: function() {
-      var NotificationListView = sharedViews.NotificationListView;
-
-      if (this.state.multiProcessEnabled) {
-        return (
-          <E10sNotSupported onClick={this.launchNonE10sWindow} />
-        );
-      }
-
-      if (!this.props.gettingStartedSeen || !this.state.gettingStartedSeen) {
-        return (
-          <div className="fte-get-started-container"
-               onContextMenu={this.handleContextMenu}>
-            <NotificationListView
-              clearOnDocumentHidden={true}
-              notifications={this.props.notifications} />
-            <GettingStartedView />
-            <ToSView />
-          </div>
-        );
-      }
-      if (!this.state.hasEncryptionKey) {
-        return <SignInRequestView />;
-      }
-
-      return (
-        <div className="panel-content"
-             onContextMenu={this.handleContextMenu} >
-          <div className="beta-ribbon" />
-          <NotificationListView
-            clearOnDocumentHidden={true}
-            notifications={this.props.notifications} />
-            <RoomList dispatcher={this.props.dispatcher}
-              store={this.props.roomStore} />
-          <div className="footer">
-            <div className="user-details">
-              <AccountLink fxAEnabled={this.state.fxAEnabled}
-                           userProfile={this.props.userProfile || this.state.userProfile}/>
-            </div>
-            <div className="signin-details">
-              <SettingsDropdown />
-            </div>
-          </div>
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Panel initialisation.
-   */
-  function init() {
-    var requests = [
-      ["GetAllConstants"],
-      ["GetAllStrings"],
-      ["GetLocale"],
-      ["GetPluralRule"]
-    ];
-    var prefetch = [
-      ["GetLoopPref", "gettingStarted.latestFTUVersion"],
-      ["GetLoopPref", "legal.ToS_url"],
-      ["GetLoopPref", "legal.privacy_url"],
-      ["GetUserProfile"],
-      ["GetFxAEnabled"],
-      ["GetDoNotDisturb"],
-      ["GetHasEncryptionKey"],
-      ["IsMultiProcessEnabled"]
-    ];
-
-    return loop.requestMulti.apply(null, requests.concat(prefetch)).then(function(results) {
-      // `requestIdx` is keyed off the order of the `requests` and `prefetch`
-      // arrays. Be careful to update both when making changes.
-      var requestIdx = 0;
-      var constants = results[requestIdx];
-      // Do the initial L10n setup, we do this before anything
-      // else to ensure the L10n environment is setup correctly.
-      var stringBundle = results[++requestIdx];
-      var locale = results[++requestIdx];
-      var pluralRule = results[++requestIdx];
-      mozL10n.initialize({
-        locale: locale,
-        pluralRule: pluralRule,
-        getStrings: function(key) {
-          if (!(key in stringBundle)) {
-            console.error("No string found for key: ", key);
-            return "{ textContent: '' }";
-          }
-
-          return JSON.stringify({ textContent: stringBundle[key] });
-        }
-      });
-
-      prefetch.forEach(function(req) {
-        req.shift();
-        loop.storeRequest(req, results[++requestIdx]);
-      });
-
-      var notifications = new sharedModels.NotificationCollection();
-      var dispatcher = new loop.Dispatcher();
-      var roomStore = new loop.store.RoomStore(dispatcher, {
-        notifications: notifications,
-        constants: constants
-      });
-
-      React.render(<PanelView
-        dispatcher={dispatcher}
-        notifications={notifications}
-        roomStore={roomStore} />, document.querySelector("#main"));
-
-      document.documentElement.setAttribute("lang", mozL10n.getLanguage());
-      document.documentElement.setAttribute("dir", mozL10n.getDirection());
-      document.body.setAttribute("platform", loop.shared.utils.getPlatform());
-
-      // Notify the window that we've finished initalization and initial layout
-      var evtObject = document.createEvent("Event");
-      evtObject.initEvent("loopPanelInitialized", true, false);
-      window.dispatchEvent(evtObject);
-    });
-  }
-
-  return {
-    AccountLink: AccountLink,
-    ConversationDropdown: ConversationDropdown,
-    E10sNotSupported: E10sNotSupported,
-    GettingStartedView: GettingStartedView,
-    init: init,
-    NewRoomView: NewRoomView,
-    PanelView: PanelView,
-    RoomEntry: RoomEntry,
-    RoomEntryContextButtons: RoomEntryContextButtons,
-    RoomList: RoomList,
-    SettingsDropdown: SettingsDropdown,
-    SignInRequestView: SignInRequestView,
-    ToSView: ToSView
-  };
-})(_, document.mozL10n);
-
-document.addEventListener("DOMContentLoaded", loop.panel.init);
deleted file mode 100644
--- a/browser/extensions/loop/content/panels/js/roomViews.jsx
+++ /dev/null
@@ -1,870 +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/. */
-
-var loop = loop || {};
-loop.roomViews = (function(mozL10n) {
-  "use strict";
-
-  var ROOM_STATES = loop.store.ROOM_STATES;
-  var FAILURE_DETAILS = loop.shared.utils.FAILURE_DETAILS;
-  var sharedActions = loop.shared.actions;
-  var sharedMixins = loop.shared.mixins;
-  var sharedUtils = loop.shared.utils;
-  var sharedViews = loop.shared.views;
-
-  /**
-   * ActiveRoomStore mixin.
-   * @type {Object}
-   */
-  var ActiveRoomStoreMixin = {
-    mixins: [Backbone.Events],
-
-    propTypes: {
-      roomStore: React.PropTypes.instanceOf(loop.store.RoomStore).isRequired
-    },
-
-    componentWillMount: function() {
-      this.listenTo(this.props.roomStore, "change:activeRoom",
-                    this._onActiveRoomStateChanged);
-      this.listenTo(this.props.roomStore, "change:error",
-                    this._onRoomError);
-      this.listenTo(this.props.roomStore, "change:savingContext",
-                    this._onRoomSavingContext);
-    },
-
-    componentWillUnmount: function() {
-      this.stopListening(this.props.roomStore);
-    },
-
-    _onActiveRoomStateChanged: function() {
-      // Only update the state if we're mounted, to avoid the problem where
-      // stopListening doesn't nuke the active listeners during a event
-      // processing.
-      if (this.isMounted()) {
-        this.setState(this.props.roomStore.getStoreState("activeRoom"));
-      }
-    },
-
-    _onRoomError: function() {
-      // Only update the state if we're mounted, to avoid the problem where
-      // stopListening doesn't nuke the active listeners during a event
-      // processing.
-      if (this.isMounted()) {
-        this.setState({ error: this.props.roomStore.getStoreState("error") });
-      }
-    },
-
-    _onRoomSavingContext: function() {
-      // Only update the state if we're mounted, to avoid the problem where
-      // stopListening doesn't nuke the active listeners during a event
-      // processing.
-      if (this.isMounted()) {
-        this.setState({ savingContext: this.props.roomStore.getStoreState("savingContext") });
-      }
-    },
-
-    getInitialState: function() {
-      var storeState = this.props.roomStore.getStoreState("activeRoom");
-      return _.extend({
-        // Used by the UI showcase.
-        roomState: this.props.roomState || storeState.roomState,
-        savingContext: false
-      }, storeState);
-    }
-  };
-
-  /**
-   * Used to display errors in direct calls and rooms to the user.
-   */
-  var FailureInfoView = React.createClass({
-    propTypes: {
-      failureReason: React.PropTypes.string.isRequired
-    },
-
-    /**
-     * Returns the translated message appropraite to the failure reason.
-     *
-     * @return {String} The translated message for the failure reason.
-     */
-    _getMessage: function() {
-      switch (this.props.failureReason) {
-        case FAILURE_DETAILS.NO_MEDIA:
-        case FAILURE_DETAILS.UNABLE_TO_PUBLISH_MEDIA:
-          return mozL10n.get("no_media_failure_message");
-        case FAILURE_DETAILS.TOS_FAILURE:
-          return mozL10n.get("tos_failure_message",
-            { clientShortname: mozL10n.get("clientShortname2") });
-        case FAILURE_DETAILS.ICE_FAILED:
-          return mozL10n.get("ice_failure_message");
-        default:
-          return mozL10n.get("generic_failure_message");
-      }
-    },
-
-    render: function() {
-      return (
-        <div className="failure-info">
-          <div className="failure-info-logo" />
-          <h2 className="failure-info-message">{this._getMessage()}</h2>
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Something went wrong view. Displayed when there's a big problem.
-   */
-  var RoomFailureView = React.createClass({
-    mixins: [sharedMixins.AudioMixin],
-
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      failureReason: React.PropTypes.string
-    },
-
-    componentDidMount: function() {
-      this.play("failure");
-    },
-
-    handleRejoinCall: function() {
-      this.props.dispatcher.dispatch(new sharedActions.JoinRoom());
-    },
-
-    render: function() {
-      var settingsMenuItems = [
-        { id: "help" }
-      ];
-
-      var btnTitle;
-      if (this.props.failureReason === FAILURE_DETAILS.ICE_FAILED) {
-        btnTitle = mozL10n.get("retry_call_button");
-      } else {
-        btnTitle = mozL10n.get("rejoin_button");
-      }
-
-      return (
-        <div className="room-failure">
-          <FailureInfoView failureReason={this.props.failureReason} />
-          <div className="btn-group call-action-group">
-            <button className="btn btn-info btn-rejoin"
-                    onClick={this.handleRejoinCall}>
-              {btnTitle}
-            </button>
-          </div>
-          <loop.shared.views.SettingsControlButton
-            menuBelow={true}
-            menuItems={settingsMenuItems} />
-        </div>
-      );
-    }
-  });
-
-  var SocialShareDropdown = React.createClass({
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      roomUrl: React.PropTypes.string,
-      show: React.PropTypes.bool.isRequired,
-      socialShareProviders: React.PropTypes.array
-    },
-
-    handleAddServiceClick: function(event) {
-      event.preventDefault();
-
-      this.props.dispatcher.dispatch(new sharedActions.AddSocialShareProvider());
-    },
-
-    handleProviderClick: function(event) {
-      event.preventDefault();
-
-      var origin = event.currentTarget.dataset.provider;
-      var provider = this.props.socialShareProviders
-                         .filter(function(socialProvider) {
-                           return socialProvider.origin === origin;
-                         })[0];
-
-      this.props.dispatcher.dispatch(new sharedActions.ShareRoomUrl({
-        provider: provider,
-        roomUrl: this.props.roomUrl,
-        previews: []
-      }));
-    },
-
-    render: function() {
-      // Don't render a thing when no data has been fetched yet.
-      if (!this.props.socialShareProviders) {
-        return null;
-      }
-
-      var cx = classNames;
-      var shareDropdown = cx({
-        "share-service-dropdown": true,
-        "dropdown-menu": true,
-        "visually-hidden": true,
-        "hide": !this.props.show
-      });
-
-      return (
-        <ul className={shareDropdown}>
-          <li className="dropdown-menu-item" onClick={this.handleAddServiceClick}>
-            <i className="icon icon-add-share-service"></i>
-            <span>{mozL10n.get("share_add_service_button")}</span>
-          </li>
-          {this.props.socialShareProviders.length ? <li className="dropdown-menu-separator"/> : null}
-          {
-            this.props.socialShareProviders.map(function(provider, idx) {
-              return (
-                <li className="dropdown-menu-item"
-                    data-provider={provider.origin}
-                    key={"provider-" + idx}
-                    onClick={this.handleProviderClick}>
-                  <img className="icon" src={provider.iconURL}/>
-                  <span>{provider.name}</span>
-                </li>
-              );
-            }.bind(this))
-          }
-        </ul>
-      );
-    }
-  });
-
-  /**
-   * Desktop room invitation view (overlay).
-   */
-  var DesktopRoomInvitationView = React.createClass({
-    statics: {
-      TRIGGERED_RESET_DELAY: 2000
-    },
-
-    mixins: [sharedMixins.DropdownMenuMixin(".room-invitation-overlay")],
-
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      error: React.PropTypes.object,
-      onAddContextClick: React.PropTypes.func,
-      onEditContextClose: React.PropTypes.func,
-      // This data is supplied by the activeRoomStore.
-      roomData: React.PropTypes.object.isRequired,
-      savingContext: React.PropTypes.bool,
-      show: React.PropTypes.bool.isRequired,
-      showEditContext: React.PropTypes.bool.isRequired,
-      socialShareProviders: React.PropTypes.array
-    },
-
-    getInitialState: function() {
-      return {
-        copiedUrl: false,
-        newRoomName: ""
-      };
-    },
-
-    handleEmailButtonClick: function(event) {
-      event.preventDefault();
-
-      var roomData = this.props.roomData;
-      var contextURL = roomData.roomContextUrls && roomData.roomContextUrls[0];
-      if (contextURL) {
-        if (contextURL.location === null) {
-          contextURL = undefined;
-        } else {
-          contextURL = sharedUtils.formatURL(contextURL.location).hostname;
-        }
-      }
-
-      this.props.dispatcher.dispatch(
-        new sharedActions.EmailRoomUrl({
-          roomUrl: roomData.roomUrl,
-          roomDescription: contextURL,
-          from: "conversation"
-        }));
-    },
-
-    handleFacebookButtonClick: function(event) {
-      event.preventDefault();
-
-      this.props.dispatcher.dispatch(new sharedActions.FacebookShareRoomUrl({
-        from: "conversation",
-        roomUrl: this.props.roomData.roomUrl
-      }));
-    },
-
-    handleCopyButtonClick: function(event) {
-      event.preventDefault();
-
-      this.props.dispatcher.dispatch(new sharedActions.CopyRoomUrl({
-        roomUrl: this.props.roomData.roomUrl,
-        from: "conversation"
-      }));
-
-      this.setState({ copiedUrl: true });
-      setTimeout(this.resetTriggeredButtons, this.constructor.TRIGGERED_RESET_DELAY);
-    },
-
-    /**
-     * Reset state of triggered buttons if necessary
-     */
-    resetTriggeredButtons: function() {
-      if (this.state.copiedUrl) {
-        this.setState({ copiedUrl: false });
-      }
-    },
-
-    handleEditContextClose: function() {
-      if (this.props.onEditContextClose) {
-        this.props.onEditContextClose();
-      }
-    },
-
-    render: function() {
-      if (!this.props.show || !this.props.roomData.roomUrl) {
-        return null;
-      }
-
-      var cx = classNames;
-      return (
-        <div className="room-invitation-overlay">
-          <div className="room-invitation-content">
-            <p className={cx({ hide: this.props.showEditContext })}>
-              {mozL10n.get("invite_header_text2")}
-            </p>
-          </div>
-          <div className={cx({
-            "btn-group": true,
-            "call-action-group": true,
-            hide: this.props.showEditContext
-          })}>
-            <div className={cx({
-                "btn-copy": true,
-                "invite-button": true,
-                "triggered": this.state.copiedUrl
-              })}
-              onClick={this.handleCopyButtonClick}>
-              <img src="shared/img/glyph-link-16x16.svg" />
-              <p>{mozL10n.get(this.state.copiedUrl ?
-                "invite_copied_link_button" : "invite_copy_link_button")}</p>
-            </div>
-            <div className="btn-email invite-button"
-              onClick={this.handleEmailButtonClick}
-              onMouseOver={this.resetTriggeredButtons}>
-              <img src="shared/img/glyph-email-16x16.svg" />
-              <p>{mozL10n.get("invite_email_link_button")}</p>
-            </div>
-            <div className="btn-facebook invite-button"
-              onClick={this.handleFacebookButtonClick}
-              onMouseOver={this.resetTriggeredButtons}>
-              <img src="shared/img/glyph-facebook-16x16.svg" />
-              <p>{mozL10n.get("invite_facebook_button3")}</p>
-            </div>
-          </div>
-          <SocialShareDropdown
-            dispatcher={this.props.dispatcher}
-            ref="menu"
-            roomUrl={this.props.roomData.roomUrl}
-            show={this.state.showMenu}
-            socialShareProviders={this.props.socialShareProviders} />
-          <DesktopRoomEditContextView
-            dispatcher={this.props.dispatcher}
-            error={this.props.error}
-            onClose={this.handleEditContextClose}
-            roomData={this.props.roomData}
-            savingContext={this.props.savingContext}
-            show={this.props.showEditContext} />
-        </div>
-      );
-    }
-  });
-
-  var DesktopRoomEditContextView = React.createClass({
-    mixins: [React.addons.LinkedStateMixin],
-    maxRoomNameLength: 124,
-
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      error: React.PropTypes.object,
-      onClose: React.PropTypes.func,
-      // This data is supplied by the activeRoomStore.
-      roomData: React.PropTypes.object.isRequired,
-      savingContext: React.PropTypes.bool.isRequired,
-      show: React.PropTypes.bool.isRequired
-    },
-
-    componentWillMount: function() {
-      this._fetchMetadata();
-    },
-
-    componentWillReceiveProps: function(nextProps) {
-      var newState = {};
-      // When the 'show' prop is changed from outside this component, we do need
-      // to update the state.
-      if (("show" in nextProps) && nextProps.show !== this.props.show) {
-        newState.show = nextProps.show;
-        if (nextProps.show) {
-          this._fetchMetadata();
-        }
-      }
-      // When we receive an update for the `roomData` property, make sure that
-      // the current form fields reflect reality. This is necessary, because the
-      // form state is maintained in the components' state.
-      if (nextProps.roomData) {
-        // Right now it's only necessary to update the form input states when
-        // they contain no text yet.
-        if (!this.state.newRoomName && nextProps.roomData.roomName) {
-          newState.newRoomName = nextProps.roomData.roomName;
-        }
-        var url = this._getURL(nextProps.roomData);
-        if (url) {
-          if (!this.state.newRoomURL && url.location) {
-            newState.newRoomURL = url.location;
-          }
-          if (!this.state.newRoomDescription && url.description) {
-            newState.newRoomDescription = url.description;
-          }
-          if (!this.state.newRoomThumbnail && url.thumbnail) {
-            newState.newRoomThumbnail = url.thumbnail;
-          }
-        }
-      }
-
-      // Feature support: when a context save completed without error, we can
-      // close the context edit form.
-      if (("savingContext" in nextProps) && this.props.savingContext &&
-          this.props.savingContext !== nextProps.savingContext && this.state.show
-          && !this.props.error && !nextProps.error) {
-        newState.show = false;
-        if (this.props.onClose) {
-          this.props.onClose();
-        }
-      }
-
-      if (Object.getOwnPropertyNames(newState).length) {
-        this.setState(newState);
-      }
-    },
-
-    getInitialState: function() {
-      var url = this._getURL();
-      return {
-        // `availableContext` prop only used in tests.
-        availableContext: null,
-        show: this.props.show,
-        newRoomName: this.props.roomData.roomName || "",
-        newRoomURL: url && url.location || "",
-        newRoomDescription: url && url.description || "",
-        newRoomThumbnail: url && url.thumbnail || ""
-      };
-    },
-
-    _fetchMetadata: function() {
-      loop.request("GetSelectedTabMetadata").then(function(metadata) {
-        var previewImage = metadata.favicon || "";
-        var description = metadata.title || metadata.description;
-        var metaUrl = metadata.url;
-        this.setState({
-          availableContext: {
-            previewImage: previewImage,
-            description: description,
-            url: metaUrl
-          }
-       });
-      }.bind(this));
-    },
-
-    handleCloseClick: function(event) {
-      event.stopPropagation();
-      event.preventDefault();
-
-      this.setState({ show: false });
-      if (this.props.onClose) {
-        this.props.onClose();
-      }
-    },
-
-    handleContextClick: function(event) {
-      event.stopPropagation();
-      event.preventDefault();
-
-      var url = this._getURL();
-      if (!url || !url.location) {
-        return;
-      }
-
-      loop.requestMulti(
-        ["OpenURL", url.location],
-        ["TelemetryAddValue", "LOOP_ROOM_CONTEXT_CLICK", 1]);
-    },
-
-    handleFormSubmit: function(event) {
-      event && event.preventDefault();
-
-      this.props.dispatcher.dispatch(new sharedActions.UpdateRoomContext({
-        roomToken: this.props.roomData.roomToken,
-        newRoomName: this.state.newRoomName,
-        newRoomURL: this.state.newRoomURL,
-        newRoomDescription: this.state.newRoomDescription,
-        newRoomThumbnail: this.state.newRoomThumbnail
-      }));
-    },
-
-    handleTextareaKeyDown: function(event) {
-      // Submit the form as soon as the user press Enter in that field
-      // Note: We're using a textarea instead of a simple text input to display
-      // placeholder and entered text on two lines, to circumvent l10n
-      // rendering/UX issues for some locales.
-      if (event.which === 13) {
-        this.handleFormSubmit(event);
-      }
-    },
-
-    /**
-     * Utility function to extract URL context data from the `roomData` property
-     * that can also be supplied as an argument.
-     *
-     * @param  {Object} roomData Optional room data object to use, equivalent to
-     *                           the activeRoomStore state.
-     * @return {Object} The first context URL found on the `roomData` object.
-     */
-    _getURL: function(roomData) {
-      roomData = roomData || this.props.roomData;
-      return this.props.roomData.roomContextUrls &&
-        this.props.roomData.roomContextUrls[0];
-    },
-
-    render: function() {
-      if (!this.state.show) {
-        return null;
-      }
-
-      var url = this._getURL();
-      var thumbnail = url && url.thumbnail || "shared/img/icons-16x16.svg#globe";
-      var urlDescription = url && url.description || "";
-      var location = url && url.location || "";
-
-      var cx = classNames;
-      var availableContext = this.state.availableContext;
-      return (
-        <div className="room-context">
-          <p className={cx({ "error": !!this.props.error,
-                            "error-display-area": true })}>
-            {mozL10n.get("rooms_change_failed_label")}
-          </p>
-          <h2 className="room-context-header">{mozL10n.get("context_inroom_header")}</h2>
-          <form onSubmit={this.handleFormSubmit}>
-            <input className="room-context-name"
-              maxLength={this.maxRoomNameLength}
-              onKeyDown={this.handleTextareaKeyDown}
-              placeholder={mozL10n.get("context_edit_name_placeholder")}
-              type="text"
-              valueLink={this.linkState("newRoomName")} />
-            <input className="room-context-url"
-              disabled={availableContext && availableContext.url === this.state.newRoomURL}
-              onKeyDown={this.handleTextareaKeyDown}
-              placeholder="https://"
-              type="text"
-              valueLink={this.linkState("newRoomURL")} />
-            <textarea className="room-context-comments"
-              onKeyDown={this.handleTextareaKeyDown}
-              placeholder={mozL10n.get("context_edit_comments_placeholder")}
-              rows="2" type="text"
-              valueLink={this.linkState("newRoomDescription")} />
-            <sharedViews.ButtonGroup>
-              <sharedViews.Button additionalClass="button-cancel"
-                caption={mozL10n.get("context_cancel_label")}
-                onClick={this.handleCloseClick} />
-              <sharedViews.Button additionalClass="button-accept"
-                caption={mozL10n.get("context_done_label")}
-                disabled={this.props.savingContext}
-                onClick={this.handleFormSubmit} />
-            </sharedViews.ButtonGroup>
-          </form>
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Desktop room conversation view.
-   */
-  var DesktopRoomConversationView = React.createClass({
-    mixins: [
-      ActiveRoomStoreMixin,
-      sharedMixins.DocumentTitleMixin,
-      sharedMixins.MediaSetupMixin,
-      sharedMixins.RoomsAudioMixin,
-      sharedMixins.WindowCloseMixin
-    ],
-
-    propTypes: {
-      chatWindowDetached: React.PropTypes.bool.isRequired,
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      // The poster URLs are for UI-showcase testing and development.
-      localPosterUrl: React.PropTypes.string,
-      onCallTerminated: React.PropTypes.func.isRequired,
-      remotePosterUrl: React.PropTypes.string,
-      roomStore: React.PropTypes.instanceOf(loop.store.RoomStore).isRequired
-    },
-
-    getInitialState: function() {
-      return {
-        showEditContext: false
-      };
-    },
-
-    componentWillUpdate: function(nextProps, nextState) {
-      // The SDK needs to know about the configuration and the elements to use
-      // for display. So the best way seems to pass the information here - ideally
-      // the sdk wouldn't need to know this, but we can't change that.
-      if (this.state.roomState !== ROOM_STATES.MEDIA_WAIT &&
-          nextState.roomState === ROOM_STATES.MEDIA_WAIT) {
-        this.props.dispatcher.dispatch(new sharedActions.SetupStreamElements({
-          publisherConfig: this.getDefaultPublisherConfig({
-            publishVideo: !this.state.videoMuted
-          })
-        }));
-      }
-
-      // Automatically start sharing a tab now we're ready to share.
-      if (this.state.roomState !== ROOM_STATES.SESSION_CONNECTED &&
-          nextState.roomState === ROOM_STATES.SESSION_CONNECTED) {
-        this.props.dispatcher.dispatch(new sharedActions.StartBrowserShare());
-      }
-    },
-
-    /**
-     * User clicked on the "Leave" button.
-     */
-    leaveRoom: function() {
-      if (this.state.used) {
-        this.props.dispatcher.dispatch(new sharedActions.LeaveRoom());
-      } else {
-        this.closeWindow();
-      }
-    },
-
-    /**
-     * Used to control publishing a stream - i.e. to mute a stream
-     *
-     * @param {String} type The type of stream, e.g. "audio" or "video".
-     * @param {Boolean} enabled True to enable the stream, false otherwise.
-     */
-    publishStream: function(type, enabled) {
-      this.props.dispatcher.dispatch(
-        new sharedActions.SetMute({
-          type: type,
-          enabled: enabled
-        }));
-    },
-
-    /**
-     * Determine if the invitation controls should be shown.
-     *
-     * @return {Boolean} True if there's no guests.
-     */
-    _shouldRenderInvitationOverlay: function() {
-      var hasGuests = typeof this.state.participants === "object" &&
-        this.state.participants.filter(function(participant) {
-          return !participant.owner;
-        }).length > 0;
-
-      // Don't show if the room has participants whether from the room state or
-      // there being non-owner guests in the participants array.
-      return this.state.roomState !== ROOM_STATES.HAS_PARTICIPANTS && !hasGuests;
-    },
-
-    /**
-     * Works out if remote video should be rended or not, depending on the
-     * room state and other flags.
-     *
-     * @return {Boolean} True if remote video should be rended.
-     *
-     * XXX Refactor shouldRenderRemoteVideo & shouldRenderLoading into one fn
-     *     that returns an enum
-     */
-    shouldRenderRemoteVideo: function() {
-      switch (this.state.roomState) {
-        case ROOM_STATES.HAS_PARTICIPANTS:
-          if (this.state.remoteVideoEnabled) {
-            return true;
-          }
-
-          if (this.state.mediaConnected) {
-            // since the remoteVideo hasn't yet been enabled, if the
-            // media is connected, then we should be displaying an avatar.
-            return false;
-          }
-
-          return true;
-
-        case ROOM_STATES.READY:
-        case ROOM_STATES.GATHER:
-        case ROOM_STATES.INIT:
-        case ROOM_STATES.JOINING:
-        case ROOM_STATES.SESSION_CONNECTED:
-        case ROOM_STATES.JOINED:
-        case ROOM_STATES.MEDIA_WAIT:
-          // this case is so that we don't show an avatar while waiting for
-          // the other party to connect
-          return true;
-
-        case ROOM_STATES.CLOSING:
-          return true;
-
-        default:
-          console.warn("DesktopRoomConversationView.shouldRenderRemoteVideo:" +
-            " unexpected roomState: ", this.state.roomState);
-          return true;
-      }
-    },
-
-    /**
-     * Should we render a visual cue to the user (e.g. a spinner) that a local
-     * stream is on its way from the camera?
-     *
-     * @returns {boolean}
-     * @private
-     */
-    _isLocalLoading: function() {
-      return this.state.roomState === ROOM_STATES.MEDIA_WAIT &&
-             !this.state.localSrcMediaElement;
-    },
-
-    /**
-     * Should we render a visual cue to the user (e.g. a spinner) that a remote
-     * stream is on its way from the other user?
-     *
-     * @returns {boolean}
-     * @private
-     */
-    _isRemoteLoading: function() {
-      return !!(this.state.roomState === ROOM_STATES.HAS_PARTICIPANTS &&
-                !this.state.remoteSrcMediaElement &&
-                !this.state.mediaConnected);
-    },
-
-    handleAddContextClick: function() {
-      this.setState({ showEditContext: true });
-    },
-
-    handleEditContextClick: function() {
-      this.setState({ showEditContext: !this.state.showEditContext });
-    },
-
-    handleEditContextClose: function() {
-      this.setState({ showEditContext: false });
-    },
-
-    componentDidUpdate: function(prevProps, prevState) {
-      // Handle timestamp and window closing only when the call has terminated.
-      if (prevState.roomState === ROOM_STATES.ENDED &&
-          this.state.roomState === ROOM_STATES.ENDED) {
-        this.props.onCallTerminated();
-      }
-    },
-
-    handleContextMenu: function(e) {
-      e.preventDefault();
-    },
-
-    render: function() {
-      if (this.state.roomName || this.state.roomContextUrls) {
-        var roomTitle = this.state.roomName ||
-                        this.state.roomContextUrls[0].description ||
-                        this.state.roomContextUrls[0].location;
-        this.setTitle(roomTitle);
-      }
-
-      var shouldRenderInvitationOverlay = this._shouldRenderInvitationOverlay();
-      var shouldRenderEditContextView = this.state.showEditContext;
-      var roomData = this.props.roomStore.getStoreState("activeRoom");
-
-      switch (this.state.roomState) {
-        case ROOM_STATES.FAILED:
-        case ROOM_STATES.FULL: {
-          // Note: While rooms are set to hold a maximum of 2 participants, the
-          //       FULL case should never happen on desktop.
-          return (
-            <RoomFailureView
-              dispatcher={this.props.dispatcher}
-              failureReason={this.state.failureReason} />
-          );
-        }
-        case ROOM_STATES.ENDED: {
-          // When conversation ended we either display a feedback form or
-          // close the window. This is decided in the AppControllerView.
-          return null;
-        }
-        default: {
-          var settingsMenuItems = [
-            {
-              id: "edit",
-              enabled: !this.state.showEditContext,
-              visible: true,
-              onClick: this.handleEditContextClick
-            },
-            { id: "help" }
-          ];
-          return (
-            <div className="room-conversation-wrapper desktop-room-wrapper"
-              onContextMenu={this.handleContextMenu}>
-              <sharedViews.MediaLayoutView
-                dispatcher={this.props.dispatcher}
-                displayScreenShare={false}
-                isLocalLoading={this._isLocalLoading()}
-                isRemoteLoading={this._isRemoteLoading()}
-                isScreenShareLoading={false}
-                localPosterUrl={this.props.localPosterUrl}
-                localSrcMediaElement={this.state.localSrcMediaElement}
-                localVideoMuted={this.state.videoMuted}
-                matchMedia={this.state.matchMedia || window.matchMedia.bind(window)}
-                remotePosterUrl={this.props.remotePosterUrl}
-                remoteSrcMediaElement={this.state.remoteSrcMediaElement}
-                renderRemoteVideo={this.shouldRenderRemoteVideo()}
-                screenShareMediaElement={this.state.screenShareMediaElement}
-                screenSharePosterUrl={null}
-                showInitialContext={false}
-                useDesktopPaths={true}>
-                <sharedViews.ConversationToolbar
-                  audio={{ enabled: !this.state.audioMuted, visible: true }}
-                  dispatcher={this.props.dispatcher}
-                  hangup={this.leaveRoom}
-                  publishStream={this.publishStream}
-                  settingsMenuItems={settingsMenuItems}
-                  show={!shouldRenderEditContextView}
-                  showHangup={this.props.chatWindowDetached}
-                  video={{ enabled: !this.state.videoMuted, visible: true }} />
-                <DesktopRoomInvitationView
-                  dispatcher={this.props.dispatcher}
-                  error={this.state.error}
-                  onAddContextClick={this.handleAddContextClick}
-                  onEditContextClose={this.handleEditContextClose}
-                  roomData={roomData}
-                  savingContext={this.state.savingContext}
-                  show={shouldRenderInvitationOverlay}
-                  showEditContext={shouldRenderInvitationOverlay && shouldRenderEditContextView}
-                  socialShareProviders={this.state.socialShareProviders} />
-                <DesktopRoomEditContextView
-                  dispatcher={this.props.dispatcher}
-                  error={this.state.error}
-                  onClose={this.handleEditContextClose}
-                  roomData={roomData}
-                  savingContext={this.state.savingContext}
-                  show={!shouldRenderInvitationOverlay && shouldRenderEditContextView} />
-              </sharedViews.MediaLayoutView>
-            </div>
-          );
-        }
-      }
-    }
-  });
-
-  return {
-    ActiveRoomStoreMixin: ActiveRoomStoreMixin,
-    FailureInfoView: FailureInfoView,
-    RoomFailureView: RoomFailureView,
-    SocialShareDropdown: SocialShareDropdown,
-    DesktopRoomEditContextView: DesktopRoomEditContextView,
-    DesktopRoomConversationView: DesktopRoomConversationView,
-    DesktopRoomInvitationView: DesktopRoomInvitationView
-  };
-
-})(document.mozL10n || navigator.mozL10n);
deleted file mode 100644
--- a/browser/extensions/loop/content/shared/img/empty_conversations.svg
+++ /dev/null
@@ -1,1 +0,0 @@
-<svg width="128" height="128" viewBox="0 0 128 128" xmlns="http://www.w3.org/2000/svg"><title>Hello_Conversations@1x</title><g fill="none" fill-rule="evenodd"><g fill-opacity=".8" fill="#D8D8D8"><path d="M92.6857529,36.4972478 C94.0074365,36.7092895 95.3714061,36.8202443 96.765995,36.8202443 C99.1850012,36.8202443 101.507433,36.4843962 103.682261,35.8711789 C108.95254,37.9114461 116.428855,40.6388416 116.883051,39.8656193 C114.228301,36.8141527 112.88469,33.6883692 112.206137,31.3849465 C116.112562,28.0573291 118.529038,23.471195 118.529038,18.4099191 C118.529038,8.2443202 108.782585,0 96.765995,0 C91.4188478,0 86.5218392,1.63140695 82.732597,4.33762852 C89.8596493,10.1193334 94.2968293,18.2546551 94.2968293,27.2647358 C94.2968293,30.4757572 93.7334546,33.5755489 92.6857559,36.4972483 Z" transform="translate(5 32)"/><path d="M20.9154969,36.8064637 C18.8009901,36.7376004 16.766387,36.4124345 14.846777,35.8711789 C9.57649798,37.9114461 2.10018319,40.6388416 1.64598695,39.8656193 C4.30073659,36.8141527 5.64434776,33.6883692 6.32290093,31.3849465 C2.41647584,28.0573291 0,23.471195 0,18.4099191 C0,8.2443202 9.74645257,0 21.7630429,0 C25.8798482,0 29.7298309,0.967027199 33.0128711,2.64707103 C24.5779765,8.47249535 19.1912092,17.3376798 19.1912092,27.2647358 C19.1912092,30.5889558 19.7953644,33.7943831 20.9154969,36.8064637 Z" transform="translate(5 32)"/></g><path d="M62,31 C43.77575,31 29,43.92775 29,59.875 C29,68.21575 33.06725,75.710875 39.531125,80.9785 C39.20525,82.084 38.763875,83.2885 38.13275,84.571375 C35.171,90.610375 33.125,92.875 33.125,92.875 C33.125,92.875 40.562375,91.4725 46.898375,88.321 C48.03275,87.755875 48.952625,87.211375 49.785875,86.683375 C53.564375,88.003375 57.681125,88.75 62,88.75 C80.22425,88.75 95,75.82225 95,59.875 C95,43.92775 80.22425,31 62,31 L62,31 Z M72.3125,47.24425 C75.303125,47.24425 77.728625,49.665625 77.728625,52.65625 C77.728625,55.646875 75.303125,58.072375 72.3125,58.072375 C69.321875,58.072375 66.9005,55.646875 66.9005,52.65625 C66.9005,49.665625 69.321875,47.24425 72.3125,47.24425 L72.3125,47.24425 Z M51.6875,47.24425 C54.678125,47.24425 57.103625,49.665625 57.103625,52.65625 C57.103625,55.646875 54.678125,58.072375 51.6875,58.072375 C48.696875,58.072375 46.2755,55.646875 46.2755,52.65625 C46.2755,49.665625 48.696875,47.24425 51.6875,47.24425 L51.6875,47.24425 Z M62,78.64375 C45.231875,78.64375 41.375,64 41.375,64 C41.375,64 50.099375,68.125 62,68.125 C73.715,68.125 82.625,64 82.625,64 C82.625,64 78.768125,78.64375 62,78.64375 L62,78.64375 Z" fill="#00A9DC"/></g></svg>
\ No newline at end of file
deleted file mode 100644
index 104990416edcaf4708a0623c919b7b40de4deda6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index c07523e76efacc1b2f2e7f77389c6f33f42ed2f6..0000000000000000000000000000000000000000
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
--- a/browser/extensions/loop/content/shared/js/linkifiedTextView.jsx
+++ /dev/null
@@ -1,116 +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/. */
-
-var loop = loop || {};
-loop.shared = loop.shared || {};
-loop.shared.views = loop.shared.views || {};
-loop.shared.views.LinkifiedTextView = (function() {
-  "use strict";
-
-  /**
-   * Given a rawText property, renderer a version of that text with any
-   * links starting with http://, https://, or ftp:// as actual clickable
-   * links inside a <p> container.
-   */
-  var LinkifiedTextView = React.createClass({
-    propTypes: {
-      // Call this instead of allowing the default <a> click semantics, if
-      // given.  Also causes sendReferrer and suppressTarget attributes to be
-      // ignored.
-      linkClickHandler: React.PropTypes.func,
-      // The text to be linkified.
-      rawText: React.PropTypes.string.isRequired,
-      // Should the links send a referrer?  Defaults to false.
-      sendReferrer: React.PropTypes.bool,
-      // Should we suppress target="_blank" on the link? Defaults to false.
-      // Mostly for testing use.
-      suppressTarget: React.PropTypes.bool
-    },
-
-    mixins: [
-      React.addons.PureRenderMixin
-    ],
-
-    _handleClickEvent: function(e) {
-      e.preventDefault();
-      e.stopPropagation();
-
-      this.props.linkClickHandler(e.currentTarget.href);
-    },
-
-    _generateLinkAttributes: function(href) {
-      var linkAttributes = {
-        href: href
-      };
-
-      if (this.props.linkClickHandler) {
-        linkAttributes.onClick = this._handleClickEvent;
-
-        // if this is specified, we short-circuit return to avoid unnecessarily
-        // creating target and rel attributes.
-        return linkAttributes;
-      }
-
-      if (!this.props.suppressTarget) {
-        linkAttributes.target = "_blank";
-      }
-
-      if (!this.props.sendReferrer) {
-        linkAttributes.rel = "noreferrer";
-      }
-
-      return linkAttributes;
-    },
-
-    /**                                                              a
-     * Parse the given string into an array of strings and React <a> elements
-     * in the order in which they should be rendered (i.e. FIFO).
-     *
-     * @param {String} s the raw string to be parsed
-     *
-     * @returns {Array} of strings and React <a> elements in order.
-     */
-    parseStringToElements: function(s) {
-      var elements = [];
-      var result = loop.shared.urlRegExps.fullUrlMatch.exec(s);
-      var reactElementsCounter = 0; // For giving keys to each ReactElement.
-
-      while (result) {
-        // If there's text preceding the first link, push it onto the array
-        // and update the string pointer.
-        if (result.index) {
-          elements.push(s.substr(0, result.index));
-          s = s.substr(result.index);
-        }
-
-        // Push the first link itself, and advance the string pointer again.
-        elements.push(
-          <a { ...this._generateLinkAttributes(result[0]) }
-            key={reactElementsCounter++}>
-            {result[0]}
-          </a>
-        );
-        s = s.substr(result[0].length);
-
-        // Check for another link, and perhaps continue...
-        result = loop.shared.urlRegExps.fullUrlMatch.exec(s);
-      }
-
-      if (s) {
-        elements.push(s);
-      }
-
-      return elements;
-    },
-
-    render: function() {
-      return (
-        <p>{this.parseStringToElements(this.props.rawText)}</p>
-      );
-    }
-  });
-
-  return LinkifiedTextView;
-
-})();
deleted file mode 100644
--- a/browser/extensions/loop/content/shared/js/textChatView.jsx
+++ /dev/null
@@ -1,427 +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/. */
-
-var loop = loop || {};
-loop.shared = loop.shared || {};
-loop.shared.views = loop.shared.views || {};
-loop.shared.views.chat = (function(mozL10n) {
-  "use strict";
-
-  var sharedActions = loop.shared.actions;
-  var sharedMixins = loop.shared.mixins;
-  var sharedViews = loop.shared.views;
-  var CHAT_MESSAGE_TYPES = loop.store.CHAT_MESSAGE_TYPES;
-  var CHAT_CONTENT_TYPES = loop.shared.utils.CHAT_CONTENT_TYPES;
-
-  /**
-   * Renders an individual entry for the text chat entries view.
-   */
-  var TextChatEntry = React.createClass({
-    mixins: [React.addons.PureRenderMixin],
-
-    propTypes: {
-      contentType: React.PropTypes.string.isRequired,
-      message: React.PropTypes.string.isRequired,
-      showTimestamp: React.PropTypes.bool.isRequired,
-      timestamp: React.PropTypes.string.isRequired,
-      type: React.PropTypes.string.isRequired
-    },
-
-    /**
-     * Pretty print timestamp. From time in milliseconds to HH:MM
-     * (or L10N equivalent).
-     *
-     */
-    _renderTimestamp: function() {
-      var date = new Date(this.props.timestamp);
-      var language = mozL10n.language ? mozL10n.language.code
-                                      : mozL10n.getLanguage();
-
-      return (
-        <span className="text-chat-entry-timestamp">
-          {date.toLocaleTimeString(language,
-                                   { hour: "numeric", minute: "numeric",
-                                   hour12: false })}
-        </span>
-      );
-    },
-
-    render: function() {
-      var classes = classNames({
-        "text-chat-entry": true,
-        "received": this.props.type === CHAT_MESSAGE_TYPES.RECEIVED,
-        "sent": this.props.type === CHAT_MESSAGE_TYPES.SENT,
-        "special": this.props.type === CHAT_MESSAGE_TYPES.SPECIAL,
-        "room-name": this.props.contentType === CHAT_CONTENT_TYPES.ROOM_NAME
-      });
-
-      var optionalProps = {};
-      if (loop.shared.utils.isDesktop()) {
-        optionalProps.linkClickHandler = function(url) {
-          loop.request("OpenURL", url);
-        };
-      }
-
-      return (
-        <div className={classes}>
-          <sharedViews.LinkifiedTextView {...optionalProps}
-            rawText={this.props.message} />
-          <span className="text-chat-arrow" />
-          {this.props.showTimestamp ? this._renderTimestamp() : null}
-        </div>
-      );
-    }
-  });
-
-  var TextChatRoomName = React.createClass({
-    mixins: [React.addons.PureRenderMixin],
-
-    propTypes: {
-      message: React.PropTypes.string.isRequired
-    },
-
-    render: function() {
-      return (
-        <div className="text-chat-header special room-name">
-          <p>{mozL10n.get("rooms_welcome_title", { conversationName: this.props.message })}</p>
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Manages the text entries in the chat entries view. This is split out from
-   * TextChatView so that scrolling can be managed more efficiently - this
-   * component only updates when the message list is changed.
-   */
-  var TextChatEntriesView = React.createClass({
-    mixins: [
-      React.addons.PureRenderMixin,
-      sharedMixins.AudioMixin
-    ],
-
-    statics: {
-      ONE_MINUTE: 60
-    },
-
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      messageList: React.PropTypes.arrayOf(React.PropTypes.object).isRequired,
-      showInitialContext: React.PropTypes.bool.isRequired,
-      useDesktopPaths: React.PropTypes.bool.isRequired
-    },
-
-    getInitialState: function() {
-      return {
-        receivedMessageCount: 0
-      };
-    },
-
-    _hasChatMessages: function() {
-      return this.props.messageList.some(function(message) {
-        return message.contentType === CHAT_CONTENT_TYPES.TEXT;
-      });
-    },
-
-    componentWillUpdate: function() {
-      var node = this.getDOMNode();
-      if (!node) {
-        return;
-      }
-      // Scroll only if we're right at the bottom of the display, or if we've
-      // not had any chat messages so far.
-      this.shouldScroll = !this._hasChatMessages() ||
-        node.scrollHeight === node.scrollTop + node.clientHeight;
-    },
-
-    componentWillReceiveProps: function(nextProps) {
-      var receivedMessageCount = nextProps.messageList.filter(function(message) {
-        return message.type === CHAT_MESSAGE_TYPES.RECEIVED;
-      }).length;
-
-      // If the number of received messages has increased, we play a sound.
-      if (receivedMessageCount > this.state.receivedMessageCount) {
-        this.play("message");
-        this.setState({ receivedMessageCount: receivedMessageCount });
-      }
-    },
-
-    componentDidUpdate: function() {
-      // Don't scroll if we haven't got any chat messages yet - e.g. for context
-      // display, we want to display starting at the top.
-      if (this.shouldScroll && this._hasChatMessages()) {
-        // This ensures the paint is complete.
-        window.requestAnimationFrame(function() {
-          try {
-            var node = this.getDOMNode();
-            node.scrollTop = node.scrollHeight - node.clientHeight;
-          } catch (ex) {
-            console.error("TextChatEntriesView.componentDidUpdate exception", ex);
-          }
-        }.bind(this));
-      }
-    },
-
-    render: function() {
-      /* Keep track of the last printed timestamp. */
-      var lastTimestamp = 0;
-
-      var entriesClasses = classNames({
-        "text-chat-entries": true
-      });
-
-      return (
-        <div className={entriesClasses}>
-          <div className="text-chat-scroller">
-            {
-              this.props.messageList.map(function(entry, i) {
-                if (entry.type === CHAT_MESSAGE_TYPES.SPECIAL) {
-                  if (!this.props.showInitialContext) { return null; }
-                  switch (entry.contentType) {
-                    case CHAT_CONTENT_TYPES.ROOM_NAME:
-                      return (
-                        <TextChatRoomName
-                          key={i}
-                          message={entry.message} />
-                      );
-                    case CHAT_CONTENT_TYPES.CONTEXT:
-                      return (
-                        <div className="context-url-view-wrapper" key={i}>
-                          <sharedViews.ContextUrlView
-                            allowClick={true}
-                            description={entry.message}
-                            dispatcher={this.props.dispatcher}
-                            thumbnail={entry.extraData.thumbnail}
-                            url={entry.extraData.location}
-                            useDesktopPaths={this.props.useDesktopPaths} />
-                        </div>
-                      );
-                    default:
-                      console.error("Unsupported contentType",
-                                    entry.contentType);
-                      return null;
-                  }
-                }
-
-                /* For SENT messages there is no received timestamp. */
-                var timestamp = entry.receivedTimestamp || entry.sentTimestamp;
-
-                var timeDiff = this._isOneMinDelta(timestamp, lastTimestamp);
-                var shouldShowTimestamp = this._shouldShowTimestamp(i,
-                                                                    timeDiff);
-
-                if (shouldShowTimestamp) {
-                  lastTimestamp = timestamp;
-                }
-
-                return (
-                  <TextChatEntry contentType={entry.contentType}
-                                 key={i}
-                                 message={entry.message}
-                                 showTimestamp={shouldShowTimestamp}
-                                 timestamp={timestamp}
-                                 type={entry.type} />
-                  );
-              }, this)
-            }
-          </div>
-        </div>
-      );
-    },
-
-    /**
-     * Decide to show timestamp or not on a message.
-     * If the time difference between two consecutive messages is bigger than
-     * one minute or if message types are different.
-     *
-     * @param {number} idx       Index of message in the messageList.
-     * @param {boolean} timeDiff If difference between consecutive messages is
-     *                           bigger than one minute.
-     */
-    _shouldShowTimestamp: function(idx, timeDiff) {
-      if (!idx) {
-        return true;
-      }
-
-      /* If consecutive messages are from different senders */
-      if (this.props.messageList[idx].type !==
-          this.props.messageList[idx - 1].type) {
-        return true;
-      }
-
-      return timeDiff;
-    },
-
-    /**
-     * Determines if difference between the two timestamp arguments
-     * is bigger that 60 (1 minute)
-     *
-     * Timestamps are using ISO8601 format.
-     *
-     * @param {string} currTime Timestamp of message yet to be rendered.
-     * @param {string} prevTime Last timestamp printed in the chat view.
-     */
-    _isOneMinDelta: function(currTime, prevTime) {
-      var date1 = new Date(currTime);
-      var date2 = new Date(prevTime);
-      var delta = date1 - date2;
-
-      if (delta / 1000 >= this.constructor.ONE_MINUTE) {
-        return true;
-      }
-
-      return false;
-    }
-  });
-
-  /**
-   * Displays a text chat entry input box for sending messages.
-   *
-   * @property {loop.Dispatcher} dispatcher
-   * @property {Boolean} showPlaceholder    Set to true to show the placeholder message.
-   * @property {Boolean} textChatEnabled    Set to true to enable the box. If false, the
-   *                                        text chat box won't be displayed.
-   */
-  var TextChatInputView = React.createClass({
-    mixins: [
-      React.addons.LinkedStateMixin,
-      React.addons.PureRenderMixin
-    ],
-
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      showPlaceholder: React.PropTypes.bool.isRequired,
-      textChatEnabled: React.PropTypes.bool.isRequired
-    },
-
-    getInitialState: function() {
-      return {
-        messageDetail: ""
-      };
-    },
-
-    /**
-     * Handles a key being pressed - looking for the return key for submitting
-     * the form.
-     *
-     * @param {Object} event The DOM event.
-     */
-    handleKeyDown: function(event) {
-      if (event.which === 13) {
-        this.handleFormSubmit(event);
-      }
-    },
-
-    /**
-     * Handles submitting of the form - dispatches a send text chat message.
-     *
-     * @param {Object} event The DOM event.
-     */
-    handleFormSubmit: function(event) {
-      event.preventDefault();
-
-      // Don't send empty messages.
-      if (!this.state.messageDetail) {
-        return;
-      }
-
-      this.props.dispatcher.dispatch(new sharedActions.SendTextChatMessage({
-        contentType: CHAT_CONTENT_TYPES.TEXT,
-        message: this.state.messageDetail,
-        sentTimestamp: (new Date()).toISOString()
-      }));
-
-      // Reset the form to empty, ready for the next message.
-      this.setState({ messageDetail: "" });
-    },
-
-    render: function() {
-      if (!this.props.textChatEnabled) {
-        return null;
-      }
-
-      return (
-        <div className="text-chat-box">
-          <form onSubmit={this.handleFormSubmit}>
-            <input
-              onKeyDown={this.handleKeyDown}
-              placeholder={this.props.showPlaceholder ? mozL10n.get("chat_textbox_placeholder") : ""}
-              type="text"
-              valueLink={this.linkState("messageDetail")} />
-          </form>
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Displays the text chat view. This includes the text chat messages as well
-   * as a field for entering new messages.
-   *
-   * @property {loop.Dispatcher} dispatcher
-   * @property {Boolean}         showInitialContext Set to true to show the room name
-   *                                          and initial context tile for linker clicker's special list items
-   */
-  var TextChatView = React.createClass({
-    mixins: [
-      React.addons.LinkedStateMixin,
-      loop.store.StoreMixin("textChatStore")
-    ],
-
-    propTypes: {
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      showInitialContext: React.PropTypes.bool.isRequired,
-      useDesktopPaths: React.PropTypes.bool.isRequired
-    },
-
-    getInitialState: function() {
-      return this.getStoreState();
-    },
-
-    render: function() {
-      var messageList = this.state.messageList;
-
-      // Filter out items not displayed when showing initial context.
-      // We do this here so that we can set the classes correctly on the view.
-      if (!this.props.showInitialContext) {
-        messageList = messageList.filter(function(item) {
-          return item.type !== CHAT_MESSAGE_TYPES.SPECIAL ||
-            (item.contentType !== CHAT_CONTENT_TYPES.ROOM_NAME &&
-             item.contentType !== CHAT_CONTENT_TYPES.CONTEXT);
-        });
-      }
-
-      // Only show the placeholder if we've sent messages.
-      var hasSentMessages = messageList.some(function(item) {
-        return item.type === CHAT_MESSAGE_TYPES.SENT;
-      });
-
-      var textChatViewClasses = classNames({
-        "text-chat-view": true,
-        "text-chat-entries-empty": !messageList.length,
-        "text-chat-disabled": !this.state.textChatEnabled
-      });
-
-      return (
-        <div className={textChatViewClasses}>
-          <TextChatEntriesView
-            dispatcher={this.props.dispatcher}
-            messageList={messageList}
-            showInitialContext={this.props.showInitialContext}
-            useDesktopPaths={this.props.useDesktopPaths} />
-          <TextChatInputView
-            dispatcher={this.props.dispatcher}
-            showPlaceholder={!hasSentMessages}
-            textChatEnabled={this.state.textChatEnabled} />
-        </div>
-      );
-    }
-  });
-
-  return {
-    TextChatEntriesView: TextChatEntriesView,
-    TextChatEntry: TextChatEntry,
-    TextChatView: TextChatView
-  };
-})(navigator.mozL10n || document.mozL10n);
deleted file mode 100644
--- a/browser/extensions/loop/content/shared/js/views.jsx
+++ /dev/null
@@ -1,1030 +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/. */
-
-var loop = loop || {};
-loop.shared = loop.shared || {};
-loop.shared.views = (function(_, mozL10n) {
-  "use strict";
-
-  var sharedActions = loop.shared.actions;
-  var sharedModels = loop.shared.models;
-  var sharedMixins = loop.shared.mixins;
-
-  /**
-   * Hang-up control button.
-   *
-   * Required props:
-   * - {Function} action  Function to be executed on click.
-   * - {String}   title   Tooltip functionality.
-   */
-  var HangUpControlButton = React.createClass({
-    mixins: [
-      React.addons.PureRenderMixin
-    ],
-
-    propTypes: {
-      action: React.PropTypes.func.isRequired,
-      title: React.PropTypes.string
-    },
-
-    handleClick: function() {
-      this.props.action();
-    },
-
-    render: function() {
-      return (
-          <button className="btn btn-hangup"
-                  onClick={this.handleClick}
-                  title={this.props.title}/>
-      );
-    }
-  });
-
-  /**
-   * Media control button.
-   *
-   * Required props:
-   * - {String}   scope   Media scope, can be "local" or "remote".
-   * - {String}   type    Media type, can be "audio" or "video".
-   * - {Function} action  Function to be executed on click.
-   * - {Enabled}  enabled Stream activation status (default: true).
-   */
-  var MediaControlButton = React.createClass({
-    propTypes: {
-      action: React.PropTypes.func.isRequired,
-      enabled: React.PropTypes.bool.isRequired,
-      scope: React.PropTypes.string.isRequired,
-      title: React.PropTypes.string,
-      type: React.PropTypes.string.isRequired,
-      visible: React.PropTypes.bool.isRequired
-    },
-
-    getDefaultProps: function() {
-      return { enabled: true, visible: true };
-    },
-
-    handleClick: function() {
-      this.props.action();
-    },
-
-    _getClasses: function() {
-      var cx = classNames;
-      // classes
-      var classesObj = {
-        "btn": true,
-        "media-control": true,
-        "transparent-button": true,
-        "local-media": this.props.scope === "local",
-        "muted": !this.props.enabled,
-        "hide": !this.props.visible
-      };
-      classesObj["btn-mute-" + this.props.type] = true;
-      return cx(classesObj);
-    },
-
-    _getTitle: function(enabled) {
-      if (this.props.title) {
-        return this.props.title;
-      }
-
-      var prefix = this.props.enabled ? "mute" : "unmute";
-      var suffix = (this.props.type === "video") ? "button_title2" : "button_title";
-      var msgId = [prefix, this.props.scope, this.props.type, suffix].join("_");
-      return mozL10n.get(msgId);
-    },
-
-    render: function() {
-      return (
-        <button className={this._getClasses()}
-                onClick={this.handleClick}
-                title={this._getTitle()}></button>
-      );
-    }
-  });
-
-  /**
-   * Settings control button.
-   */
-  var SettingsControlButton = React.createClass({
-    propTypes: {
-      // Set to true if the menu should be below the button rather than above.
-      menuBelow: React.PropTypes.bool,
-      menuItems: React.PropTypes.array
-    },
-
-    mixins: [
-      sharedMixins.DropdownMenuMixin(),
-      React.addons.PureRenderMixin
-    ],
-
-    getDefaultProps: function() {
-      return {
-        menuBelow: false
-      };
-    },
-
-    /**
-     * Reposition Menu if cropped
-     *
-     * Added to reposition the menu if it is cropped on the left side because of
-     * a long text string. This function measures how much the menu is cropped
-     * on the left or right and adjusts the coordinates so the menu isn't cropped.
-     * Also, sets the left style to auto, to prevent complexity in calculations
-     *
-     * The dropdownmenu mixin needs to be revamped, along with all components
-     * using dropdown menus. Components should be utilizing a global function
-     * for menu positions and it should be consistent throughout.
-     *
-     */
-    _repositionMenu: function() {
-      if (this.refs.menu && this.state.showMenu) {
-        var menuNode = this.refs.menu && this.refs.menu.getDOMNode();
-
-        if (menuNode) {
-          // Amount of pixels that the dropdown needs to stay away from the edges
-          // of the page body. Copied from the mixin.
-          var boundOffset = 4;
-          var menuNodeRect = menuNode.getBoundingClientRect();
-          var menuComputedStyle = window.getComputedStyle(menuNode);
-          var documentBody = this.getDOMNode().ownerDocument.body;
-          var bodyRect = documentBody.getBoundingClientRect();
-          var menuLeft = parseFloat(menuNodeRect.left);
-          var menuRight = parseFloat(menuNodeRect.right);
-          var bodyRight = parseFloat(bodyRect.right);
-
-          menuNode.style.left = "auto";
-
-          // If menu is too close or cropped on left, move right
-          if (menuLeft < -boundOffset) {
-            menuNode.style.right =
-              (parseFloat(menuComputedStyle.right) + menuLeft - boundOffset) + "px";
-          }
-          // If menu is too close or cropped on right, move left
-          if (menuRight > bodyRight - boundOffset) {
-            menuNode.style.right =
-              (parseFloat(menuComputedStyle.right) + (menuRight - bodyRight) + boundOffset) + "px";
-          }
-        }
-      }
-    },
-
-    /**
-     * Return the function that Show or hide the edit context edition form
-     */
-    getHandleToggleEdit: function(editItem) {
-      return function _handleToglleEdit(event) {
-          event.preventDefault();
-          if (editItem.onClick) {
-            editItem.onClick(!editItem.enabled);
-          }
-        };
-    },
-
-    /**
-     * Load on the browser the help (support) url from prefs
-     */
-    handleHelpEntry: function(event) {
-      event.preventDefault();
-      loop.request("GetLoopPref", "support_url").then(function(helloSupportUrl) {
-        loop.request("OpenURL", helloSupportUrl);
-      });
-    },
-
-    /**
-     * Recover the needed info for generating an specific menu Item
-     */
-    getItemInfo: function(menuItem) {
-      var cx = classNames;
-      switch (menuItem.id) {
-        case "help":
-          return {
-            cssClasses: "dropdown-menu-item",
-            handler: this.handleHelpEntry,
-            label: mozL10n.get("help_label")
-          };
-        case "edit":
-          return {
-            cssClasses: cx({
-              "dropdown-menu-item": true,
-              "entry-settings-edit": true,
-              "hide": !menuItem.visible
-            }),
-            handler: this.getHandleToggleEdit(menuItem),
-            label: mozL10n.get(menuItem.enabled ?
-              "conversation_settings_menu_edit_context" :
-              "conversation_settings_menu_hide_context"),
-            scope: "local",
-            type: "edit"
-          };
-        default:
-          console.error("Invalid menu item", menuItem);
-          return null;
-       }
-    },
-
-    /**
-     * Generate a menu item after recover its info
-     */
-    generateMenuItem: function(menuItem) {
-      var itemInfo = this.getItemInfo(menuItem);
-      if (!itemInfo) {
-        return null;
-      }
-      return (
-        <li className={itemInfo.cssClasses}
-            key={menuItem.id}
-            onClick={itemInfo.handler}
-            scope={itemInfo.scope || ""}
-            type={itemInfo.type || ""} >
-          {itemInfo.label}
-        </li>
-        );
-    },
-
-    render: function() {
-      if (!this.props.menuItems || !this.props.menuItems.length) {
-        return null;
-      }
-      var menuItemRows = this.props.menuItems.map(this.generateMenuItem)
-        .filter(function(item) { return item; });
-
-      if (!menuItemRows || !menuItemRows.length) {
-        return null;
-      }
-
-      var cx = classNames;
-      var settingsDropdownMenuClasses = cx({
-        "settings-menu": true,
-        "dropdown-menu": true,
-        "menu-below": this.props.menuBelow,
-        "hide": !this.state.showMenu
-      });
-      return (
-        <div className="settings-control">
-          <button className="btn btn-settings transparent-button"
-             onClick={this.toggleDropdownMenu}
-             ref="anchor"
-             title={mozL10n.get("settings_menu_button_tooltip")} />
-          <ul className={settingsDropdownMenuClasses} ref="menu">
-            {menuItemRows}
-          </ul>
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Conversation controls.
-   */
-  var ConversationToolbar = React.createClass({
-    getDefaultProps: function() {
-      return {
-        video: { enabled: true, visible: true },
-        audio: { enabled: true, visible: true },
-        settingsMenuItems: null,
-        showHangup: true
-      };
-    },
-
-    getInitialState: function() {
-      return {
-        idle: false
-      };
-    },
-
-    propTypes: {
-      audio: React.PropTypes.object.isRequired,
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher).isRequired,
-      hangup: React.PropTypes.func.isRequired,
-      publishStream: React.PropTypes.func.isRequired,
-      settingsMenuItems: React.PropTypes.array,
-      show: React.PropTypes.bool.isRequired,
-      showHangup: React.PropTypes.bool,
-      video: React.PropTypes.object.isRequired
-    },
-
-    handleClickHangup: function() {
-      this.props.hangup();
-    },
-
-    handleToggleVideo: function() {
-      this.props.publishStream("video", !this.props.video.enabled);
-    },
-
-    handleToggleAudio: function() {
-      this.props.publishStream("audio", !this.props.audio.enabled);
-    },
-
-    componentDidMount: function() {
-      this.userActivity = false;
-      this.startIdleCountDown();
-      document.body.addEventListener("mousemove", this._onBodyMouseMove);
-    },
-
-    componentWillUnmount: function() {
-      clearTimeout(this.inactivityTimeout);
-      clearInterval(this.inactivityPollInterval);
-      document.body.removeEventListener("mousemove", this._onBodyMouseMove);
-    },
-
-    /**
-     * If the conversation toolbar is idle, update its state and initialize the countdown
-     * to return of the idle state. If the toolbar is active, only it's updated the userActivity flag.
-     */
-    _onBodyMouseMove: function() {
-      if (this.state.idle) {
-        this.setState({ idle: false });
-        this.startIdleCountDown();
-      } else {
-        this.userActivity = true;
-      }
-    },
-
-    /**
-     * Instead of resetting the timeout for every mousemove (this event is called to many times,
-     * when the mouse is moving, we check the flat userActivity every 4 seconds. If the flag is activated,
-     * the user is still active, and we can restart the countdown for the idle state
-     */
-    checkUserActivity: function() {
-      this.inactivityPollInterval = setInterval(function() {
-        if (this.userActivity) {
-          this.userActivity = false;
-          this.restartIdleCountDown();
-        }
-      }.bind(this), 4000);
-    },
-
-    /**
-     * Stop the execution of the current inactivity countdown and it starts a new one.
-     */
-    restartIdleCountDown: function() {
-      clearTimeout(this.inactivityTimeout);
-      this.startIdleCountDown();
-    },
-
-    /**
-     * Launchs the process to check the user activity and the inactivity countdown to change
-     * the toolbar to idle.
-     * When the toolbar changes to idle, we remove the procces to check the user activity,
-     * because the toolbar is going to be updated directly when the user moves the mouse.
-     */
-    startIdleCountDown: function() {
-      this.checkUserActivity();
-      this.inactivityTimeout = setTimeout(function() {
-        this.setState({ idle: true });
-        clearInterval(this.inactivityPollInterval);
-      }.bind(this), 6000);
-    },
-
-    render: function() {
-      if (!this.props.show) {
-        return null;
-      }
-
-      var cx = classNames;
-      var conversationToolbarCssClasses = cx({
-        "conversation-toolbar": true,
-        "idle": this.state.idle
-      });
-      var showButtons = this.props.video.visible || this.props.audio.visible;
-      var mediaButtonGroupCssClasses = cx({
-        "conversation-toolbar-media-btn-group-box": true,
-        "hide": !showButtons
-      });
-      return (
-        <ul className={conversationToolbarCssClasses}>
-        {
-          this.props.showHangup && showButtons ?
-          <li className="conversation-toolbar-btn-box btn-hangup-entry">
-            <HangUpControlButton action={this.handleClickHangup}
-                                 title={mozL10n.get("rooms_leave_button_label")}/>
-          </li> : null
-        }
-
-          <li className="conversation-toolbar-btn-box">
-            <div className={mediaButtonGroupCssClasses}>
-                <MediaControlButton action={this.handleToggleVideo}
-                                    enabled={this.props.video.enabled}
-                                    scope="local" type="video"
-                                    visible={this.props.video.visible}/>
-                <MediaControlButton action={this.handleToggleAudio}
-                                    enabled={this.props.audio.enabled}
-                                    scope="local" type="audio"
-                                    visible={this.props.audio.visible}/>
-            </div>
-          </li>
-          <li className="conversation-toolbar-btn-box btn-edit-entry">
-            <SettingsControlButton menuItems={this.props.settingsMenuItems} />
-          </li>
-        </ul>
-      );
-    }
-  });
-
-  /**
-   * Notification view.
-   */
-  var NotificationView = React.createClass({
-    mixins: [Backbone.Events],
-
-    propTypes: {
-      notification: React.PropTypes.object.isRequired
-    },
-
-    render: function() {
-      var notification = this.props.notification;
-      return (
-        <div className="notificationContainer">
-          <div className={"alert alert-" + notification.get("level")}>
-            <span className="message">{notification.get("message")}</span>
-          </div>
-          <div className={"detailsBar details-" + notification.get("level")}
-               hidden={!notification.get("details")}>
-            <button className="detailsButton btn-info"
-                    hidden={!notification.get("detailsButtonLabel") || !notification.get("detailsButtonCallback")}
-                    onClick={notification.get("detailsButtonCallback")}>
-              {notification.get("detailsButtonLabel")}
-            </button>
-            <span className="details">{notification.get("details")}</span>
-          </div>
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Notification list view.
-   */
-  var NotificationListView = React.createClass({
-    mixins: [Backbone.Events, sharedMixins.DocumentVisibilityMixin],
-
-    propTypes: {
-      clearOnDocumentHidden: React.PropTypes.bool,
-      notifications: React.PropTypes.object.isRequired
-    },
-
-    getDefaultProps: function() {
-      return { clearOnDocumentHidden: false };
-    },
-
-    componentDidMount: function() {
-      this.listenTo(this.props.notifications, "reset add remove", function() {
-        this.forceUpdate();
-      });
-    },
-
-    componentWillUnmount: function() {
-      this.stopListening(this.props.notifications);
-    },
-
-    /**
-     * Provided by DocumentVisibilityMixin. Clears notifications stack when the
-     * current document is hidden if the clearOnDocumentHidden prop is set to
-     * true and the collection isn't empty.
-     */
-    onDocumentHidden: function() {
-      if (this.props.clearOnDocumentHidden &&
-          this.props.notifications.length > 0) {
-        // Note: The `silent` option prevents the `reset` event to be triggered
-        // here, preventing the UI to "jump" a little because of the event
-        // callback being processed in another tick (I think).
-        this.props.notifications.reset([], { silent: true });
-        this.forceUpdate();
-      }
-    },
-
-    render: function() {
-      return (
-        <div className="messages">
-          {this.props.notifications.map(function(notification, key) {
-            return <NotificationView key={key} notification={notification} />;
-          })}
-        </div>
-      );
-    }
-  });
-
-  var Button = React.createClass({
-    propTypes: {
-      additionalClass: React.PropTypes.string,
-      caption: React.PropTypes.string.isRequired,
-      children: React.PropTypes.element,
-      disabled: React.PropTypes.bool,
-      htmlId: React.PropTypes.string,
-      onClick: React.PropTypes.func.isRequired
-    },
-
-    getDefaultProps: function() {
-      return {
-        disabled: false,
-        additionalClass: "",
-        htmlId: ""
-      };
-    },
-
-    render: function() {
-      var cx = classNames;
-      var classObject = { button: true, disabled: this.props.disabled };
-      if (this.props.additionalClass) {
-        classObject[this.props.additionalClass] = true;
-      }
-      return (
-        <button className={cx(classObject)}
-                disabled={this.props.disabled}
-                id={this.props.htmlId}
-                onClick={this.props.onClick}>
-          <span className="button-caption">{this.props.caption}</span>
-          {this.props.children}
-        </button>
-      );
-    }
-  });
-
-  var ButtonGroup = React.createClass({
-    propTypes: {
-      additionalClass: React.PropTypes.string,
-      children: React.PropTypes.oneOfType([
-        React.PropTypes.element,
-        React.PropTypes.arrayOf(React.PropTypes.element)
-      ])
-    },
-
-    getDefaultProps: function() {
-      return {
-        additionalClass: ""
-      };
-    },
-
-    render: function() {
-      var cx = classNames;
-      var classObject = { "button-group": true };
-      if (this.props.additionalClass) {
-        classObject[this.props.additionalClass] = true;
-      }
-      return (
-        <div className={cx(classObject)}>
-          {this.props.children}
-        </div>
-      );
-    }
-  });
-
-  var Checkbox = React.createClass({
-    propTypes: {
-      additionalClass: React.PropTypes.string,
-      checked: React.PropTypes.bool,
-      disabled: React.PropTypes.bool,
-      label: React.PropTypes.string,
-      onChange: React.PropTypes.func.isRequired,
-      // If true, this will cause the label to be cut off at the end of the
-      // first line with an ellipsis, and a tooltip supplied.
-      useEllipsis: React.PropTypes.bool,
-      // If `value` is not supplied, the consumer should rely on the boolean
-      // `checked` state changes.
-      value: React.PropTypes.string
-    },
-
-    getDefaultProps: function() {
-      return {
-        additionalClass: "",
-        checked: false,
-        disabled: false,
-        label: null,
-        useEllipsis: false,
-        value: ""
-      };
-    },
-
-    componentWillReceiveProps: function(nextProps) {
-      // Only change the state if the prop has changed, and if it is also
-      // different from the state.
-      if (this.props.checked !== nextProps.checked &&
-          this.state.checked !== nextProps.checked) {
-        this.setState({ checked: nextProps.checked });
-      }
-    },
-
-    getInitialState: function() {
-      return {
-        checked: this.props.checked,
-        value: this.props.checked ? this.props.value : ""
-      };
-    },
-
-    _handleClick: function(event) {
-      event.preventDefault();
-
-      var newState = {
-        checked: !this.state.checked,
-        value: this.state.checked ? "" : this.props.value
-      };
-      this.setState(newState);
-      this.props.onChange(newState);
-    },
-
-    render: function() {
-      var cx = classNames;
-      var wrapperClasses = {
-        "checkbox-wrapper": true,
-        disabled: this.props.disabled
-      };
-      var checkClasses = {
-        checkbox: true,
-        checked: this.state.checked,
-        disabled: this.props.disabled
-      };
-      var labelClasses = {
-        "checkbox-label": true,
-        "ellipsis": this.props.useEllipsis
-      };
-
-      if (this.props.additionalClass) {
-        wrapperClasses[this.props.additionalClass] = true;
-      }
-      return (
-        <div className={cx(wrapperClasses)}
-             disabled={this.props.disabled}
-             onClick={this._handleClick}>
-          <div className={cx(checkClasses)} />
-          {
-            this.props.label ?
-              <div className={cx(labelClasses)}
-                   title={this.props.useEllipsis ? this.props.label : ""}>
-                {this.props.label}
-              </div> : null
-          }
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Renders an avatar element for display when video is muted.
-   */
-  var AvatarView = React.createClass({
-    mixins: [React.addons.PureRenderMixin],
-
-    render: function() {
-        return <div className="avatar"/>;
-    }
-  });
-
-  /**
-   * Renders a loading spinner for when video content is not yet available.
-   */
-  var LoadingView = React.createClass({
-    mixins: [React.addons.PureRenderMixin],
-
-    render: function() {
-        return (
-          <div className="loading-background">
-            <div className="loading-stream"/>
-          </div>
-        );
-    }
-  });
-
-  /**
-   * Renders a url that's part of context on the display.
-   *
-   * @property {Boolean} allowClick         Set to true to allow the url to be clicked. If this
-   *                                        is specified, then 'dispatcher' is also required.
-   * @property {String}  description        The description for the context url.
-   * @property {loop.Dispatcher} dispatcher
-   * @property {String}  thumbnail          The thumbnail url (expected to be a data url) to
-   *                                        display. If not specified, a fallback url will be
-   *                                        shown.
-   * @property {String}  url                The url to be displayed. If not present or invalid,
-   *                                        then this view won't be displayed.
-   * @property {Boolean} useDesktopPaths    Whether or not to use the desktop paths for for the
-   *                                        fallback url.
-   */
-  var ContextUrlView = React.createClass({
-    mixins: [React.addons.PureRenderMixin],
-
-    propTypes: {
-      allowClick: React.PropTypes.bool.isRequired,
-      description: React.PropTypes.string.isRequired,
-      dispatcher: React.PropTypes.instanceOf(loop.Dispatcher),
-      thumbnail: React.PropTypes.string,
-      url: React.PropTypes.string,
-      useDesktopPaths: React.PropTypes.bool.isRequired
-    },
-
-    /**
-     * Dispatches an action to record when the link is clicked.
-     */
-    handleLinkClick: function() {
-      if (!this.props.allowClick) {
-        return;
-      }
-
-      this.props.dispatcher.dispatch(new sharedActions.RecordClick({
-        linkInfo: "Shared URL"
-      }));
-    },
-
-    render: function() {
-      var hostname;
-
-      try {
-        hostname = new URL(this.props.url).hostname;
-      } catch (ex) {
-        return null;
-      }
-
-      var thumbnail = this.props.thumbnail;
-
-      if (!thumbnail) {
-        thumbnail = this.props.useDesktopPaths ?
-          "shared/img/icons-16x16.svg#globe" :
-          "shared/img/icons-16x16.svg#globe";
-      }
-
-      var wrapperClasses = classNames({
-        "context-wrapper": true,
-        "clicks-allowed": this.props.allowClick
-      });
-
-      return (
-        <div className="context-content">
-          <a className={wrapperClasses}
-             href={this.props.allowClick ? this.props.url : null}
-             onClick={this.handleLinkClick}
-             rel="noreferrer"
-             target="_blank">
-            <img className="context-preview" src={thumbnail} />
-            <span className="context-info">
-              {this.props.description}
-              <span className="context-url">
-                {hostname}
-              </span>
-            </span>
-          </a>
-        </div>
-      );
-    }
-  });
-
-  /**
-   * Renders a media element for display. This also handles displaying an avatar
-   * instead of the video, and attaching a video stream to the video element.
-   */
-  var MediaView = React.createClass({
-    // srcMediaElement should be ok for a shallow comparison, so we are safe
-    // to use the pure render mixin here.
-    mixins: [React.addons.PureRenderMixin],
-
-    propTypes: {
-      displayAvatar: React.PropTypes.bool.isRequired,
-      isLoading: React.PropTypes.bool.isRequired,
-      mediaType: React.PropTypes.string.isRequired,
-      posterUrl: React.PropTypes.string,
-      // Expecting "local" or "remote".
-      srcMediaElement: React.PropTypes.object
-    },
-
-    componentDidMount: function() {
-      if (!this.props.displayAvatar) {
-        this.attachVideo(this.props.srcMediaElement);
-      }
-    },
-
-    componentDidUpdate: function() {
-      if (!this.props.displayAvatar) {
-        this.attachVideo(this.props.srcMediaElement);
-      }
-    },
-
-    /**
-     * Attaches a video stream from a donor video element to this component's
-     * video element if the component is displaying one.
-     *
-     * @param {Object} srcMediaElement The src video object to clone the stream
-     *                                from.
-     *
-     * XXX need to have a corresponding detachVideo or change this to syncVideo
-     * to protect from leaks (bug 1171978)
-     */
-    attachVideo: function(srcMediaElement) {
-      if (!srcMediaElement) {
-        // Not got anything to display.
-        return;
-      }
-
-      var videoElement = this.getDOMNode();
-
-      if (videoElement.tagName.toLowerCase() !== "video") {
-        // Must be displaying the avatar view, so don't try and attach video.
-        return;
-      }
-
-      // Set the src of our video element
-      var attrName = "";
-      if ("srcObject" in videoElement) {
-        // srcObject is according to the standard.
-        attrName = "srcObject";
-      } else if ("mozSrcObject" in videoElement) {
-        // mozSrcObject is for Firefox
-        attrName = "mozSrcObject";
-      } else if ("src" in videoElement) {
-        // src is for Chrome.
-        attrName = "src";
-      } else {
-        console.error("Error attaching stream to element - no supported" +
-                      "attribute found");
-        return;
-      }
-
-      // If the object hasn't changed it, then don't reattach it.
-      if (videoElement[attrName] !== srcMediaElement[attrName]) {
-        videoElement[attrName] = srcMediaElement[attrName];
-      }
-      videoElement.play();
-    },
-
-    render: function() {
-      if (this.props.isLoading) {
-        return <LoadingView />;
-      }
-
-      if (this.props.displayAvatar) {
-        return <AvatarView />;
-      }
-
-      if (!this.props.srcMediaElement && !this.props.posterUrl) {
-        return <div className="no-video"/>;
-      }
-
-      var optionalPoster = {};
-      if (this.props.posterUrl) {
-        optionalPoster.poster = this.props.posterUrl;
-      }
-
-      // For now, always mute media. For local media, we should be muted anyway,
-      // as we don't want to hear ourselves speaking.
-