Merge m-c to oak DONTBUILD
authorRobert Strong <robert.bugzilla@gmail.com>
Thu, 07 May 2015 23:47:27 -0700
changeset 491427 725533bd8c2387edadc69a681ee0418c8b08042a
parent 491426 5b078c9ba78ad7df62ef081bac9f7ab9d6d69019 (current diff)
parent 261930 356e735fa9082c54528cd8a77c2c7b413b7cd5cc (diff)
child 491428 de62e21b87bbd36fc8f3e7e17a9ab0f41843895e
push id47343
push userbmo:dothayer@mozilla.com
push dateWed, 01 Mar 2017 22:58:58 +0000
milestone40.0a1
Merge m-c to oak DONTBUILD
CLOBBER
b2g/branding/official/android-resources.mn
b2g/branding/unofficial/android-resources.mn
b2g/installer/package-manifest.in
browser/app/profile/firefox.js
browser/base/content/test/general/browser_fxa_profile_channel.html
browser/base/content/test/general/browser_fxa_profile_channel.js
browser/branding/aurora/Makefile.in
browser/branding/nightly/Makefile.in
browser/branding/official/Makefile.in
browser/branding/unofficial/Makefile.in
browser/components/loop/CardDavImporter.jsm
browser/components/loop/GoogleImporter.jsm
browser/components/loop/LoopCalls.jsm
browser/components/loop/LoopContacts.jsm
browser/components/loop/LoopRooms.jsm
browser/components/loop/LoopStorage.jsm
browser/components/loop/MozLoopAPI.jsm
browser/components/loop/MozLoopPushHandler.jsm
browser/components/loop/MozLoopService.jsm
browser/components/loop/MozLoopWorker.js
browser/components/loop/content/shared/.eslintrc
browser/components/loop/content/shared/libs/jquery-2.1.0.js
browser/components/loop/standalone/.eslintrc
browser/components/sessionstore/test/browser_telemetry.js
browser/devtools/commandline/commands-index.js
browser/devtools/debugger/debugger-panes.js
browser/devtools/debugger/debugger-toolbar.js
browser/devtools/performance/modules/performance-graphs.js
browser/devtools/performance/test/browser_perf-jump-to-debugger-01.js
browser/devtools/performance/test/browser_perf-jump-to-debugger-02.js
browser/devtools/performance/test/browser_timeline_blueprint.js
browser/devtools/performance/test/browser_timeline_filters.js
browser/devtools/shared/test/browser_inplace-editor.js
browser/devtools/timeline/test/browser.ini
browser/devtools/timeline/test/browser_timeline_aaa_run_first_leaktest.js
browser/devtools/timeline/test/browser_timeline_overview-initial-selection-01.js
browser/devtools/timeline/test/browser_timeline_overview-initial-selection-02.js
browser/devtools/timeline/test/browser_timeline_overview-theme.js
browser/devtools/timeline/test/browser_timeline_overview-update.js
browser/devtools/timeline/test/browser_timeline_panels.js
browser/devtools/timeline/test/browser_timeline_recording-without-memory.js
browser/devtools/timeline/test/browser_timeline_recording.js
browser/devtools/timeline/test/browser_timeline_waterfall-background.js
browser/devtools/timeline/test/browser_timeline_waterfall-generic.js
browser/devtools/timeline/test/browser_timeline_waterfall-sidebar.js
browser/devtools/timeline/test/browser_timeline_waterfall-styles.js
browser/devtools/timeline/test/doc_simple-test.html
browser/devtools/timeline/test/head.js
browser/devtools/webide/themes/project-listing.css
browser/extensions/Makefile.in
browser/installer/package-manifest.in
browser/locales/en-US/chrome/browser/devtools/gcli.properties
browser/locales/en-US/chrome/browser/devtools/gclicommands.properties
build/automationutils.py
configure.in
dom/animation/Animation.cpp
dom/animation/Animation.h
dom/animation/AnimationEffectReadonly.cpp
dom/animation/AnimationEffectReadonly.h
dom/bluetooth/BluetoothCommon.h
dom/bluetooth/BluetoothHfpManagerBase.h
dom/bluetooth/BluetoothHidManager.cpp
dom/bluetooth/BluetoothHidManager.h
dom/bluetooth/BluetoothInterface.cpp
dom/bluetooth/BluetoothInterface.h
dom/bluetooth/BluetoothInterfaceHelpers.cpp
dom/bluetooth/BluetoothInterfaceHelpers.h
dom/bluetooth/BluetoothProfileManagerBase.h
dom/bluetooth/BluetoothRilListener.cpp
dom/bluetooth/BluetoothRilListener.h
dom/bluetooth/BluetoothSocketObserver.h
dom/bluetooth/BluetoothUtils.cpp
dom/bluetooth/BluetoothUtils.h
dom/bluetooth/BluetoothUuid.cpp
dom/bluetooth/BluetoothUuid.h
dom/bluetooth/ObexBase.cpp
dom/bluetooth/ObexBase.h
dom/browser-element/mochitest/file_NestedFramesOuter_CopyPaste.html
dom/cache/FetchPut.cpp
dom/cache/FetchPut.h
dom/events/BeforeAfterKeyboardEvent.h
dom/interfaces/css/nsIDOMCSSCharsetRule.idl
dom/interfaces/html/nsIDOMHTMLBRElement.idl
dom/interfaces/html/nsIDOMHTMLDivElement.idl
dom/interfaces/html/nsIDOMHTMLHeadingElement.idl
dom/interfaces/html/nsIDOMHTMLTableCaptionElem.idl
dom/interfaces/html/nsIDOMHTMLTableElement.idl
dom/interfaces/html/nsIDOMHTMLTitleElement.idl
dom/media/omx/AudioSink.h
dom/mobileconnection/gonk/MobileConnectionService.js
dom/tests/mochitest/chrome/MozEnteredDomFullscreen_chrome.xul
dom/tests/mochitest/chrome/test_MozEnteredDomFullscreen_event.xul
dom/tests/mochitest/general/file_MozEnteredDomFullscreen.html
dom/webidl/Animation.webidl
dom/webidl/AnimationEffectReadonly.webidl
extensions/pref/autoconfig/src/beos/platform.js
extensions/pref/autoconfig/src/mac/platform.js
extensions/pref/autoconfig/src/unix/platform.js
extensions/pref/autoconfig/src/win/platform.js
extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/chromium_en_US.dic_delta
extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/dupe-dictionary.pl
extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/edit-dictionary
extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/hunspell-en_US-20081205.dic
extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/merge-dictionaries
extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-chromium.diff
extensions/spellcheck/locales/en-US/hunspell/dictionary-sources/upstream-hunspell.diff
image/public/ImageLogging.h
image/public/imgICache.idl
image/public/imgIContainer.idl
image/public/imgIContainerDebug.idl
image/public/imgIEncoder.idl
image/public/imgILoader.idl
image/public/imgINotificationObserver.idl
image/public/imgIOnloadBlocker.idl
image/public/imgIRequest.idl
image/public/imgIScriptedNotificationObserver.idl
image/public/imgITools.idl
image/public/moz.build
image/public/nsIIconURI.idl
intl/uconv/tests/unit/test_bug365345.js
intl/unicharutil/tables/htmlEntityVersions.properties
intl/unicharutil/tables/transliterate.properties
intl/unicharutil/tests/moz.build
intl/unicharutil/tests/unit/test_bug_427350_1.js
intl/unicharutil/tests/unit/xpcshell.ini
ipc/glue/GeckoChildProcessHost.cpp
js/src/jit-test/tests/basic/semicolon-less-return.js
js/src/jit-test/tests/basic/string-contains.js
js/src/jsapi-tests/testGCNursery.cpp
js/xpconnect/src/XPCShellImpl.cpp
media/libvpx/bug1137614.patch
mobile/android/base/adjust/adjust.rst
mobile/android/base/tests/AboutHomeTest.java
mobile/android/base/tests/BaseRobocopTest.java
mobile/android/base/tests/BaseTest.java
mobile/android/base/tests/ContentContextMenuTest.java
mobile/android/base/tests/ContentProviderTest.java
mobile/android/base/tests/DatabaseHelper.java
mobile/android/base/tests/Firefox.jpg
mobile/android/base/tests/JavascriptTest.java
mobile/android/base/tests/MotionEventHelper.java
mobile/android/base/tests/MotionEventReplayer.java
mobile/android/base/tests/PixelTest.java
mobile/android/base/tests/README.rst
mobile/android/base/tests/SelectionHandlerTest.java
mobile/android/base/tests/SessionTest.java
mobile/android/base/tests/StringHelper.java
mobile/android/base/tests/UITest.java
mobile/android/base/tests/UITestContext.java
mobile/android/base/tests/assets/README
mobile/android/base/tests/assets/mock-package.zip
mobile/android/base/tests/assets/testcheck2-motionevents
mobile/android/base/tests/components/AboutHomeComponent.java
mobile/android/base/tests/components/AppMenuComponent.java
mobile/android/base/tests/components/BaseComponent.java
mobile/android/base/tests/components/GeckoViewComponent.java
mobile/android/base/tests/components/ToolbarComponent.java
mobile/android/base/tests/devicesearch.xml
mobile/android/base/tests/green.swf
mobile/android/base/tests/helpers/AssertionHelper.java
mobile/android/base/tests/helpers/DeviceHelper.java
mobile/android/base/tests/helpers/FrameworkHelper.java
mobile/android/base/tests/helpers/GeckoHelper.java
mobile/android/base/tests/helpers/HelperInitializer.java
mobile/android/base/tests/helpers/JavascriptBridge.java
mobile/android/base/tests/helpers/JavascriptMessageParser.java
mobile/android/base/tests/helpers/NavigationHelper.java
mobile/android/base/tests/helpers/TextInputHelper.java
mobile/android/base/tests/helpers/WaitHelper.java
mobile/android/base/tests/javascript_redirect.sjs
mobile/android/base/tests/link_discovery.html
mobile/android/base/tests/reader_mode_pages/basic_article.html
mobile/android/base/tests/reader_mode_pages/developer.mozilla.org/en/XULRunner/Build_Instructions.html
mobile/android/base/tests/reader_mode_pages/not_an_article.html
mobile/android/base/tests/robocop.ini
mobile/android/base/tests/robocop_404.sjs
mobile/android/base/tests/robocop_adobe_flash.html
mobile/android/base/tests/robocop_autophone.ini
mobile/android/base/tests/robocop_big_link.html
mobile/android/base/tests/robocop_big_mailto.html
mobile/android/base/tests/robocop_blank_01.html
mobile/android/base/tests/robocop_blank_02.html
mobile/android/base/tests/robocop_blank_03.html
mobile/android/base/tests/robocop_blank_04.html
mobile/android/base/tests/robocop_blank_05.html
mobile/android/base/tests/robocop_boxes.html
mobile/android/base/tests/robocop_dynamic.sjs
mobile/android/base/tests/robocop_geolocation.html
mobile/android/base/tests/robocop_getusermedia.html
mobile/android/base/tests/robocop_getusermedia2.html
mobile/android/base/tests/robocop_head.js
mobile/android/base/tests/robocop_input.html
mobile/android/base/tests/robocop_javascript.html
mobile/android/base/tests/robocop_login_01.html
mobile/android/base/tests/robocop_login_02.html
mobile/android/base/tests/robocop_offline_storage.html
mobile/android/base/tests/robocop_picture_link.html
mobile/android/base/tests/robocop_popup.html
mobile/android/base/tests/robocop_search.html
mobile/android/base/tests/robocop_suggestions.sjs
mobile/android/base/tests/robocop_testharness.js
mobile/android/base/tests/robocop_text_page.html
mobile/android/base/tests/robocop_tiles.sjs
mobile/android/base/tests/roboextender/SelectionUtils.js
mobile/android/base/tests/roboextender/paymentsUI.html
mobile/android/base/tests/roboextender/robocop_home_banner.html
mobile/android/base/tests/roboextender/robocop_prompt_gridinput.html
mobile/android/base/tests/roboextender/testInputSelections.html
mobile/android/base/tests/roboextender/testSelectionHandler.html
mobile/android/base/tests/roboextender/testTextareaSelections.html
mobile/android/base/tests/session_formdata_sample.html
mobile/android/base/tests/simple_redirect.sjs
mobile/android/base/tests/simpleservice.xml
mobile/android/base/tests/testANRReporter.java
mobile/android/base/tests/testAboutHomePageNavigation.java
mobile/android/base/tests/testAboutHomeVisibility.java
mobile/android/base/tests/testAboutPage.java
mobile/android/base/tests/testAboutPasswords.java
mobile/android/base/tests/testAboutPasswords.js
mobile/android/base/tests/testAccounts.java
mobile/android/base/tests/testAccounts.js
mobile/android/base/tests/testAddSearchEngine.java
mobile/android/base/tests/testAddonManager.java
mobile/android/base/tests/testAdobeFlash.java
mobile/android/base/tests/testAndroidLog.java
mobile/android/base/tests/testAndroidLog.js
mobile/android/base/tests/testAppConstants.java
mobile/android/base/tests/testAppConstants.js
mobile/android/base/tests/testAppMenuPathways.java
mobile/android/base/tests/testAwesomebar.java
mobile/android/base/tests/testAxisLocking.java
mobile/android/base/tests/testBackButtonInEditMode.java
mobile/android/base/tests/testBookmark.java
mobile/android/base/tests/testBookmarkFolders.java
mobile/android/base/tests/testBookmarkKeyword.java
mobile/android/base/tests/testBookmarklets.java
mobile/android/base/tests/testBookmarksPanel.java
mobile/android/base/tests/testBrowserDiscovery.java
mobile/android/base/tests/testBrowserDiscovery.js
mobile/android/base/tests/testBrowserProvider.java
mobile/android/base/tests/testBrowserProviderPerf.java
mobile/android/base/tests/testBrowserSearchVisibility.java
mobile/android/base/tests/testCheck.java
mobile/android/base/tests/testCheck2.java
mobile/android/base/tests/testClearPrivateData.java
mobile/android/base/tests/testDBUtils.java
mobile/android/base/tests/testDebuggerServer.java
mobile/android/base/tests/testDebuggerServer.js
mobile/android/base/tests/testDeviceSearchEngine.java
mobile/android/base/tests/testDeviceSearchEngine.js
mobile/android/base/tests/testDistribution.java
mobile/android/base/tests/testDoorHanger.java
mobile/android/base/tests/testEventDispatcher.java
mobile/android/base/tests/testEventDispatcher.js
mobile/android/base/tests/testFilePicker.java
mobile/android/base/tests/testFilePicker.js
mobile/android/base/tests/testFilterOpenTab.java
mobile/android/base/tests/testFindInPage.java
mobile/android/base/tests/testFindInPage.js
mobile/android/base/tests/testFlingCorrectness.java
mobile/android/base/tests/testFormHistory.java
mobile/android/base/tests/testGeckoProfile.java
mobile/android/base/tests/testGeckoRequest.java
mobile/android/base/tests/testGeckoRequest.js
mobile/android/base/tests/testGetUserMedia.java
mobile/android/base/tests/testHistory.java
mobile/android/base/tests/testHistoryService.java
mobile/android/base/tests/testHistoryService.js
mobile/android/base/tests/testHomeBanner.java
mobile/android/base/tests/testHomeListsProvider.java
mobile/android/base/tests/testHomeProvider.java
mobile/android/base/tests/testHomeProvider.js
mobile/android/base/tests/testImportFromAndroid.java
mobile/android/base/tests/testInputConnection.java
mobile/android/base/tests/testInputSelections.java
mobile/android/base/tests/testInputUrlBar.java
mobile/android/base/tests/testJNI.java
mobile/android/base/tests/testJNI.js
mobile/android/base/tests/testJarReader.java
mobile/android/base/tests/testJavascriptBridge.java
mobile/android/base/tests/testJavascriptBridge.js
mobile/android/base/tests/testLinkContextMenu.java
mobile/android/base/tests/testLoad.java
mobile/android/base/tests/testMailToContextMenu.java
mobile/android/base/tests/testMasterPassword.java
mobile/android/base/tests/testMozPay.java
mobile/android/base/tests/testMozPay.js
mobile/android/base/tests/testNativeCrypto.java
mobile/android/base/tests/testNetworkManager.java
mobile/android/base/tests/testNetworkManager.js
mobile/android/base/tests/testNewTab.java
mobile/android/base/tests/testOSLocale.java
mobile/android/base/tests/testOfflinePage.java
mobile/android/base/tests/testOfflinePage.js
mobile/android/base/tests/testOrderedBroadcast.java
mobile/android/base/tests/testOrderedBroadcast.js
mobile/android/base/tests/testPan.java
mobile/android/base/tests/testPanCorrectness.java
mobile/android/base/tests/testPasswordEncrypt.java
mobile/android/base/tests/testPasswordProvider.java
mobile/android/base/tests/testPermissions.java
mobile/android/base/tests/testPictureLinkContextMenu.java
mobile/android/base/tests/testPrefsObserver.java
mobile/android/base/tests/testPrivateBrowsing.java
mobile/android/base/tests/testPromptGridInput.java
mobile/android/base/tests/testReaderMode.java
mobile/android/base/tests/testReaderModeTitle.java
mobile/android/base/tests/testReadingListCache.java
mobile/android/base/tests/testReadingListCache.js
mobile/android/base/tests/testReadingListProvider.java
mobile/android/base/tests/testResourceSubstitutions.java
mobile/android/base/tests/testResourceSubstitutions.js
mobile/android/base/tests/testRestrictedProfiles.java
mobile/android/base/tests/testRestrictedProfiles.js
mobile/android/base/tests/testSearchHistoryProvider.java
mobile/android/base/tests/testSearchSuggestions.java
mobile/android/base/tests/testSelectionHandler.java
mobile/android/base/tests/testSessionFormData.java
mobile/android/base/tests/testSessionFormData.js
mobile/android/base/tests/testSessionHistory.java
mobile/android/base/tests/testSessionOOMRestore.java
mobile/android/base/tests/testSessionOOMSave.java
mobile/android/base/tests/testSettingsMenuItems.java
mobile/android/base/tests/testShareLink.java
mobile/android/base/tests/testSharedPreferences.java
mobile/android/base/tests/testSharedPreferences.js
mobile/android/base/tests/testSimpleDiscovery.java
mobile/android/base/tests/testSimpleDiscovery.js
mobile/android/base/tests/testStumblerSetting.java
mobile/android/base/tests/testSystemPages.java
mobile/android/base/tests/testTextareaSelections.java
mobile/android/base/tests/testThumbnails.java
mobile/android/base/tests/testTitleBar.java
mobile/android/base/tests/testTrackingProtection.java
mobile/android/base/tests/testTrackingProtection.js
mobile/android/base/tests/testUITelemetry.java
mobile/android/base/tests/testUITelemetry.js
mobile/android/base/tests/testVideoControls.java
mobile/android/base/tests/testVideoControls.js
mobile/android/base/tests/testVideoDiscovery.java
mobile/android/base/tests/testVideoDiscovery.js
mobile/android/base/tests/testVkbOverlap.java
mobile/android/base/tests/test_bug720538.html
mobile/android/base/tests/test_bug720538.java
mobile/android/base/tests/test_viewport.sjs
mobile/android/base/tests/tracking_bad.html
mobile/android/base/tests/tracking_good.html
mobile/android/base/tests/video-pattern.ogg
mobile/android/base/tests/video-pattern.webm
mobile/android/base/tests/video_controls.html
mobile/android/base/tests/video_discovery.html
mobile/android/extensions/Makefile.in
python/mozbuild/mozbuild/base.py
services/fxaccounts/FxAccountsProfileChannel.jsm
services/fxaccounts/tests/xpcshell/test_profile_channel.js
startupcache/test/TestStartupCache.cpp
testing/marionette/client/marionette/tests/unit/test_submit.py
testing/mochitest/mochitest_options.py
testing/mochitest/runtests.py
testing/taskcluster/tasks/builds/b2g_aries_lightsaber_nightly.yml
testing/web-platform/meta/service-workers/cache-storage/common.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-delete.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-put.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-keys.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/serviceworker/cache-storage.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-delete.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-put.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-storage-keys.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-storage-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/cache-storage.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/window/sandboxed-iframes.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-add.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-delete.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-put.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-storage-keys.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-storage-match.https.html.ini
testing/web-platform/meta/service-workers/cache-storage/worker/cache-storage.https.html.ini
testing/web-platform/meta/workers/Worker_terminate_event_queue.htm.ini
testing/web-platform/tests/IndexedDB/interfaces.htm
testing/web-platform/tests/web-animations/animation-timeline/animation-timeline.html
testing/xpcshell/selftest.py
toolkit/components/maintenanceservice/serviceinstall.cpp
toolkit/components/telemetry/Histograms.json
toolkit/components/telemetry/TelemetryPing.jsm
toolkit/components/telemetry/tests/unit/test_TelemetryPing.js
toolkit/components/telemetry/tests/unit/test_TelemetryPingBuildID.js
toolkit/components/telemetry/tests/unit/test_TelemetryPingShutdown.js
toolkit/components/telemetry/tests/unit/test_TelemetryPing_idle.js
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/mozapps/update/nsUpdateService.js
toolkit/mozapps/update/tests/data/xpcshellUtilsAUS.js
toolkit/mozapps/update/tests/unit_base_updater/marAppApplyUpdateStageSuccess.js
toolkit/mozapps/update/tests/unit_base_updater/xpcshell.ini
toolkit/mozapps/update/tests/unit_service_updater/marAppApplyUpdateStageSuccessSvc.js
toolkit/mozapps/update/tests/unit_service_updater/xpcshell.ini
toolkit/mozapps/update/updater/updater-common.build
toolkit/mozapps/update/updater/updater.cpp
toolkit/themes/linux/global/icons/find.png
toolkit/themes/linux/global/icons/wrap.png
toolkit/themes/osx/global/icons/error-24.png
toolkit/themes/osx/global/icons/question-24.png
toolkit/themes/osx/global/icons/warning-24.png
toolkit/themes/windows/global/icons/error-24-XP.png
toolkit/themes/windows/global/icons/error-24.png
toolkit/themes/windows/global/icons/error-48-XP.png
toolkit/themes/windows/global/icons/error-48.png
toolkit/themes/windows/global/icons/errorBar-30-aero.png
toolkit/themes/windows/global/icons/errorBar-30.png
toolkit/themes/windows/global/icons/errorBar-60-aero.png
toolkit/themes/windows/global/icons/errorBar-60.png
toolkit/themes/windows/global/icons/errorBarIcon-16-aero.png
toolkit/themes/windows/global/icons/errorBarIcon-16.png
toolkit/themes/windows/global/icons/errorGhosted-64-aero.png
toolkit/themes/windows/global/icons/errorGhosted-64.png
toolkit/themes/windows/global/icons/find-XP.png
toolkit/themes/windows/global/icons/find.png
toolkit/themes/windows/global/icons/information-48-XP.png
toolkit/themes/windows/global/icons/information-48.png
toolkit/themes/windows/global/icons/information-64-XP.png
toolkit/themes/windows/global/icons/information-64.png
toolkit/themes/windows/global/icons/informationBarIcon-16-aero.png
toolkit/themes/windows/global/icons/informationBarIcon-16.png
toolkit/themes/windows/global/icons/informationGhosted-64-aero.png
toolkit/themes/windows/global/icons/informationGhosted-64.png
toolkit/themes/windows/global/icons/question-24-XP.png
toolkit/themes/windows/global/icons/question-24.png
toolkit/themes/windows/global/icons/question-48-XP.png
toolkit/themes/windows/global/icons/question-48.png
toolkit/themes/windows/global/icons/questionBarIcon-16-aero.png
toolkit/themes/windows/global/icons/questionBarIcon-16.png
toolkit/themes/windows/global/icons/questionGhosted-64-aero.png
toolkit/themes/windows/global/icons/questionGhosted-64.png
toolkit/themes/windows/global/icons/warning-24-XP.png
toolkit/themes/windows/global/icons/warning-24.png
toolkit/themes/windows/global/icons/warningBar-30-aero.png
toolkit/themes/windows/global/icons/warningBar-30.png
toolkit/themes/windows/global/icons/warningBar-60-aero.png
toolkit/themes/windows/global/icons/warningBar-60.png
toolkit/themes/windows/global/icons/warningBarIcon-16-aero.png
toolkit/themes/windows/global/icons/warningBarIcon-16.png
toolkit/themes/windows/global/icons/warningGhosted-64-aero.png
toolkit/themes/windows/global/icons/warningGhosted-64.png
toolkit/themes/windows/global/icons/wrap-XP.png
toolkit/themes/windows/global/icons/wrap.png
toolkit/themes/windows/mozapps/extensions/navigation.png
toolkit/xre/nsAppRunner.cpp
toolkit/xre/nsUpdateDriver.cpp
toolkit/xre/nsXREDirProvider.cpp
toolkit/xre/nsXREDirProvider.h
widget/android/APZCCallbackHandler.cpp
widget/android/APZCCallbackHandler.h
xpcom/build/XPCOMInit.cpp
xpcom/glue/nsVoidArray.cpp
xpcom/glue/nsVoidArray.h
new file mode 100644
--- /dev/null
+++ b/.ycm_extra_conf.py
@@ -0,0 +1,34 @@
+# 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/.
+
+import imp
+import os
+from StringIO import StringIO
+import shlex
+
+path = os.path.join(os.path.dirname(__file__), 'mach')
+
+if not os.path.exists(path):
+    path = os.path.join(os.path.dirname(__file__), 'config.status')
+    config = imp.load_module('_buildconfig', open(path), path, ('', 'r', imp.PY_SOURCE))
+    path = os.path.join(config.topsrcdir, 'mach')
+mach_module = imp.load_module('_mach', open(path), path, ('', 'r', imp.PY_SOURCE))
+
+def FlagsForFile(filename):
+    mach = mach_module.get_mach()
+    out = StringIO()
+    out.encoding = None
+    mach.run(['compileflags', filename], stdout=out, stderr=out)
+
+    flag_list = shlex.split(out.getvalue())
+
+    # This flag is added by Fennec for android build and causes ycmd to fail to parse the file.
+    # Removing this flag is a workaround until ycmd starts to handle this flag properly.
+    # https://github.com/Valloric/YouCompleteMe/issues/1490
+    final_flags = [x for x in flag_list if not x.startswith('-march=armv')]
+
+    return {
+        'flags': final_flags,
+        'do_cache': True
+    }
--- a/CLOBBER
+++ b/CLOBBER
@@ -17,9 +17,9 @@
 #
 # Modifying this file will now automatically clobber the buildbot machines \o/
 #
 
 # Are you updating CLOBBER because you think it's needed for your WebIDL
 # changes to stick? As of bug 928195, this shouldn't be necessary! Please
 # don't change CLOBBER for WebIDL changes any more.
 
-Bug 1039866: Removing the metro browser
+Bug 1155494 seems to need a clobber to pick up a change the ipdl parser.
--- a/Makefile.in
+++ b/Makefile.in
@@ -90,17 +90,17 @@ backend.RecursiveMakeBackend:
 Makefile: backend.RecursiveMakeBackend
 	@$(TOUCH) $@
 
 include backend.RecursiveMakeBackend.pp
 
 default:: backend.RecursiveMakeBackend
 
 install_manifests := \
-  $(addprefix dist/,bin idl include public private sdk xpi-stage) \
+  $(addprefix dist/,bin branding idl include public private sdk xpi-stage) \
   _tests \
   $(NULL)
 install_manifest_depends = \
   CLOBBER \
   $(configure_dir)/configure \
   config.status \
   backend.RecursiveMakeBackend \
   $(NULL)
@@ -250,18 +250,19 @@ ifdef MOZ_CRASHREPORTER
 	cd $(DIST)/crashreporter-symbols && \
           zip -r9D '../$(PKG_PATH)$(SYMBOL_ARCHIVE_BASENAME).zip' . -i '*.sym' -i '*.txt'  -x '*test*' -x '*Test*'
 endif # MOZ_CRASHREPORTER
 
 uploadsymbols:
 ifdef MOZ_CRASHREPORTER
 ifdef SOCORRO_SYMBOL_UPLOAD_TOKEN_FILE
 	$(PYTHON) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.py '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
+else
+	$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
 endif
-	$(SHELL) $(topsrcdir)/toolkit/crashreporter/tools/upload_symbols.sh $(SYMBOL_INDEX_NAME) '$(DIST)/$(PKG_PATH)$(SYMBOL_FULL_ARCHIVE_BASENAME).zip'
 endif
 
 # MOZ_SOURCE_STAMP is defined in package-name.mk with a deferred assignment.
 # exporting it makes make run its $(shell) command for each invoked submake,
 # so transform it to an immediate assignment.
 MOZ_SOURCE_STAMP := $(MOZ_SOURCE_STAMP)
 export MOZ_SOURCE_STAMP
 endif
--- a/accessible/atk/AccessibleWrap.cpp
+++ b/accessible/atk/AccessibleWrap.cpp
@@ -118,30 +118,26 @@ static const GInterfaceInfo atk_if_infos
     {(GInterfaceInitFunc)textInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)documentInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr},
     {(GInterfaceInitFunc)imageInterfaceInitCB,
      (GInterfaceFinalizeFunc) nullptr, nullptr}
 };
 
-// This is or'd with the pointer in MaiAtkObject::accWrap if the wrap-ee is a
-// proxy.
-static const uintptr_t IS_PROXY = 1;
-
 static GQuark quark_mai_hyperlink = 0;
 
 AtkHyperlink*
 MaiAtkObject::GetAtkHyperlink()
 {
   NS_ASSERTION(quark_mai_hyperlink, "quark_mai_hyperlink not initialized");
   MaiHyperlink* maiHyperlink =
     (MaiHyperlink*)g_object_get_qdata(G_OBJECT(this), quark_mai_hyperlink);
   if (!maiHyperlink) {
-    maiHyperlink = new MaiHyperlink(reinterpret_cast<Accessible*>(accWrap));
+    maiHyperlink = new MaiHyperlink(accWrap);
     g_object_set_qdata(G_OBJECT(this), quark_mai_hyperlink, maiHyperlink);
   }
 
   return maiHyperlink->GetAtkHyperlink();
 }
 
 void
 MaiAtkObject::Shutdown()
@@ -1040,16 +1036,28 @@ GetWrapperFor(ProxyAccessible* aProxy)
 static uint16_t
 GetInterfacesForProxy(ProxyAccessible* aProxy, uint32_t aInterfaces)
 {
   uint16_t interfaces = 1 << MAI_INTERFACE_COMPONENT;
   if (aInterfaces & Interfaces::HYPERTEXT)
     interfaces |= (1 << MAI_INTERFACE_HYPERTEXT) | (1 << MAI_INTERFACE_TEXT)
         | (1 << MAI_INTERFACE_EDITABLE_TEXT);
 
+  if (aInterfaces & Interfaces::HYPERLINK)
+    interfaces |= MAI_INTERFACE_HYPERLINK_IMPL;
+
+  if (aInterfaces & Interfaces::VALUE)
+    interfaces |= MAI_INTERFACE_VALUE;
+
+  if (aInterfaces & Interfaces::TABLE)
+    interfaces |= MAI_INTERFACE_TABLE;
+
+  if (aInterfaces & Interfaces::IMAGE)
+    interfaces |= MAI_INTERFACE_IMAGE;
+
   return interfaces;
 }
 
 void
 a11y::ProxyCreated(ProxyAccessible* aProxy, uint32_t aInterfaces)
 {
   GType type = GetMaiAtkType(GetInterfacesForProxy(aProxy, aInterfaces));
   NS_ASSERTION(type, "why don't we have a type!");
--- a/accessible/atk/nsMai.h
+++ b/accessible/atk/nsMai.h
@@ -46,16 +46,20 @@ extern int atkMajorVersion, atkMinorVers
  */
 static inline bool
 IsAtkVersionAtLeast(int aMajor, int aMinor)
 {
   return aMajor < atkMajorVersion ||
          (aMajor == atkMajorVersion && aMinor <= atkMinorVersion);
 }
 
+// This is or'd with the pointer in MaiAtkObject::accWrap if the wrap-ee is a
+// proxy.
+static const uintptr_t IS_PROXY = 1;
+
 /**
  * This MaiAtkObject is a thin wrapper, in the MAI namespace, for AtkObject
  */
 struct MaiAtkObject
 {
   AtkObject parent;
   /*
    * The AccessibleWrap whose properties and features are exported
--- a/accessible/atk/nsMaiHyperlink.cpp
+++ b/accessible/atk/nsMaiHyperlink.cpp
@@ -1,16 +1,17 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=2 et sw=2 tw=80: */
 /* 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/. */
 
 #include "nsIURI.h"
 #include "nsMaiHyperlink.h"
+#include "mozilla/a11y/ProxyAccessible.h"
 
 using namespace mozilla::a11y;
 
 /* MaiAtkHyperlink */
 
 #define MAI_TYPE_ATK_HYPERLINK      (mai_atk_hyperlink_get_type ())
 #define MAI_ATK_HYPERLINK(obj)      (G_TYPE_CHECK_INSTANCE_CAST ((obj),\
                                      MAI_TYPE_ATK_HYPERLINK, MaiAtkHyperlink))
@@ -56,18 +57,27 @@ static gchar *getUriCB(AtkHyperlink *aLi
 static AtkObject *getObjectCB(AtkHyperlink *aLink, gint aLinkIndex);
 static gint getEndIndexCB(AtkHyperlink *aLink);
 static gint getStartIndexCB(AtkHyperlink *aLink);
 static gboolean isValidCB(AtkHyperlink *aLink);
 static gint getAnchorCountCB(AtkHyperlink *aLink);
 G_END_DECLS
 
 static gpointer parent_class = nullptr;
-static Accessible*
-get_accessible_hyperlink(AtkHyperlink *aHyperlink);
+
+static MaiHyperlink*
+GetMaiHyperlink(AtkHyperlink *aHyperlink)
+{
+    NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
+    MaiHyperlink * maiHyperlink =
+        MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink;
+    NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr);
+    NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr);
+    return maiHyperlink;
+}
 
 GType
 mai_atk_hyperlink_get_type(void)
 {
     static GType type = 0;
 
     if (!type) {
         static const GTypeInfo tinfo = {
@@ -85,23 +95,20 @@ mai_atk_hyperlink_get_type(void)
 
         type = g_type_register_static(ATK_TYPE_HYPERLINK,
                                       "MaiAtkHyperlink",
                                       &tinfo, GTypeFlags(0));
     }
     return type;
 }
 
-MaiHyperlink::MaiHyperlink(Accessible* aHyperLink) :
+MaiHyperlink::MaiHyperlink(uintptr_t aHyperLink) :
     mHyperlink(aHyperLink),
     mMaiAtkHyperlink(nullptr)
 {
-  if (!mHyperlink->IsLink())
-    return;
-
     mMaiAtkHyperlink =
         reinterpret_cast<AtkHyperlink *>
                         (g_object_new(mai_atk_hyperlink_get_type(), nullptr));
     NS_ASSERTION(mMaiAtkHyperlink, "OUT OF MEMORY");
     if (!mMaiAtkHyperlink)
       return;
 
     MAI_ATK_HYPERLINK(mMaiAtkHyperlink)->maiHyperlink = this;
@@ -148,84 +155,107 @@ finalizeCB(GObject *aObj)
     /* call parent finalize function */
     if (G_OBJECT_CLASS (parent_class)->finalize)
         G_OBJECT_CLASS (parent_class)->finalize(aObj);
 }
 
 gchar *
 getUriCB(AtkHyperlink *aLink, gint aLinkIndex)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, nullptr);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return nullptr;
 
+  nsAutoCString cautoStr;
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink()) {
     nsCOMPtr<nsIURI> uri = hyperlink->AnchorURIAt(aLinkIndex);
     if (!uri)
-        return nullptr;
+      return nullptr;
 
-    nsAutoCString cautoStr;
     nsresult rv = uri->GetSpec(cautoStr);
     NS_ENSURE_SUCCESS(rv, nullptr);
 
     return g_strdup(cautoStr.get());
+  }
+
+  bool valid;
+  maiLink->Proxy()->AnchorURIAt(aLinkIndex, cautoStr, &valid);
+  if (!valid)
+    return nullptr;
+
+  return g_strdup(cautoStr.get());
 }
 
 AtkObject *
 getObjectCB(AtkHyperlink *aLink, gint aLinkIndex)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, nullptr);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return nullptr;
 
-    Accessible* anchor = hyperlink->AnchorAt(aLinkIndex);
-    NS_ENSURE_TRUE(anchor, nullptr);
+    if (Accessible* hyperlink = maiLink->GetAccHyperlink()) {
+      Accessible* anchor = hyperlink->AnchorAt(aLinkIndex);
+      NS_ENSURE_TRUE(anchor, nullptr);
 
-    AtkObject* atkObj = AccessibleWrap::GetAtkObject(anchor);
-    //no need to add ref it, because it is "get" not "ref"
-    return atkObj;
+      return AccessibleWrap::GetAtkObject(anchor);
+    }
+
+    ProxyAccessible* anchor = maiLink->Proxy()->AnchorAt(aLinkIndex);
+    return anchor ? GetWrapperFor(anchor) : nullptr;
 }
 
 gint
 getEndIndexCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, -1);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return false;
 
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
     return static_cast<gint>(hyperlink->EndOffset());
+
+  bool valid = false;
+  uint32_t endIdx = maiLink->Proxy()->EndOffset(&valid);
+  return valid ? static_cast<gint>(endIdx) : -1;
 }
 
 gint
 getStartIndexCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, -1);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (maiLink)
+    return -1;
 
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
     return static_cast<gint>(hyperlink->StartOffset());
+
+  bool valid = false;
+  uint32_t startIdx = maiLink->Proxy()->StartOffset(&valid);
+  return valid ? static_cast<gint>(startIdx) : -1;
 }
 
 gboolean
 isValidCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, FALSE);
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return false;
 
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
     return static_cast<gboolean>(hyperlink->IsLinkValid());
+
+  return static_cast<gboolean>(maiLink->Proxy()->IsLinkValid());
 }
 
 gint
 getAnchorCountCB(AtkHyperlink *aLink)
 {
-    Accessible* hyperlink = get_accessible_hyperlink(aLink);
-    NS_ENSURE_TRUE(hyperlink, -1);
-
-    return static_cast<gint>(hyperlink->AnchorCount());
-}
+  MaiHyperlink* maiLink = GetMaiHyperlink(aLink);
+  if (!maiLink)
+    return -1;
 
-// Check if aHyperlink is a valid MaiHyperlink, and return the
-// HyperLinkAccessible related.
-Accessible*
-get_accessible_hyperlink(AtkHyperlink *aHyperlink)
-{
-    NS_ENSURE_TRUE(MAI_IS_ATK_HYPERLINK(aHyperlink), nullptr);
-    MaiHyperlink * maiHyperlink =
-        MAI_ATK_HYPERLINK(aHyperlink)->maiHyperlink;
-    NS_ENSURE_TRUE(maiHyperlink != nullptr, nullptr);
-    NS_ENSURE_TRUE(maiHyperlink->GetAtkHyperlink() == aHyperlink, nullptr);
-    return maiHyperlink->GetAccHyperlink();
+  if (Accessible* hyperlink = maiLink->GetAccHyperlink())
+    return static_cast<gint>(hyperlink->AnchorCount());
+
+  bool valid = false;
+  uint32_t anchorCount = maiLink->Proxy()->AnchorCount(&valid);
+  return valid ? static_cast<gint>(anchorCount) : -1;
 }
--- a/accessible/atk/nsMaiHyperlink.h
+++ b/accessible/atk/nsMaiHyperlink.h
@@ -18,25 +18,40 @@ namespace a11y {
 
 /*
  * MaiHyperlink is a auxiliary class for MaiInterfaceHyperText.
  */
 
 class MaiHyperlink
 {
 public:
-  explicit MaiHyperlink(Accessible* aHyperLink);
+  explicit MaiHyperlink(uintptr_t aHyperLink);
   ~MaiHyperlink();
 
 public:
   AtkHyperlink* GetAtkHyperlink() const { return mMaiAtkHyperlink; }
   Accessible* GetAccHyperlink()
-    { return mHyperlink && mHyperlink->IsLink() ? mHyperlink : nullptr; }
+    {
+      if (!mHyperlink || mHyperlink & IS_PROXY)
+        return nullptr;
+
+      Accessible* link = reinterpret_cast<Accessible*>(mHyperlink);
+      NS_ASSERTION(link->IsLink(), "Why isn't it a link!");
+      return link;
+    }
+
+  ProxyAccessible* Proxy() const
+  {
+    if (!(mHyperlink & IS_PROXY))
+      return nullptr;
+
+    return reinterpret_cast<ProxyAccessible*>(mHyperlink & ~IS_PROXY);
+  }
 
 protected:
-  Accessible* mHyperlink;
+  uintptr_t mHyperlink;
   AtkHyperlink* mMaiAtkHyperlink;
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif /* __MAI_HYPERLINK_H__ */
--- a/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp
+++ b/accessible/atk/nsMaiInterfaceHyperlinkImpl.cpp
@@ -11,20 +11,21 @@
 
 using namespace mozilla::a11y;
 
 extern "C" {
 static AtkHyperlink*
 getHyperlinkCB(AtkHyperlinkImpl* aImpl)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aImpl));
-  if (!accWrap)
+  if (!accWrap || !GetProxy(ATK_OBJECT(aImpl)))
     return nullptr;
 
-  NS_ENSURE_TRUE(accWrap->IsLink(), nullptr);
+  if (accWrap)
+    NS_ASSERTION(accWrap->IsLink(), "why isn't it a link!");
 
   return MAI_ATK_OBJECT(aImpl)->GetAtkHyperlink();
 }
 }
 
 void
 hyperlinkImplInterfaceInitCB(AtkHyperlinkImplIface *aIface)
 {
--- a/accessible/atk/nsMaiInterfaceHypertext.cpp
+++ b/accessible/atk/nsMaiInterfaceHypertext.cpp
@@ -17,41 +17,37 @@
 using namespace mozilla::a11y;
 
 extern "C" {
 
 static AtkHyperlink*
 getLinkCB(AtkHypertext *aText, gint aLinkIndex)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
+  AtkObject* atkHyperLink = nullptr;
   if (accWrap) {
     HyperTextAccessible* hyperText = accWrap->AsHyperText();
     NS_ENSURE_TRUE(hyperText, nullptr);
 
     Accessible* hyperLink = hyperText->LinkAt(aLinkIndex);
-    if (!hyperLink) {
+    if (!hyperLink || !hyperLink->IsLink()) {
       return nullptr;
     }
 
-    AtkObject* hyperLinkAtkObj = AccessibleWrap::GetAtkObject(hyperLink);
-    NS_ENSURE_TRUE(IS_MAI_OBJECT(hyperLinkAtkObj), nullptr);
+    atkHyperLink = AccessibleWrap::GetAtkObject(hyperLink);
+  } else if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
+    ProxyAccessible* proxyLink = proxy->LinkAt(aLinkIndex);
+    if (!proxyLink)
+      return nullptr;
 
-    return MAI_ATK_OBJECT(hyperLinkAtkObj)->GetAtkHyperlink();
+    atkHyperLink = GetWrapperFor(proxyLink);
   }
 
-  if (ProxyAccessible* proxy = GetProxy(ATK_OBJECT(aText))) {
-    ProxyAccessible* proxyLink = proxy->LinkAt(aLinkIndex);
-    if (proxyLink) {
-      NS_WARNING("IMPLEMENT ME! See bug 1146518.");
-      // We should somehow get from ProxyAccessible* to AtkHyperlink*.
-    }
-    return nullptr;
-  }
-
-  return nullptr;
+    NS_ENSURE_TRUE(IS_MAI_OBJECT(atkHyperLink), nullptr);
+    return MAI_ATK_OBJECT(atkHyperLink)->GetAtkHyperlink();
 }
 
 static gint
 getLinkCountCB(AtkHypertext *aText)
 {
   AccessibleWrap* accWrap = GetAccessibleWrap(ATK_OBJECT(aText));
   if (accWrap) {
     HyperTextAccessible* hyperText = accWrap->AsHyperText();
--- a/accessible/base/nsAccessibilityService.cpp
+++ b/accessible/base/nsAccessibilityService.cpp
@@ -1252,34 +1252,39 @@ nsAccessibilityService::Init()
 
   for (uint32_t i = 0; i < ArrayLength(sMarkupMapList); i++)
     mMarkupMaps.Put(*sMarkupMapList[i].tag, &sMarkupMapList[i]);
 
 #ifdef A11Y_LOG
   logging::CheckEnv();
 #endif
 
-  gApplicationAccessible = new ApplicationAccessibleWrap();
+  if (XRE_GetProcessType() == GeckoProcessType_Default)
+    gApplicationAccessible = new ApplicationAccessibleWrap();
+  else
+    gApplicationAccessible = new ApplicationAccessible();
+
   NS_ADDREF(gApplicationAccessible); // will release in Shutdown()
 
 #ifdef MOZ_CRASHREPORTER
   CrashReporter::
     AnnotateCrashReport(NS_LITERAL_CSTRING("Accessibility"),
                         NS_LITERAL_CSTRING("Active"));
 #endif
 
 #ifdef XP_WIN
   sPendingPlugins = new nsTArray<nsCOMPtr<nsIContent> >;
   sPluginTimers = new nsTArray<nsCOMPtr<nsITimer> >;
 #endif
 
   gIsShutdown = false;
 
   // Now its safe to start platform accessibility.
-  PlatformInit();
+  if (XRE_GetProcessType() == GeckoProcessType_Default)
+    PlatformInit();
 
   return true;
 }
 
 void
 nsAccessibilityService::Shutdown()
 {
   // Remove observers.
@@ -1311,17 +1316,19 @@ nsAccessibilityService::Shutdown()
   // accessibility service as shutdown to prevent calls of its methods.
   // Don't null accessibility service static member at this point to be safe
   // if someone will try to operate with it.
 
   NS_ASSERTION(!gIsShutdown, "Accessibility was shutdown already");
 
   gIsShutdown = true;
 
-  PlatformShutdown();
+  if (XRE_GetProcessType() == GeckoProcessType_Default)
+    PlatformShutdown();
+
   gApplicationAccessible->Shutdown();
   NS_RELEASE(gApplicationAccessible);
   gApplicationAccessible = nullptr;
 
   NS_IF_RELEASE(gXPCApplicationAccessible);
   gXPCApplicationAccessible = nullptr;
 }
 
--- a/accessible/ipc/DocAccessibleChild.cpp
+++ b/accessible/ipc/DocAccessibleChild.cpp
@@ -22,16 +22,28 @@ namespace a11y {
 
 static uint32_t
 InterfacesFor(Accessible* aAcc)
 {
   uint32_t interfaces = 0;
   if (aAcc->IsHyperText() && aAcc->AsHyperText()->IsTextRole())
     interfaces |= Interfaces::HYPERTEXT;
 
+  if (aAcc->IsLink())
+    interfaces |= Interfaces::HYPERLINK;
+
+  if (aAcc->HasNumericValue())
+    interfaces |= Interfaces::VALUE;
+
+  if (aAcc->IsImage())
+    interfaces |= Interfaces::IMAGE;
+
+  if (aAcc->IsTableCell())
+    interfaces |= Interfaces::TABLECELL;
+
   return interfaces;
 }
 
 static void
 SerializeTree(Accessible* aRoot, nsTArray<AccessibleData>& aTree)
 {
   uint64_t id = reinterpret_cast<uint64_t>(aRoot->UniqueID());
   uint32_t role = aRoot->Role();
--- a/accessible/ipc/ProxyAccessible.h
+++ b/accessible/ipc/ProxyAccessible.h
@@ -309,15 +309,20 @@ private:
   uintptr_t mWrapper;
   uint64_t mID;
   role mRole : 31;
   bool mOuterDoc : 1;
 };
 
 enum Interfaces
 {
-  HYPERTEXT = 1
+  HYPERTEXT = 1,
+  HYPERLINK = 2,
+  IMAGE = 4,
+  VALUE = 8,
+  TABLE = 16,
+  TABLECELL = 32,
 };
 
 }
 }
 
 #endif
--- a/accessible/windows/ia2/ia2Accessible.cpp
+++ b/accessible/windows/ia2/ia2Accessible.cpp
@@ -349,17 +349,17 @@ ia2Accessible::get_states(AccessibleStat
     return E_INVALIDARG;
   *aStates = 0;
 
   // XXX: bug 344674 should come with better approach that we have here.
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
   if (acc->IsDefunct()) {
     *aStates = IA2_STATE_DEFUNCT;
-    return CO_E_OBJNOTCONNECTED;
+    return S_OK;
   }
 
   uint64_t state;
   if (acc->IsProxy())
     state = acc->Proxy()->State();
   else
     state = acc->State();
 
@@ -490,17 +490,17 @@ STDMETHODIMP
 ia2Accessible::get_uniqueID(long* aUniqueID)
 {
   A11Y_TRYBLOCK_BEGIN
 
   if (!aUniqueID)
     return E_INVALIDARG;
 
   AccessibleWrap* acc = static_cast<AccessibleWrap*>(this);
-  *aUniqueID = - reinterpret_cast<intptr_t>(acc->UniqueID());
+  *aUniqueID = AccessibleWrap::GetChildIDFor(acc);
   return S_OK;
 
   A11Y_TRYBLOCK_END
 }
 
 STDMETHODIMP
 ia2Accessible::get_windowHandle(HWND* aWindowHandle)
 {
--- a/accessible/windows/msaa/AccessibleWrap.cpp
+++ b/accessible/windows/msaa/AccessibleWrap.cpp
@@ -51,26 +51,58 @@ const uint32_t USE_ROLE_STRING = 0;
  */
 
 //#define DEBUG_LEAKS
 
 #ifdef DEBUG_LEAKS
 static gAccessibles = 0;
 #endif
 
+#ifdef _WIN64
+IDSet AccessibleWrap::sIDGen;
+
+static const uint32_t kNoID = 0;
+#endif
+
 static const int32_t kIEnumVariantDisconnected = -1;
 
 ////////////////////////////////////////////////////////////////////////////////
 // AccessibleWrap
 ////////////////////////////////////////////////////////////////////////////////
+AccessibleWrap::AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
+  Accessible(aContent, aDoc)
+#ifdef _WIN64
+  , mID(kNoID)
+#endif
+{
+}
+
+AccessibleWrap::~AccessibleWrap()
+{
+#ifdef _WIN64
+  if (mID != kNoID)
+    sIDGen.ReleaseID(mID);
+#endif
+}
 
 ITypeInfo* AccessibleWrap::gTypeInfo = nullptr;
 
 NS_IMPL_ISUPPORTS_INHERITED0(AccessibleWrap, Accessible)
 
+void
+AccessibleWrap::Shutdown()
+{
+#ifdef _WIN64
+  if (mID != kNoID)
+    static_cast<DocAccessibleWrap*>(mDoc)->RemoveID(mID);
+#endif
+
+  Accessible::Shutdown();
+}
+
 //-----------------------------------------------------
 // IUnknown interface methods - see iunknown.h for documentation
 //-----------------------------------------------------
 
 // Microsoft COM QueryInterface
 STDMETHODIMP
 AccessibleWrap::QueryInterface(REFIID iid, void** ppv)
 {
@@ -1249,20 +1281,33 @@ AccessibleWrap::HandleAccEvent(AccEvent*
 
 int32_t
 AccessibleWrap::GetChildIDFor(Accessible* aAccessible)
 {
   // A child ID of the window is required, when we use NotifyWinEvent,
   // so that the 3rd party application can call back and get the IAccessible
   // the event occurred on.
 
-  // Yes, this means we're only compatibible with 32 bit
-  // MSAA is only available for 32 bit windows, so it's okay
-  // XXX: bug 606080
-  return aAccessible ? - NS_PTR_TO_INT32(aAccessible->UniqueID()) : 0;
+#ifdef _WIN64
+  if (!aAccessible || !aAccessible->Document())
+    return 0;
+
+  uint32_t* id = & static_cast<AccessibleWrap*>(aAccessible)->mID;
+  if (*id != kNoID)
+    return *id;
+
+  *id = sIDGen.GetID();
+  DocAccessibleWrap* doc =
+    static_cast<DocAccessibleWrap*>(aAccessible->Document());
+  doc->AddID(*id, static_cast<AccessibleWrap*>(aAccessible));
+
+  return *id;
+#else
+  return - reinterpret_cast<intptr_t>(aAccessible);
+#endif
 }
 
 HWND
 AccessibleWrap::GetHWNDFor(Accessible* aAccessible)
 {
   if (aAccessible) {
     DocAccessible* document = aAccessible->Document();
     if(!document)
@@ -1302,16 +1347,35 @@ AccessibleWrap::NativeAccessible(Accessi
     return nullptr;
   }
 
   IAccessible* msaaAccessible = nullptr;
   aAccessible->GetNativeInterface(reinterpret_cast<void**>(&msaaAccessible));
   return static_cast<IDispatch*>(msaaAccessible);
 }
 
+#ifdef _WIN64
+static Accessible*
+GetAccessibleInSubtree(DocAccessible* aDoc, uint32_t aID)
+{
+  Accessible* child = static_cast<DocAccessibleWrap*>(aDoc)->GetAccessibleByID(aID);
+  if (child)
+    return child;
+
+  uint32_t childDocCount = aDoc->ChildDocumentCount();
+  for (uint32_t i = 0; i < childDocCount; i++) {
+    child = GetAccessibleInSubtree(aDoc->GetChildDocumentAt(i), aID);
+    if (child)
+      return child;
+  }
+
+    return nullptr;
+  }
+#endif
+
 Accessible*
 AccessibleWrap::GetXPAccessibleFor(const VARIANT& aVarChild)
 {
   if (aVarChild.vt != VT_I4)
     return nullptr;
 
   // if its us real easy - this seems to always be the case
   if (aVarChild.lVal == CHILDID_SELF)
@@ -1337,17 +1401,21 @@ AccessibleWrap::GetXPAccessibleFor(const
   // Otherwise we treat lVal as index in parent.
 
   if (aVarChild.lVal < 0) {
     // Convert child ID to unique ID.
     void* uniqueID = reinterpret_cast<void*>(-aVarChild.lVal);
 
     DocAccessible* document = Document();
     Accessible* child =
+#ifdef _WIN64
+    GetAccessibleInSubtree(document, static_cast<uint32_t>(aVarChild.lVal));
+#else
       document->GetAccessibleByUniqueIDInSubtree(uniqueID);
+#endif
 
     // If it is a document then just return an accessible.
     if (IsDoc())
       return child;
 
     // Otherwise check whether the accessible is a child (this path works for
     // ARIA documents and popups).
     Accessible* parent = child;
--- a/accessible/windows/msaa/AccessibleWrap.h
+++ b/accessible/windows/msaa/AccessibleWrap.h
@@ -10,16 +10,17 @@
 #include "nsCOMPtr.h"
 #include "Accessible.h"
 #include "Accessible2.h"
 #include "ia2Accessible.h"
 #include "ia2AccessibleComponent.h"
 #include "ia2AccessibleHyperlink.h"
 #include "ia2AccessibleValue.h"
 #include "mozilla/a11y/ProxyAccessible.h"
+#include "mozilla/a11y/IDSet.h"
 
 #ifdef __GNUC__
 // Inheriting from both XPCOM and MSCOM interfaces causes a lot of warnings
 // about virtual functions being hidden by each other. This is done by
 // design, so silence the warning.
 #pragma GCC diagnostic ignored "-Woverloaded-virtual"
 #endif
 
@@ -28,18 +29,17 @@ namespace a11y {
 
 class AccessibleWrap : public Accessible,
                        public ia2Accessible,
                        public ia2AccessibleComponent,
                        public ia2AccessibleHyperlink,
                        public ia2AccessibleValue
 {
 public: // construction, destruction
-  AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc) :
-    Accessible(aContent, aDoc) { }
+  AccessibleWrap(nsIContent* aContent, DocAccessible* aDoc);
 
   // nsISupports
   NS_DECL_ISUPPORTS_INHERITED
 
   public: // IUnknown methods - see iunknown.h for documentation
     STDMETHODIMP QueryInterface(REFIID, void**);
 
   // Return the registered OLE class ID of this object's CfDataObj.
@@ -147,16 +147,17 @@ public: // construction, destruction
                                            LCID lcid, WORD wFlags,
                                            DISPPARAMS *pDispParams,
                                            VARIANT *pVarResult,
                                            EXCEPINFO *pExcepInfo,
                                            UINT *puArgErr);
 
   // Accessible
   virtual nsresult HandleAccEvent(AccEvent* aEvent);
+  virtual void Shutdown() override;
 
   // Helper methods
   static int32_t GetChildIDFor(Accessible* aAccessible);
   static HWND GetHWNDFor(Accessible* aAccessible);
 
   /**
    * System caret support: update the Windows caret position. 
    * The system caret works more universally than the MSAA caret
@@ -171,25 +172,32 @@ public: // construction, destruction
    */
   Accessible* GetXPAccessibleFor(const VARIANT& aVarChild);
 
   virtual void GetNativeInterface(void **aOutAccessible) override;
 
   static IDispatch* NativeAccessible(Accessible* aAccessible);
 
 protected:
-  virtual ~AccessibleWrap() { }
+  virtual ~AccessibleWrap();
+
+#ifdef _WIN64
+  uint32_t mID;
+#endif
 
   /**
    * Creates ITypeInfo for LIBID_Accessibility if it's needed and returns it.
    */
   static ITypeInfo* GetTI(LCID lcid);
 
   static ITypeInfo* gTypeInfo;
 
+#ifdef _WIN64
+  static IDSet sIDGen;
+#endif
 
   enum navRelations {
     NAVRELATION_CONTROLLED_BY = 0x1000,
     NAVRELATION_CONTROLLER_FOR = 0x1001,
     NAVRELATION_LABEL_FOR = 0x1002,
     NAVRELATION_LABELLED_BY = 0x1003,
     NAVRELATION_MEMBER_OF = 0x1004,
     NAVRELATION_NODE_CHILD_OF = 0x1005,
--- a/accessible/windows/msaa/Compatibility.h
+++ b/accessible/windows/msaa/Compatibility.h
@@ -34,16 +34,36 @@ public:
    */
   static bool IsWE() { return !!(sConsumers & WE); }
 
   /**
    * Return true if Dolphin mode is enabled.
    */
   static bool IsDolphin() { return !!(sConsumers & DOLPHIN); }
 
+  /**
+   * Return true if we should disable e10s due to a detected
+   * accessibility client.
+   */
+  static bool IsBlacklistedForE10S()
+  {
+    // We currently blacklist everything except UNKNOWN and UIAUTOMATION
+    return !!(sConsumers &
+              (NVDA     |
+               JAWS     |
+               OLDJAWS  |
+               WE       |
+               DOLPHIN  |
+               SEROTEK  |
+               COBRA    |
+               ZOOMTEXT |
+               KAZAGURU |
+               YOUDAO));
+  }
+
 private:
   Compatibility();
   Compatibility(const Compatibility&);
   Compatibility& operator = (const Compatibility&);
 
   /**
    * Initialize compatibility mode. Called by platform (see Platform.h) during
    * accessibility initialization.
--- a/accessible/windows/msaa/DocAccessibleWrap.h
+++ b/accessible/windows/msaa/DocAccessibleWrap.h
@@ -29,20 +29,38 @@ public:
         /* [retval][out] */ BSTR __RPC_FAR *pszValue);
 
   // Accessible
   virtual void Shutdown();
 
   // DocAccessible
   virtual void* GetNativeWindow() const;
 
+  /**
+   * Manage the mapping from id to Accessible.
+   */
+#ifdef _WIN64
+  void AddID(uint32_t aID, AccessibleWrap* aAcc)
+    { mIDToAccessibleMap.Put(aID, aAcc); }
+  void RemoveID(uint32_t aID) { mIDToAccessibleMap.Remove(aID); }
+  AccessibleWrap* GetAccessibleByID(uint32_t aID) const
+    { return mIDToAccessibleMap.Get(aID); }
+#endif
+
 protected:
   // DocAccessible
   virtual void DoInitialUpdate();
 
 protected:
   void* mHWND;
+
+  /*
+   * This provides a mapping from 32 bit id to accessible objects.
+   */
+#ifdef _WIN64
+  nsDataHashtable<nsUint32HashKey, AccessibleWrap*> mIDToAccessibleMap;
+#endif
 };
 
 } // namespace a11y
 } // namespace mozilla
 
 #endif
new file mode 100644
--- /dev/null
+++ b/accessible/windows/msaa/IDSet.h
@@ -0,0 +1,126 @@
+/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* vim: set ts=8 sts=2 et sw=2 tw=80: */
+/* 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/. */
+
+/**
+ * A class to generate unique IDs in the range [ - 2^31, 0 )
+ */
+
+#ifndef MOZILLA_A11Y_IDSet_h_
+#define MOZILLA_A11Y_IDSet_h_
+
+#include "mozilla/Attributes.h"
+#include "mozilla/MathAlgorithms.h"
+#include "mozilla/SplayTree.h"
+
+namespace mozilla {
+namespace a11y {
+
+/**
+ * On windows an accessible's id must be a negative 32 bit integer.  It is
+ * important to support recycling arbitrary IDs because accessibles can be
+ * created and destroyed at any time in the life of a page.  IDSet provides 2
+ * operations: generate an ID in the range [ - 2^31, 0 ), and release an ID so
+ * it can be allocated again.  Allocated ID are tracked by a sparse bitmap
+ * implemented with a splay tree.  Nodes in the tree are keyed by the upper N
+ * bits of the bitwise negation of the ID, and the node contains a bitmap
+ * tracking the allocation of 2^(32 - N) IDs.
+ */
+class IDSet
+{
+public:
+  MOZ_CONSTEXPR IDSet() : mBitSet(), mIdx(0) {}
+
+  /**
+   * Return a new unique id.
+   */
+  uint32_t GetID()
+  {
+    uint32_t idx = mIdx;
+    while (true) {
+      BitSetElt* elt = mBitSet.findOrInsert(BitSetElt(idx));
+      if (elt->mBitvec[0] != UINT64_MAX) {
+        uint32_t i = CountTrailingZeroes64(~elt->mBitvec[0]);
+
+        elt->mBitvec[0] |= (1ull << i);
+        mIdx = idx;
+        return ~(elt->mIdx * bitsPerElt + i);
+      }
+
+      if (elt->mBitvec[1] != UINT64_MAX) {
+        uint32_t i = CountTrailingZeroes64(~elt->mBitvec[1]);
+
+        elt->mBitvec[1] |= (1ull << i);
+        mIdx = idx;
+        return ~(elt->mIdx * bitsPerElt + bitsPerWord + i);
+      }
+
+      idx++;
+      if (idx > sMaxIdx) {
+        idx = 0;
+      }
+
+      if (idx == mIdx) {
+        MOZ_CRASH("used up all the available ids");
+      }
+    }
+  }
+
+  /**
+   * Free a no longer required id so it may be allocated again.
+   */
+  void ReleaseID(uint32_t aID)
+  {
+    aID = ~aID;
+    MOZ_ASSERT(aID < static_cast<uint32_t>(INT32_MAX));
+
+    uint32_t idx = aID / bitsPerElt;
+    mIdx = idx;
+    BitSetElt* elt = mBitSet.find(BitSetElt(idx));
+    MOZ_ASSERT(elt);
+
+    uint32_t vecIdx = (aID % bitsPerElt) / bitsPerWord;
+    elt->mBitvec[vecIdx] &= ~(1ull << (aID % bitsPerWord));
+    if (elt->mBitvec[0] == 0 && elt->mBitvec[1] == 0) {
+      delete mBitSet.remove(*elt);
+    }
+  }
+
+private:
+  static const unsigned int wordsPerElt = 2;
+  static const unsigned int bitsPerWord = 64;
+  static const unsigned int bitsPerElt = wordsPerElt * bitsPerWord;
+  static const uint32_t sMaxIdx = INT32_MAX / bitsPerElt;
+
+  struct BitSetElt : mozilla::SplayTreeNode<BitSetElt>
+  {
+    explicit BitSetElt(uint32_t aIdx) :
+      mIdx(aIdx)
+    { mBitvec[0] = mBitvec[1] = 0; }
+
+    uint64_t mBitvec[wordsPerElt];
+    uint32_t mIdx;
+
+    static int compare(const BitSetElt& a, const BitSetElt& b)
+    {
+      if (a.mIdx == b.mIdx) {
+        return 0;
+      }
+
+      if (a.mIdx < b.mIdx) {
+        return -1;
+      }
+      return 1;
+    }
+  };
+
+  SplayTree<BitSetElt, BitSetElt> mBitSet;
+  uint32_t mIdx;
+};
+
+}
+}
+
+#endif
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -7,16 +7,17 @@
 EXPORTS += [
     'IUnknownImpl.h',
 ]
 
 EXPORTS.mozilla.a11y += [
     'AccessibleWrap.h',
     'Compatibility.h',
     'HyperTextAccessibleWrap.h',
+    'IDSet.h',
 ]
 
 UNIFIED_SOURCES += [
     'AccessibleWrap.cpp',
     'ApplicationAccessibleWrap.cpp',
     'ARIAGridAccessibleWrap.cpp',
     'Compatibility.cpp',
     'DocAccessibleWrap.cpp',
--- a/addon-sdk/source/lib/sdk/self.js
+++ b/addon-sdk/source/lib/sdk/self.js
@@ -23,17 +23,17 @@ const loadReason = readPref("load.reason
 const rootURI = readPref("rootURI") || options.rootURI || "";
 const baseURI = readPref("baseURI") || options.prefixURI + name + "/"
 const addonDataURI = baseURI + "data/";
 const metadata = options.metadata || {};
 const permissions = metadata.permissions || {};
 const isPacked = rootURI && rootURI.indexOf("jar:") === 0;
 
 const uri = (path="") =>
-  path.contains(":") ? path : addonDataURI + path.replace(/^\.\//, "");
+  path.includes(":") ? path : addonDataURI + path.replace(/^\.\//, "");
 
 let preferencesBranch = ("preferences-branch" in metadata)
                             ? metadata["preferences-branch"]
                             : options.preferencesBranch
 
 if (/[^\w{@}.-]/.test(preferencesBranch)) {
   preferencesBranch = id;
   console.warn("Ignoring preferences-branch (not a valid branch name)");
--- a/addon-sdk/source/test/addons/e10s-content/lib/test-page-worker.js
+++ b/addon-sdk/source/test/addons/e10s-content/lib/test-page-worker.js
@@ -475,17 +475,17 @@ exports.testMessageQueue = function (ass
 };
 
 exports.testWindowStopDontBreak = function (assert, done) {
   const { Ci, Cc } = require('chrome');
   const consoleService = Cc['@mozilla.org/consoleservice;1'].
                             getService(Ci.nsIConsoleService);
   const listener = {
     observe: ({message}) => {
-      if (message.contains('contentWorker is null'))
+      if (message.includes('contentWorker is null'))
         assert.fail('contentWorker is null');
     }
   };
   consoleService.registerListener(listener)
 
   let page = new Page({
     contentURL: 'data:text/html;charset=utf-8,testWindowStopDontBreak',
     contentScriptWhen: 'ready',
--- a/addon-sdk/source/test/fixtures.js
+++ b/addon-sdk/source/test/fixtures.js
@@ -1,16 +1,16 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 const { uri } = module;
 const prefix = uri.substr(0, uri.lastIndexOf("/") + 1) + "fixtures/";
 
-exports.url = (path="") => path && path.contains(":")
+exports.url = (path="") => path && path.includes(":")
   ? path
   : prefix + path.replace(/^\.\//, "");
 
 const base64jpeg = "data:image/jpeg;base64,%2F9j%2F4AAQSkZJRgABAQAAAQABAAD%2F" +
                   "2wBDAAMCAgICAgMCAgIDAwMDBAYEBAQEBAgGBgUGCQgKCgkICQkKDA8MCg" +
                   "sOCwkJDRENDg8QEBEQCgwSExIQEw8QEBD%2F2wBDAQMDAwQDBAgEBAgQCw" +
                   "kLEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQ" +
                   "EBAQEBAQEBD%2FwAARCAAgACADAREAAhEBAxEB%2F8QAHwAAAQUBAQEBAQ" +
--- a/addon-sdk/source/test/test-content-events.js
+++ b/addon-sdk/source/test/test-content-events.js
@@ -129,17 +129,17 @@ exports["test dead object errors"] = fun
 
   // The dead object error is properly reported on console but
   // doesn't raise any test's exception
   function onMessage({ subject }) {
     let message = subject.wrappedJSObject;
     let { level } = message;
     let text = String(message.arguments[0]);
 
-    if (level === "error" && text.contains("can't access dead object"))
+    if (level === "error" && text.includes("can't access dead object"))
       fail(text);
   }
 
   let cleanup = () => system.off("console-api-log-event", onMessage);
   let fail = (reason) => {
     cleanup();
     assert.fail(reason);
   }
--- a/addon-sdk/source/test/test-page-worker.js
+++ b/addon-sdk/source/test/test-page-worker.js
@@ -483,17 +483,17 @@ exports.testMessageQueue = function (ass
 };
 
 exports.testWindowStopDontBreak = function (assert, done) {
   const { Ci, Cc } = require('chrome');
   const consoleService = Cc['@mozilla.org/consoleservice;1'].
                             getService(Ci.nsIConsoleService);
   const listener = {
     observe: ({message}) => {
-      if (message.contains('contentWorker is null'))
+      if (message.includes('contentWorker is null'))
         assert.fail('contentWorker is null');
     }
   };
   consoleService.registerListener(listener)
 
   let page = new Page({
     contentURL: 'data:text/html;charset=utf-8,testWindowStopDontBreak',
     contentScriptWhen: 'ready',
--- a/addon-sdk/source/test/test-system-input-output.js
+++ b/addon-sdk/source/test/test-system-input-output.js
@@ -21,17 +21,17 @@ const isConsoleEvent = topic =>
    "console-storage-cache-event"].indexOf(topic) >= 0;
 
 const message = x => ({wrappedJSObject: {data: x}});
 
 exports["test start / stop ports"] = assert => {
   const input = new InputPort({ id: Date.now().toString(32), initial: {data:0} });
   const topic = input.topic;
 
-  assert.ok(topic.contains(addonID), "topics are namespaced to add-on");
+  assert.ok(topic.includes(addonID), "topics are namespaced to add-on");
 
   const xs = lift(({data}) => "x:" + data, input);
   const ys = lift(({data}) => "y:" + data, input);
 
   assert.deepEqual(input.value, {data:0}, "initila value is set");
   assert.deepEqual(xs.value, "x:0", "initial value is mapped");
   assert.deepEqual(ys.value, "y:0", "initial value is mapped");
 
@@ -211,17 +211,17 @@ exports["test explicit input topic"] = (
 };
 
 
 exports["test receive what was send"] = assert => {
   const id = Date.now().toString(32);
   const input = new InputPort({ id: id, initial: 0});
   const output = new OutputPort({ id: id, sync: true });
 
-  assert.ok(input.topic.contains(addonID),
+  assert.ok(input.topic.includes(addonID),
             "input topic is namespaced to addon");
   assert.equal(input.topic, output.topic,
               "input & output get same topics from id.");
 
   start(input);
 
   assert.equal(input.value, 0, "initial value is set");
 
--- a/b2g/app/b2g.js
+++ b/b2g/app/b2g.js
@@ -313,21 +313,27 @@ pref("media.cache_size", 4096);    // 4M
 // below 10s of buffered data.
 pref("media.cache_resume_threshold", 10);
 pref("media.cache_readahead_limit", 30);
 
 #ifdef MOZ_FMP4
 // Enable/Disable Gonk Decoder Module
 pref("media.fragmented-mp4.gonk.enabled", true);
 #endif
+
+//Encrypted media extensions.
+pref("media.eme.enabled", true);
+pref("media.eme.apiVisible", true);
+
 // The default number of decoded video frames that are enqueued in
 // MediaDecoderReader's mVideoQueue.
 pref("media.video-queue.default-size", 3);
 
 // optimize images' memory usage
+pref("image.downscale-during-decode.enabled", true);
 pref("image.decode-only-on-draw.enabled", false);
 pref("image.mem.allow_locking_in_content_processes", true);
 // Limit the surface cache to 1/8 of main memory or 128MB, whichever is smaller.
 // Almost everything that was factored into 'max_decoded_image_kb' is now stored
 // in the surface cache.  1/8 of main memory is 32MB on a 256MB device, which is
 // about the same as the old 'max_decoded_image_kb'.
 pref("image.mem.surfacecache.max_size_kb", 131072);  // 128MB
 pref("image.mem.surfacecache.size_factor", 8);  // 1/8 of main memory
@@ -1121,8 +1127,16 @@ pref("dom.mozSettings.SettingsService.ve
 // readwrite.
 pref("dom.mozSettings.allowForceReadOnly", false);
 
 // RequestSync API is enabled by default on B2G.
 pref("dom.requestSync.enabled", true);
 
 // Resample touch events on b2g
 pref("gfx.touch.resample", true);
+
+// Comma separated list of activity names that can only be provided by
+// the system app in dev mode.
+pref("dom.activities.developer_mode_only", "import-app");
+
+// mulet apparently loads firefox.js as well as b2g.js, so we have to explicitly
+// disable serviceworkers here to get them disabled in mulet.
+pref("dom.serviceWorkers.enabled", false);
deleted file mode 100644
--- a/b2g/branding/official/android-resources.mn
+++ /dev/null
@@ -1,1 +0,0 @@
-b2g/branding/official/content/splash.png
deleted file mode 100644
--- a/b2g/branding/unofficial/android-resources.mn
+++ /dev/null
@@ -1,1 +0,0 @@
-b2g/branding/unofficial/content/splash.png
--- a/b2g/chrome/content/settings.js
+++ b/b2g/chrome/content/settings.js
@@ -560,16 +560,17 @@ let settingsToObserve = {
   'layers.enable-tiles': true,
   'layers.effect.invert': false,
   'layers.effect.grayscale': false,
   'layers.effect.contrast': "0.0",
   'network.debugging.enabled': false,
   'privacy.donottrackheader.enabled': false,
   'ril.debugging.enabled': false,
   'ril.radio.disabled': false,
+  'mms.debugging.enabled': false,
   'ril.mms.requestReadReport.enabled': {
     prefName: 'dom.mms.requestReadReport',
     defaultValue: true
   },
   'ril.mms.requestStatusReport.enabled': {
     prefName: 'dom.mms.requestStatusReport',
     defaultValue: false
   },
--- a/b2g/chrome/content/shell.js
+++ b/b2g/chrome/content/shell.js
@@ -24,16 +24,17 @@ Cu.import('resource://gre/modules/Resour
 // Identity
 Cu.import('resource://gre/modules/SignInToWebsite.jsm');
 SignInToWebsiteController.init();
 
 Cu.import('resource://gre/modules/FxAccountsMgmtService.jsm');
 Cu.import('resource://gre/modules/DownloadsAPI.jsm');
 Cu.import('resource://gre/modules/MobileIdentityManager.jsm');
 Cu.import('resource://gre/modules/PresentationDeviceInfoManager.jsm');
+Cu.import('resource://gre/modules/AboutServiceWorkers.jsm');
 
 XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
                                   "resource://gre/modules/SystemAppProxy.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Screenshot",
                                   "resource://gre/modules/Screenshot.jsm");
 
 Cu.import('resource://gre/modules/Webapps.jsm');
new file mode 100644
--- /dev/null
+++ b/b2g/components/AboutServiceWorkers.jsm
@@ -0,0 +1,174 @@
+/* This Source Code Form is subject to the terms of the Mozilla Public
+ * License, v. 2.0. If a copy of the MPL was not distributed with this file,
+ * You can obtain one at http://mozilla.org/MPL/2.0/. */
+
+"use strict"
+
+this.EXPORTED_SYMBOLS = [];
+
+const { interfaces: Ci, utils: Cu } = Components;
+
+Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "SystemAppProxy",
+                                  "resource://gre/modules/SystemAppProxy.jsm");
+
+XPCOMUtils.defineLazyServiceGetter(this, "gServiceWorkerManager",
+                                  "@mozilla.org/serviceworkers/manager;1",
+                                  "nsIServiceWorkerManager");
+
+function debug(aMsg) {
+  //dump("AboutServiceWorkers - " + aMsg + "\n");
+}
+
+function serializeServiceWorkerInfo(aServiceWorkerInfo) {
+  if (!aServiceWorkerInfo) {
+    throw new Error("Invalid service worker information");
+  }
+
+  let result = {};
+
+  Object.keys(aServiceWorkerInfo).forEach(property => {
+    if (typeof aServiceWorkerInfo[property] == "function") {
+      return;
+    }
+    if (property === "principal") {
+      result.principal = {
+        origin: aServiceWorkerInfo.principal.origin,
+        appId: aServiceWorkerInfo.principal.appId,
+        isInBrowser: aServiceWorkerInfo.principal.isInBrowser
+      };
+      return;
+    }
+    result[property] = aServiceWorkerInfo[property];
+  });
+
+  return result;
+}
+
+function sendResult(aId, aResult) {
+  SystemAppProxy._sendCustomEvent("mozAboutServiceWorkersChromeEvent", {
+    id: aId,
+    result: aResult
+  });
+}
+
+function sendError(aId, aError) {
+  SystemAppProxy._sendCustomEvent("mozAboutServiceWorkersChromeEvent", {
+    id: aId,
+    error: aError
+  });
+}
+
+this.AboutServiceWorkers = {
+  get enabled() {
+    if (this._enabled) {
+      return this._enabled;
+    }
+    this._enabled = false;
+    try {
+      this._enabled = Services.prefs.getBoolPref("dom.serviceWorkers.enabled");
+    } catch(e) {}
+    return this._enabled;
+  },
+
+  init: function() {
+    SystemAppProxy.addEventListener("mozAboutServiceWorkersContentEvent",
+                                   AboutServiceWorkers);
+  },
+
+  handleEvent: function(aEvent) {
+    let message = aEvent.detail;
+
+    debug("Got content event " + JSON.stringify(message));
+
+    if (!message.id || !message.name) {
+      dump("Invalid event " + JSON.stringify(message) + "\n");
+      return;
+    }
+
+    switch(message.name) {
+      case "init":
+        if (!this.enabled) {
+          sendResult({
+            enabled: false,
+            registrations: []
+          });
+          return;
+        };
+
+        let data = gServiceWorkerManager.getAllRegistrations();
+        if (!data) {
+          sendError(message.id, "NoServiceWorkersRegistrations");
+          return;
+        }
+
+        let registrations = [];
+
+        for (let i = 0; i < data.length; i++) {
+          let info = data.queryElementAt(i, Ci.nsIServiceWorkerInfo);
+          if (!info) {
+            dump("AboutServiceWorkers: Invalid nsIServiceWorkerInfo " +
+                 "interface.\n");
+            continue;
+          }
+          registrations.push(serializeServiceWorkerInfo(info));
+        }
+
+        sendResult(message.id, {
+          enabled: this.enabled,
+          registrations: registrations
+        });
+        break;
+
+      case "update":
+        if (!message.scope) {
+          sendError(message.id, "MissingScope");
+          return;
+        }
+        gServiceWorkerManager.update(message.scope);
+        sendResult(message.id, true);
+        break;
+
+      case "unregister":
+        if (!message.principal ||
+            !message.principal.origin ||
+            !message.principal.appId) {
+          sendError("MissingPrincipal");
+          return;
+        }
+
+        let principal = Services.scriptSecurityManager.getAppCodebasePrincipal(
+          Services.io.newURI(message.principal.origin, null, null),
+          message.principal.appId,
+          message.principal.isInBrowser
+        );
+
+        if (!message.scope) {
+          sendError("MissingScope");
+          return;
+        }
+
+        let serviceWorkerUnregisterCallback = {
+          unregisterSucceeded: function() {
+            sendResult(message.id, true);
+          },
+
+          unregisterFailed: function() {
+            sendError(message.id, "UnregisterError");
+          },
+
+          QueryInterface: XPCOMUtils.generateQI([
+            Ci.nsIServiceWorkerUnregisterCallback
+          ])
+        };
+        gServiceWorkerManager.unregister(principal,
+                                         serviceWorkerUnregisterCallback,
+                                         message.scope);
+        break;
+    }
+  }
+};
+
+AboutServiceWorkers.init();
--- a/b2g/components/ProcessGlobal.js
+++ b/b2g/components/ProcessGlobal.js
@@ -99,16 +99,20 @@ ProcessGlobal.prototype = {
     lines.forEach((line) => {
       log(line);
       let params = line.split(" ");
       if (params[0] == "wipe") {
         this.wipeDir(params[1]);
       } else if (params[0] == "root") {
         log("unrestrict devtools");
         Services.prefs.setBoolPref("devtools.debugger.forbid-certified-apps", false);
+        Services.prefs.setBoolPref("dom.apps.developer_mode", true);
+        // TODO: Remove once bug 1125916 is fixed.
+        Services.prefs.setBoolPref("network.disable.ipc.security", true);
+        Services.prefs.setBoolPref("dom.webcomponents.enabled", true);
         let lock = settings.createLock();
         lock.set("developer.menu.enabled", true, null);
       }
     });
   },
 
   cleanupAfterFactoryReset: function() {
     log("cleanupAfterWipe start");
--- a/b2g/components/moz.build
+++ b/b2g/components/moz.build
@@ -44,16 +44,17 @@ EXTRA_PP_COMPONENTS += [
 ]
 
 if CONFIG['MOZ_UPDATER']:
     EXTRA_PP_COMPONENTS += [
         'UpdatePrompt.js',
     ]
 
 EXTRA_JS_MODULES += [
+    'AboutServiceWorkers.jsm',
     'AlertsHelper.jsm',
     'Bootstraper.jsm',
     'ContentRequestHelper.jsm',
     'DebuggerActors.js',
     'ErrorPage.jsm',
     'Frames.jsm',
     'FxAccountsMgmtService.jsm',
     'LogCapture.jsm',
--- a/b2g/config/dolphin/sources.xml
+++ b/b2g/config/dolphin/sources.xml
@@ -7,28 +7,28 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
+  <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b4c949cdc780893897c9b45c1adea46e2eb694ff"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="90f848a40efad820ab00fa52bec52dff37255b12"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="83760d213fb3bec7b4117d266fcfbf6fe2ba14ab"/>
   <project name="device/common" path="device/common" revision="6a2995683de147791e516aae2ccb31fdfbe2ad30"/>
@@ -105,17 +105,17 @@
   <project name="platform/frameworks/native" path="frameworks/native" revision="8d54940d9bdad8fec3208ff58ddab590be9fe0d4"/>
   <project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="dbbe673145107e99883f62bafd70c5f43f11065c"/>
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="aac6c4bb59a6577c97cbda68699829b507b7490d"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="fbeca55f4695dd07c0291213403533b8fbca4885"/>
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="92605aa35361ae4ae1e473781e40c1f6929f4ec4"/>
   <project name="platform/libcore" path="libcore" revision="e195beab082c09217318fc19250caeaf4c1bd800"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="feeb36c2bd4adfe285f98f5de92e0f3771b2c115"/>
   <project name="platform/ndk" path="ndk" revision="e58ef003be4306bb53a8c11331146f39e4eab31f"/>
-  <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="0e7c060db684b409616fe67ea433ef19f5634c60"/>
+  <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="23404f05422c6bf3c39573325a4f4909167671b4"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="c792f0bd9fff7aea2887c60bbb3a9bbdb534ffa3"/>
   <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="cfcef469537869947abb9aa1d656774cc2678d4c"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
   <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="48d2332e6d8400cdc0de273ceff2abe8aaababf8"/>
   <project name="platform/system/extras" path="system/extras" revision="10e78a05252b3de785f88c2d0b9ea8a428009c50"/>
   <project name="platform/system/media" path="system/media" revision="7ff72c2ea2496fa50b5e8a915e56e901c3ccd240"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3c5405863d2002f665ef2b901abb3853c420129b"/>
@@ -129,16 +129,16 @@
   <project name="platform/external/icu4c" path="external/icu4c" revision="2bb01561780583cc37bc667f0ea79f48a122d8a2"/>
   <!-- dolphin specific things -->
   <project name="device/sprd" path="device/sprd" revision="a26ba0ab998133ad590102be1e5950818b86ce82"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="39a5b5bcadad745df3e6882316fce426f98b1669"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="8bb69db127112fc66da75f8ca7a1158614b919f6"/>
   <project name="platform/hardware/akm" path="hardware/akm" revision="6d3be412647b0eab0adff8a2768736cf4eb68039"/>
   <project groups="invensense" name="platform/hardware/invensense" path="hardware/invensense" revision="e6d9ab28b4f4e7684f6c07874ee819c9ea0002a2"/>
   <project name="platform/hardware/ril" path="hardware/ril" revision="865ce3b4a2ba0b3a31421ca671f4d6c5595f8690"/>
-  <project name="kernel/common" path="kernel" revision="65d2a18bd4ab0f1ed36a76c1e3c4f9ae98f345b9"/>
+  <project name="kernel/common" path="kernel" revision="8696b132455224412a6725022acf672be80a0641"/>
   <project name="platform/system/core" path="system/core" revision="7992618bd4ee33ce96897675a5c0a9b619122f13"/>
   <project name="u-boot" path="u-boot" revision="f1502910977ac88f43da7bf9277c3523ad4b0b2f"/>
-  <project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="4c59900937dc2e978b7b14b7f1ea617e3d5d550e"/>
+  <project name="vendor/sprd/gps" path="vendor/sprd/gps" revision="7d6e1269be7186b2073fa568958b357826692c4b"/>
   <project name="vendor/sprd/open-source" path="vendor/sprd/open-source" revision="e503b1d14d7fdee532b8f391407299da193c1b2d"/>
   <project name="vendor/sprd/partner" path="vendor/sprd/partner" revision="8649c7145972251af11b0639997edfecabfc7c2e"/>
   <project name="vendor/sprd/proprietories" path="vendor/sprd/proprietories" revision="d2466593022f7078aaaf69026adf3367c2adb7bb"/>
 </manifest>
--- a/b2g/config/emulator-ics/sources.xml
+++ b/b2g/config/emulator-ics/sources.xml
@@ -14,21 +14,21 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b4c949cdc780893897c9b45c1adea46e2eb694ff"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="46e1877c0d88b085f7ebc5f432d5bb8f1e2d1f3b"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8c2d32bccc7061e9ca0165135457c3fd53e7107e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- a/b2g/config/emulator-jb/sources.xml
+++ b/b2g/config/emulator-jb/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b4c949cdc780893897c9b45c1adea46e2eb694ff"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="90f848a40efad820ab00fa52bec52dff37255b12"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/emulator-kk/sources.xml
+++ b/b2g/config/emulator-kk/sources.xml
@@ -7,28 +7,28 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
+  <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b4c949cdc780893897c9b45c1adea46e2eb694ff"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="90f848a40efad820ab00fa52bec52dff37255b12"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="f92a936f2aa97526d4593386754bdbf02db07a12"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="6e47ff2790f5656b5b074407829ceecf3e6188c4"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="1950e4760fa14688b83cdbb5acaa1af9f82ef434"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="ac6eb97a37035c09fb5ede0852f0881e9aadf9ad"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="737f591c5f95477148d26602c7be56cbea0cdeb9"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="51da9b1981be481b92a59a826d4d78dc73d0989a"/>
   <project name="device/common" path="device/common" revision="798a3664597e6041985feab9aef42e98d458bc3d"/>
@@ -105,17 +105,17 @@
   <project name="platform/frameworks/native" path="frameworks/native" revision="2176649bcda07ff82ba6e83f3b5ee8b80f2c5cb1"/>
   <project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="7a2d17bd2190556c9c804721ad7b19d45948bb1f"/>
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="eb6077f10ae6255a72337124188f0e08dcd10e3e"/>
   <project name="platform/hardware/libhardware" path="hardware/libhardware" revision="3b80c725cea54132df05d208930d91e00d19f999"/>
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="01f436c51dc68aec7cc1c85fda6e6792b2a95066"/>
   <project name="platform/libcore" path="libcore" revision="9877ade9617bb0db6e59aa2a54719a9bc92600f3"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="46c96ace65eb1ccab05bf15b9bf8e53e443039af"/>
   <project name="platform/ndk" path="ndk" revision="cb5519af32ae7b4a9c334913a612462ecd04c5d0"/>
-  <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="0e7c060db684b409616fe67ea433ef19f5634c60"/>
+  <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="23404f05422c6bf3c39573325a4f4909167671b4"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="6aa61f8557a22039a30b42b7f283996381fd625d"/>
   <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="b562b01c93de9578d5db537b6a602a38e1aaa0ce"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="387f03e815f57d536dd922706db1622bddba8d81"/>
   <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="48d2332e6d8400cdc0de273ceff2abe8aaababf8"/>
   <project name="platform/system/extras" path="system/extras" revision="5356165f67f4a81c2ef28671c13697f1657590df"/>
   <project name="platform/system/media" path="system/media" revision="be0e2fe59a8043fa5200f75697df9220a99abe9d"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3c5405863d2002f665ef2b901abb3853c420129b"/>
@@ -123,16 +123,16 @@
   <project name="platform/system/security" path="system/security" revision="583374f69f531ba68fc3dcbff1f74893d2a96406"/>
   <project name="platform/system/vold" path="system/vold" revision="d4455b8cf361f8353e8aebac15ffd64b4aedd2b9"/>
   <project name="platform/external/icu4c" path="external/icu4c" remote="aosp" revision="b4c6379528887dc25ca9991a535a8d92a61ad6b6"/>
   <project name="platform_frameworks_av" path="frameworks/av" remote="b2g" revision="f3cedd7fd9b1649aa5107d466be9078bb7602af6"/>
   <project name="platform_system_core" path="system/core" remote="b2g" revision="9395eb5aa885cf6d305a202de6e9694a58a89717"/>
   <default remote="caf" revision="refs/tags/android-4.4.2_r1" sync-j="4"/>
   <!-- Emulator specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="72ffdf71c68a96309212eb13d63560d66db14c9e"/>
-  <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="f5f7fa2fc26b96d2cbd0af4569c0036fe034bb43"/>
+  <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="0c967fc587b614ffe391eb24e0b7f9f3bc31147b"/>
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="fbd2becab3825c49e756db5149552f85049c66e2"/>
-  <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="694cecf256122d0cb3b6a1a4efb4b5c7401db223"/>
+  <project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="9a725b0f5aa715282f8854ac56e5b63efc9cd077"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="0c2ffe181ca64a6cad9c5f93ddea623f080c6434"/>
   <project name="platform/development" path="development" revision="5968ff4e13e0d696ad8d972281fc27ae5a12829b"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="0951179277915335251c5e11d242e4e1a8c2236f"/>
   <project name="darwinstreamingserver" path="system/darwinstreamingserver" remote="b2g" revision="cf85968c7f85e0ec36e72c87ceb4837a943b8af6"/>
 </manifest>
--- a/b2g/config/emulator-l/sources.xml
+++ b/b2g/config/emulator-l/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b4c949cdc780893897c9b45c1adea46e2eb694ff"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="90f848a40efad820ab00fa52bec52dff37255b12"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <!-- Stock Android things -->
   <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" revision="8af5ff6f5dced9eb5a8127459df6c75d24342204"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="30915518fa7ea07166efedc191a4f40aef516fe7"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" revision="96eee58e3389fb05a835310d6a06a6ba4486097a"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" revision="7c8a46698171aa2e0be09edb43d15a6acf832770"/>
   <project groups="pdk,linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" path="prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" revision="24b2038be8a636fd4a5d21f0abae1e466b07bcf7"/>
@@ -139,14 +139,14 @@
   <project name="platform_frameworks_wilhelm" path="frameworks/wilhelm" remote="b2g" revision="0dbf5baafadf6d233c0a29e392fa3293f0121673"/>
   <project name="platform_system_core" path="system/core" remote="b2g" revision="f594bc64eacac490857748b1139ffcb34c856bbd"/>
   <default remote="caf" revision="refs/tags/android-5.1.0_r1" sync-j="4"/>
   <!-- Emulator specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="fe7df1bc8dd0fd71571505d7be1c31a4ad1e40fb"/>
   <project name="device_generic_goldfish" path="device/generic/goldfish" remote="b2g" revision="48132ec0b0dfe9fc29c7c3f0e799066be8999198"/>
   <!-- external/qemu for emulator-l need to be updated in bug-1121378 -->
   <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="7639c5c496ffd207bb627f2a59b2c5203ae6fefc"/>
-  <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="c15b6e266136cd0cdd9b94d0bbed1962d9dd6672"/>
+  <project name="platform_external_wpa_supplicant_8" path="external/wpa_supplicant_8" remote="b2g" revision="326450198720862ade868801cc2f43597f3c1fd8"/>
   <project name="platform/development" path="development" revision="0c51f6e0aa2ee57fcb75ec3b2ff6bf754cece63e"/>
   <project name="android-sdk" path="sdk" remote="b2g" revision="ff4190dc603f62a7caa48342aa268acf99863c5c"/>
   <!-- hardware-ril for emulator-l need to be updated in bug-1113054 -->
   <project name="platform/hardware/ril" path="hardware/ril" revision="e00d716e7e3d31729f75399855b6921e90cb0b66"/>
 </manifest>
--- a/b2g/config/emulator/sources.xml
+++ b/b2g/config/emulator/sources.xml
@@ -14,21 +14,21 @@
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <default remote="caf" revision="refs/tags/android-4.0.4_r2.1" sync-j="4"/>
   <!-- Gonk specific things and forks -->
   <project name="platform_build" path="build" remote="b2g" revision="173b3104bfcbd23fc9dccd4b0035fc49aae3d444">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="fake-dalvik" path="dalvik" remote="b2g" revision="ca1f327d5acc198bb4be62fa51db2c039032c9ce"/>
-  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="b4c949cdc780893897c9b45c1adea46e2eb694ff"/>
+  <project name="gaia.git" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="platform_hardware_ril" path="hardware/ril" remote="b2g" revision="9a9797062c6001d6346504161c51187a2968466b"/>
-  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="46e1877c0d88b085f7ebc5f432d5bb8f1e2d1f3b"/>
+  <project name="platform_external_qemu" path="external/qemu" remote="b2g" revision="8c2d32bccc7061e9ca0165135457c3fd53e7107e"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="apitrace" path="external/apitrace" remote="apitrace" revision="34ea6163f9f0e0122fb0bb03607eccdca31ced7a"/>
   <!-- Stock Android things -->
   <project name="platform/abi/cpp" path="abi/cpp" revision="dd924f92906085b831bf1cbbc7484d3c043d613c"/>
   <project name="platform_bionic" path="bionic" remote="b2g" revision="e2b3733ba3fa5e3f404e983d2e4142b1f6b1b846"/>
   <project name="platform/bootable/recovery" path="bootable/recovery" revision="425f8b5fadf5889834c5acd27d23c9e0b2129c28"/>
   <project name="device/common" path="device/common" revision="42b808b7e93d0619286ae8e59110b176b7732389"/>
   <project name="device/sample" path="device/sample" revision="237bd668d0f114d801a8d6455ef5e02cc3577587"/>
--- a/b2g/config/flame-kk/sources.xml
+++ b/b2g/config/flame-kk/sources.xml
@@ -7,28 +7,28 @@
   <remote fetch="https://git.mozilla.org/b2g" name="mozilla"/>
   <!--original fetch url was git://github.com/apitrace/-->
   <remote fetch="https://git.mozilla.org/external/apitrace" name="apitrace"/>
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
-  <project name="platform_build" path="build" remote="b2g" revision="ef937d1aca7c4cf89ecb5cc43ae8c21c2000a9db">
+  <project name="platform_build" path="build" remote="b2g" revision="2eda36a4795012a5d1275b77ebb20ac377c8cd26">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b4c949cdc780893897c9b45c1adea46e2eb694ff"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="90f848a40efad820ab00fa52bec52dff37255b12"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.7" revision="a1e239a0bb5cd1d69680bf1075883aa9a7bf2429"/>
   <project groups="linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" path="prebuilts/gcc/linux-x86/x86/i686-linux-android-4.7" revision="c7931763d41be602407ed9d71e2c0292c6597e00"/>
   <project groups="linux,x86" name="platform/prebuilts/python/linux-x86/2.7.5" path="prebuilts/python/linux-x86/2.7.5" revision="a32003194f707f66a2d8cdb913ed1869f1926c5d"/>
   <project name="device/common" path="device/common" revision="96d4d2006c4fcb2f19a3fa47ab10cb409faa017b"/>
@@ -99,17 +99,17 @@
   <project name="platform/external/webrtc" path="external/webrtc" revision="446452f84e9cc4c75d8e80f6f05e24793397a19d"/>
   <project name="platform/external/yaffs2" path="external/yaffs2" revision="a2cff2275e1b501ff478b03757d6e4f05fddc2db"/>
   <project name="platform/external/zlib" path="external/zlib" revision="6eb3570ff8fa71bd83bb375b4bf09804c6089fed"/>
   <project name="platform/frameworks/opt/emoji" path="frameworks/opt/emoji" revision="dbbe673145107e99883f62bafd70c5f43f11065c"/>
   <project name="platform/frameworks/wilhelm" path="frameworks/wilhelm" revision="f0c3b4edf597c40aae4ea311575f39c8bcf203df"/>
   <project name="platform/libcore" path="libcore" revision="baf7d8068dd501cfa338d3a8b1b87216d6ce0571"/>
   <project name="platform/libnativehelper" path="libnativehelper" revision="50c4430e32849530ced32680fd6ee98963b3f7ac"/>
   <project name="platform/ndk" path="ndk" revision="e58ef003be4306bb53a8c11331146f39e4eab31f"/>
-  <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="0e7c060db684b409616fe67ea433ef19f5634c60"/>
+  <project name="platform_prebuilts_misc" path="prebuilts/misc" remote="b2g" revision="23404f05422c6bf3c39573325a4f4909167671b4"/>
   <project name="platform/prebuilts/ndk" path="prebuilts/ndk" revision="c792f0bd9fff7aea2887c60bbb3a9bbdb534ffa3"/>
   <project name="platform_prebuilts_qemu-kernel" path="prebuilts/qemu-kernel" remote="b2g" revision="f7d9bf71cf6693474f3f2a81a4ba62c0fc5646aa"/>
   <project name="platform/prebuilts/sdk" path="prebuilts/sdk" revision="69d524e80cdf3981006627c65ac85f3a871238a3"/>
   <project name="platform/prebuilts/tools" path="prebuilts/tools" revision="5a48c04c4bb5f079bc757e29864a42427378e051"/>
   <project name="platform_system_bluetoothd" path="system/bluetoothd" remote="b2g" revision="48d2332e6d8400cdc0de273ceff2abe8aaababf8"/>
   <project name="platform/system/extras" path="system/extras" revision="576f57b6510de59c08568b53c0fb60588be8689e"/>
   <project name="platform_system_libfdio" path="system/libfdio" remote="b2g" revision="3c5405863d2002f665ef2b901abb3853c420129b"/>
   <project name="platform/system/netd" path="system/netd" revision="a6531f7befb49b1c81bc0de7e51c5482b308e1c5"/>
@@ -120,17 +120,17 @@
   <project name="platform/hardware/libhardware_legacy" path="hardware/libhardware_legacy" revision="76c4bf4bc430a1b8317f2f21ef735867733e50cc"/>
   <project name="platform/system/media" path="system/media" revision="c1332c21c608f4932a6d7e83450411cde53315ef"/>
   <!--original fetch url was git://github.com/t2m-foxfone/-->
   <remote fetch="https://git.mozilla.org/external/t2m-foxfone" name="t2m"/>
   <default remote="caf" revision="LNX.LA.3.5.2.1.1" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="1bb28abbc215f45220620af5cd60a8ac1be93722"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="2501e5940ba69ece7654ff85611c76ae5bda299c"/>
-  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="b83fc73de7b64594cd74b33e498bf08332b5d87b"/>
+  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="a9f3f8fb8b0844724de32426b7bcc4e6dc4fa2ed"/>
   <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="0865bc4134b67220df4058625fba29305d6b10c3"/>
   <project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="fda40423ffa573dc6cafd3780515010cb2a086be"/>
   <project name="platform_bootable_recovery" path="bootable/recovery" remote="b2g" revision="d5e53ed6f22fa06052351dc03510af9473af01ea"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="d61fc97258c8b0c362430dd2eb195dcc4d266f14"/>
   <project name="platform/external/wpa_supplicant_8" path="external/wpa_supplicant_8" revision="5b71e40213f650459e95d35b6f14af7e88d8ab62"/>
   <project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
   <project name="platform_external_libnfc-pn547" path="external/libnfc-pn547" remote="b2g" revision="5bb999b84b8adc14f6bea004d523ba258dea8188"/>
   <project name="platform/frameworks/av" path="frameworks/av" revision="65f5144987afff35a932262c0c5fad6ecce0c04a"/>
--- a/b2g/config/flame/sources.xml
+++ b/b2g/config/flame/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b4c949cdc780893897c9b45c1adea46e2eb694ff"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="90f848a40efad820ab00fa52bec52dff37255b12"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="e95b4ce22c825da44d14299e1190ea39a5260bde"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="471afab478649078ad7c75ec6b252481a59e19b8"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="95bb5b66b3ec5769c3de8d3f25d681787418e7d2"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="ebdad82e61c16772f6cd47e9f11936bf6ebe9aa0"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="8b880805d454664b3eed11d0f053cdeafa1ff06e"/>
@@ -116,17 +116,17 @@
   <project name="platform/system/security" path="system/security" revision="360f51f7af191316cd739f229db1c5f7233be063"/>
   <project name="platform/system/vold" path="system/vold" revision="153df4d067a4149c7d78f1c92fed2ce2bd6a272e"/>
   <!--original fetch url was git://github.com/t2m-foxfone/-->
   <remote fetch="https://git.mozilla.org/external/t2m-foxfone" name="t2m"/>
   <default remote="caf" revision="jb_3.2" sync-j="4"/>
   <!-- Flame specific things -->
   <project name="device/generic/armv7-a-neon" path="device/generic/armv7-a-neon" revision="e8a318f7690092e639ba88891606f4183e846d3f"/>
   <project name="device/qcom/common" path="device/qcom/common" revision="878804e0becfe5635bb8ccbf2671333d546c6fb6"/>
-  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="f54de260816110dca21bc9e76e4c4a09a950f232"/>
+  <project name="device-flame" path="device/t2m/flame" remote="b2g" revision="2f0c2790b0ab42bb2f0061f8977d88a46167e029"/>
   <project name="codeaurora_kernel_msm" path="kernel" remote="b2g" revision="49417cfc622074daa3c76b345a199f6731375800"/>
   <project name="kernel_lk" path="bootable/bootloader/lk" remote="b2g" revision="6f00133ac0f47e90027bd7e263a16b405bfac503"/>
   <project name="platform_bootable_recovery" path="bootable/recovery" remote="b2g" revision="e81502511cda303c803e63f049574634bc96f9f2"/>
   <project name="platform/external/bluetooth/bluedroid" path="external/bluetooth/bluedroid" revision="81c4a859d75d413ad688067829d21b7ba9205f81"/>
   <project name="platform/external/bluetooth/bluez" path="external/bluetooth/bluez" revision="f0689ac1914cdbc59e53bdc9edd9013dc157c299"/>
   <project name="platform/external/bluetooth/glib" path="external/bluetooth/glib" revision="dd925f76e4f149c3d5571b80e12f7e24bbe89c59"/>
   <project name="platform/external/dbus" path="external/dbus" revision="ea87119c843116340f5df1d94eaf8275e1055ae8"/>
   <project name="platform_external_libnfc-nci" path="external/libnfc-nci" remote="t2m" revision="4186bdecb4dae911b39a8202252cc2310d91b0be"/>
--- a/b2g/config/gaia.json
+++ b/b2g/config/gaia.json
@@ -1,9 +1,9 @@
 {
     "git": {
-        "git_revision": "b4c949cdc780893897c9b45c1adea46e2eb694ff", 
+        "git_revision": "bc5bfa18f795919b56b952bbf3637c235d0e13dc", 
         "remote": "https://git.mozilla.org/releases/gaia.git", 
         "branch": ""
     }, 
-    "revision": "70ab08a2dadc6cf89a4d9579c3696517faf807b8", 
+    "revision": "12e33f70aeccca27a275b3fa172876a07b891fe8", 
     "repo_path": "integration/gaia-central"
 }
--- a/b2g/config/nexus-4/sources.xml
+++ b/b2g/config/nexus-4/sources.xml
@@ -12,20 +12,20 @@
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="4efd19d199ae52656604f794c5a77518400220fd">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b4c949cdc780893897c9b45c1adea46e2eb694ff"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="90f848a40efad820ab00fa52bec52dff37255b12"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
   <!-- Stock Android things -->
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.1" path="prebuilts/clang/linux-x86/3.1" revision="5c45f43419d5582949284eee9cef0c43d866e03b"/>
   <project groups="linux" name="platform/prebuilts/clang/linux-x86/3.2" path="prebuilts/clang/linux-x86/3.2" revision="3748b4168e7bd8d46457d4b6786003bc6a5223ce"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/i686-linux-glibc2.7-4.6" revision="9025e50b9d29b3cabbbb21e1dd94d0d13121a17e"/>
   <project groups="linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.7-4.6" revision="b89fda71fcd0fa0cf969310e75be3ea33e048b44"/>
   <project groups="linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.7" revision="2e7d5348f35575870b3c7e567a9a9f6d66f8d6c5"/>
--- a/b2g/config/nexus-5-l/sources.xml
+++ b/b2g/config/nexus-5-l/sources.xml
@@ -10,25 +10,25 @@
   <!--original fetch url was git://codeaurora.org/-->
   <remote fetch="https://git.mozilla.org/external/caf" name="caf"/>
   <!--original fetch url was https://git.mozilla.org/releases-->
   <remote fetch="https://git.mozilla.org/releases" name="mozillaorg"/>
   <!-- B2G specific things. -->
   <project name="platform_build" path="build" remote="b2g" revision="61e82f99bb8bc78d52b5717e9a2481ec7267fa33">
     <copyfile dest="Makefile" src="core/root.mk"/>
   </project>
-  <project name="gaia" path="gaia" remote="mozillaorg" revision="b4c949cdc780893897c9b45c1adea46e2eb694ff"/>
+  <project name="gaia" path="gaia" remote="mozillaorg" revision="bc5bfa18f795919b56b952bbf3637c235d0e13dc"/>
   <project name="fake-libdvm" path="dalvik" remote="b2g" revision="d50ae982b19f42f0b66d08b9eb306be81687869f"/>
   <project name="gonk-misc" path="gonk-misc" remote="b2g" revision="d3868ff4bb3a4b81382795e2784258c210fe6cb8"/>
   <project name="librecovery" path="librecovery" remote="b2g" revision="1b3591a50ed352fc6ddb77462b7b35d0bfa555a3"/>
   <project name="moztt" path="external/moztt" remote="b2g" revision="adb24954bf8068f21705b570450475d183336b2d"/>
   <project name="rilproxy" path="rilproxy" remote="b2g" revision="5ef30994f4778b4052e58a4383dbe7890048c87e"/>
   <project name="valgrind" path="external/valgrind" remote="b2g" revision="daa61633c32b9606f58799a3186395fd2bbb8d8c"/>
   <project name="vex" path="external/VEX" remote="b2g" revision="47f031c320888fe9f3e656602588565b52d43010"/>
-  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="90f848a40efad820ab00fa52bec52dff37255b12"/>
+  <project name="apitrace" path="external/apitrace" remote="apitrace" revision="0627790166dccd8dd370fa7d9f434ed9fc027fb4"/>
   <!-- Stock Android things -->
   <project groups="pdk,linux" name="platform/prebuilts/clang/linux-x86/host/3.5" path="prebuilts/clang/linux-x86/host/3.5" revision="ffc05a232799fe8fcb3e47b7440b52b1fb4244c0"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" path="prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.8" revision="337e0ef5e40f02a1ae59b90db0548976c70a7226"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-eabi-4.8" revision="8af5ff6f5dced9eb5a8127459df6c75d24342204"/>
   <project groups="pdk,linux,arm" name="platform/prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" path="prebuilts/gcc/linux-x86/arm/arm-linux-androideabi-4.8" revision="30915518fa7ea07166efedc191a4f40aef516fe7"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.6" revision="96eee58e3389fb05a835310d6a06a6ba4486097a"/>
   <project groups="pdk,linux" name="platform/prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" path="prebuilts/gcc/linux-x86/host/x86_64-linux-glibc2.11-4.8" revision="7c8a46698171aa2e0be09edb43d15a6acf832770"/>
   <project groups="pdk,linux,x86" name="platform/prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" path="prebuilts/gcc/linux-x86/x86/x86_64-linux-android-4.8" revision="24b2038be8a636fd4a5d21f0abae1e466b07bcf7"/>
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -738,17 +738,16 @@
 ; All the pref files must be part of base to prevent migration bugs
 #ifdef MOZ_MULET
 @RESPATH@/browser/@PREF_DIR@/b2g.js
 #else
 @RESPATH@/@PREF_DIR@/b2g.js
 #endif
 @RESPATH@/@PREF_DIR@/channel-prefs.js
 @RESPATH@/greprefs.js
-@RESPATH@/defaults/autoconfig/platform.js
 @RESPATH@/defaults/autoconfig/prefcalls.js
 @RESPATH@/defaults/profile/prefs.js
 
 ; Services (gre) prefs
 #ifdef MOZ_SERVICES_SYNC
 @RESPATH@/defaults/pref/services-sync.js
 #endif
 
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -64,16 +64,19 @@ pref("extensions.update.autoUpdateDefaul
 pref("extensions.hotfix.id", "firefox-hotfix@mozilla.org");
 pref("extensions.hotfix.cert.checkAttributes", true);
 pref("extensions.hotfix.certs.1.sha1Fingerprint", "91:53:98:0C:C1:86:DF:47:8F:35:22:9E:11:C9:A7:31:04:49:A1:AA");
 
 // Disable add-ons that are not installed by the user in all scopes by default.
 // See the SCOPE constants in AddonManager.jsm for values to use here.
 pref("extensions.autoDisableScopes", 15);
 
+// Don't require signed add-ons by default
+pref("xpinstall.signatures.required", false);
+
 // Dictionary download preference
 pref("browser.dictionaries.download.url", "https://addons.mozilla.org/%LOCALE%/firefox/dictionaries/");
 
 // At startup, should we check to see if the installation
 // date is older than some threshold
 pref("app.update.checkInstallTime", true);
 
 // The number of days a binary is permitted to be old without checking is defined in
@@ -602,17 +605,17 @@ pref("mousewheel.with_shift.action", 2);
 pref("mousewheel.with_meta.action", 1); // win key on Win, Super/Hyper on Linux
 #endif
 pref("mousewheel.with_control.action",3);
 pref("mousewheel.with_win.action", 1);
 
 pref("browser.xul.error_pages.enabled", true);
 pref("browser.xul.error_pages.expert_bad_cert", false);
 
-// Work Offline is best manually managed by the user.
+// If true, network link events will change the value of navigator.onLine
 pref("network.manage-offline-status", false);
 
 // We want to make sure mail URLs are handled externally...
 pref("network.protocol-handler.external.mailto", true); // for mail
 pref("network.protocol-handler.external.news", true);   // for news
 pref("network.protocol-handler.external.snews", true);  // for secure news
 pref("network.protocol-handler.external.nntp", true);   // also news
 #ifdef XP_WIN
@@ -1190,20 +1193,25 @@ pref("security.sandbox.windows.log", fal
 //     everything, but will definitely cause some functionality restrictions
 pref("dom.ipc.plugins.sandbox-level.default", 0);
 
 #if defined(MOZ_CONTENT_SANDBOX)
 // This controls the strength of the Windows content process sandbox for testing
 // purposes. This will require a restart.
 // On windows these levels are:
 // 0 - sandbox with USER_NON_ADMIN access token level
-// 1 - a more strict sandbox, which causes problems in specific areas
+// 1 - level 0 plus low integrity
 // 2 - a policy that we can reasonably call an effective sandbox
 // 3 - an equivalent basic policy to the Chromium renderer processes
+#if defined(NIGHTLY_BUILD)
+pref("security.sandbox.content.level", 1);
+#else
 pref("security.sandbox.content.level", 0);
+#endif
+
 
 #if defined(MOZ_STACKWALKING)
 // This controls the depth of stack trace that is logged when Windows sandbox
 // logging is turned on.  This is only currently available for the content
 // process because the only other sandbox (for GMP) has too strict a policy to
 // allow stack tracing.  This does not require a restart to take effect.
 pref("security.sandbox.windows.log.stackTraceDepth", 0);
 #endif
@@ -1314,38 +1322,37 @@ pref("services.sync.prefs.sync.security.
 pref("services.sync.prefs.sync.security.tls.version.max", true);
 pref("services.sync.prefs.sync.signon.rememberSignons", true);
 pref("services.sync.prefs.sync.spellchecker.dictionary", true);
 pref("services.sync.prefs.sync.xpinstall.whitelist.required", true);
 #endif
 
 // Developer edition preferences
 #ifdef MOZ_DEV_EDITION
-pref("lightweightThemes.selectedThemeID", "firefox-devedition@mozilla.org");
-pref("browser.devedition.theme.enabled", true);
+sticky_pref("lightweightThemes.selectedThemeID", "firefox-devedition@mozilla.org");
+sticky_pref("browser.devedition.theme.enabled", true);
 #endif
 
 // Developer edition promo preferences
 pref("devtools.devedition.promo.shown", false);
 pref("devtools.devedition.promo.url", "https://www.mozilla.org/firefox/developer/?utm_source=firefox-dev-tools&utm_medium=firefox-browser&utm_content=betadoorhanger");
 
 // Only potentially show in beta release
 #if MOZ_UPDATE_CHANNEL == beta
   pref("devtools.devedition.promo.enabled", true);
 #else
   pref("devtools.devedition.promo.enabled", false);
 #endif
 
 // Disable the error console
 pref("devtools.errorconsole.enabled", false);
 
-// Developer toolbar and GCLI preferences
+// Developer toolbar preferences
 pref("devtools.toolbar.enabled", true);
 pref("devtools.toolbar.visible", false);
-pref("devtools.commands.dir", "");
 
 // Enable the app manager
 pref("devtools.appmanager.enabled", true);
 pref("devtools.appmanager.lastTab", "help");
 pref("devtools.appmanager.manifestEditor.enabled", true);
 
 // Enable DevTools WebIDE by default
 pref("devtools.webide.enabled", true);
@@ -1420,24 +1427,34 @@ pref("devtools.debugger.ui.variables-sea
 
 // Enable the Performance tools
 pref("devtools.performance.enabled", true);
 
 // The default Performance UI settings
 pref("devtools.performance.memory.sample-probability", "0.05");
 pref("devtools.performance.memory.max-log-length", 2147483647); // Math.pow(2,31) - 1
 pref("devtools.performance.timeline.hidden-markers", "[]");
+pref("devtools.performance.profiler.buffer-size", 10000000);
+pref("devtools.performance.profiler.sample-frequency-khz", 1);
 pref("devtools.performance.ui.invert-call-tree", true);
 pref("devtools.performance.ui.invert-flame-graph", false);
 pref("devtools.performance.ui.flatten-tree-recursion", true);
 pref("devtools.performance.ui.show-platform-data", false);
 pref("devtools.performance.ui.show-idle-blocks", true);
 pref("devtools.performance.ui.enable-memory", false);
 pref("devtools.performance.ui.enable-framerate", true);
 pref("devtools.performance.ui.show-jit-optimizations", false);
+// If in aurora/dev edition (40.0, will revert for 40.1), set default
+// to retro mode.
+// TODO bug 1160313
+#ifdef MOZ_DEV_EDITION
+  pref("devtools.performance.ui.retro-mode", true);
+#else
+  pref("devtools.performance.ui.retro-mode", false);
+#endif
 
 // The default cache UI setting
 pref("devtools.cache.disabled", false);
 
 // The default service workers UI setting
 pref("devtools.serviceWorkers.testing.enabled", false);
 
 // Enable the Network Monitor
@@ -1492,32 +1509,21 @@ pref("devtools.canvasdebugger.enabled", 
 // Enable the Web Audio Editor
 pref("devtools.webaudioeditor.enabled", false);
 
 // Web Audio Editor Inspector Width should be a preference
 pref("devtools.webaudioeditor.inspectorWidth", 300);
 
 // Default theme ("dark" or "light")
 #ifdef MOZ_DEV_EDITION
-pref("devtools.theme", "dark");
+sticky_pref("devtools.theme", "dark");
 #else
-pref("devtools.theme", "light");
+sticky_pref("devtools.theme", "light");
 #endif
 
-// Display the introductory text
-pref("devtools.gcli.hideIntro", false);
-
-// How eager are we to show help: never=1, sometimes=2, always=3
-pref("devtools.gcli.eagerHelper", 2);
-
-// Alias to the script URLs for inject command.
-pref("devtools.gcli.jquerySrc", "https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js");
-pref("devtools.gcli.lodashSrc", "https://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.min.js");
-pref("devtools.gcli.underscoreSrc", "https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.7.0/underscore-min.js");
-
 // Remember the Web Console filters
 pref("devtools.webconsole.filter.network", true);
 pref("devtools.webconsole.filter.networkinfo", false);
 pref("devtools.webconsole.filter.netwarn", true);
 pref("devtools.webconsole.filter.netxhr", false);
 pref("devtools.webconsole.filter.csserror", true);
 pref("devtools.webconsole.filter.cssparser", false);
 pref("devtools.webconsole.filter.csslog", false);
@@ -1525,16 +1531,19 @@ pref("devtools.webconsole.filter.excepti
 pref("devtools.webconsole.filter.jswarn", true);
 pref("devtools.webconsole.filter.jslog", false);
 pref("devtools.webconsole.filter.error", true);
 pref("devtools.webconsole.filter.warn", true);
 pref("devtools.webconsole.filter.info", true);
 pref("devtools.webconsole.filter.log", true);
 pref("devtools.webconsole.filter.secerror", true);
 pref("devtools.webconsole.filter.secwarn", true);
+pref("devtools.webconsole.filter.serviceworkers", false);
+pref("devtools.webconsole.filter.sharedworkers", false);
+pref("devtools.webconsole.filter.windowlessworkers", false);
 
 // Remember the Browser Console filters
 pref("devtools.browserconsole.filter.network", true);
 pref("devtools.browserconsole.filter.networkinfo", false);
 pref("devtools.browserconsole.filter.netwarn", true);
 pref("devtools.browserconsole.filter.netxhr", false);
 pref("devtools.browserconsole.filter.csserror", true);
 pref("devtools.browserconsole.filter.cssparser", false);
@@ -1543,16 +1552,19 @@ pref("devtools.browserconsole.filter.exc
 pref("devtools.browserconsole.filter.jswarn", true);
 pref("devtools.browserconsole.filter.jslog", true);
 pref("devtools.browserconsole.filter.error", true);
 pref("devtools.browserconsole.filter.warn", true);
 pref("devtools.browserconsole.filter.info", true);
 pref("devtools.browserconsole.filter.log", true);
 pref("devtools.browserconsole.filter.secerror", true);
 pref("devtools.browserconsole.filter.secwarn", true);
+pref("devtools.browserconsole.filter.serviceworkers", true);
+pref("devtools.browserconsole.filter.sharedworkers", true);
+pref("devtools.browserconsole.filter.windowlessworkers", true);
 
 // Text size in the Web Console. Use 0 for the system default size.
 pref("devtools.webconsole.fontSize", 0);
 
 // Max number of inputs to store in web console history.
 pref("devtools.webconsole.inputHistoryCount", 50);
 
 // Persistent logging: |true| if you want the Web Console to keep all of the
@@ -1593,21 +1605,16 @@ pref("devtools.editor.autocomplete", tru
 // Enable the Font Inspector
 pref("devtools.fontinspector.enabled", true);
 
 // Pref to store the browser version at the time of a telemetry ping for an
 // opened developer tool. This allows us to ping telemetry just once per browser
 // version for each user.
 pref("devtools.telemetry.tools.opened.version", "{}");
 
-// Set imgur upload client ID
-pref("devtools.gcli.imgurClientID", '0df414e888d7240');
-// Imgur's upload URL
-pref("devtools.gcli.imgurUploadURL", "https://api.imgur.com/3/image");
-
 // Whether the character encoding menu is under the main Firefox button. This
 // preference is a string so that localizers can alter it.
 pref("browser.menu.showCharacterEncoding", "chrome://browser/locale/browser.properties");
 
 // Allow using tab-modal prompts when possible.
 pref("prompts.tab_modal.enabled", true);
 // Whether the Panorama should animate going in/out of tabs
 pref("browser.panorama.animate_zoom", true);
@@ -1625,20 +1632,20 @@ pref("browser.newtabpage.enabled", true)
 
 // number of rows of newtab grid
 pref("browser.newtabpage.rows", 3);
 
 // number of columns of newtab grid
 pref("browser.newtabpage.columns", 5);
 
 // directory tiles download URL
-pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v2/links/fetch/%LOCALE%");
+pref("browser.newtabpage.directory.source", "https://tiles.services.mozilla.com/v3/links/fetch/%LOCALE%/%CHANNEL%");
 
 // endpoint to send newtab click and view pings
-pref("browser.newtabpage.directory.ping", "https://tiles.services.mozilla.com/v2/links/");
+pref("browser.newtabpage.directory.ping", "https://tiles.services.mozilla.com/v3/links/");
 
 // Enable the DOM fullscreen API.
 pref("full-screen-api.enabled", true);
 
 // True if the fullscreen API requires approval upon a domain entering fullscreen.
 // Domains that have already had fullscreen permission granted won't re-request
 // approval.
 pref("full-screen-api.approval-required", true);
@@ -1707,17 +1714,17 @@ pref("loop.CSP", "default-src 'self' abo
 pref("loop.oauth.google.redirect_uri", "urn:ietf:wg:oauth:2.0:oob:auto");
 pref("loop.oauth.google.scope", "https://www.google.com/m8/feeds");
 pref("loop.fxa_oauth.tokendata", "");
 pref("loop.fxa_oauth.profile", "");
 pref("loop.support_url", "https://support.mozilla.org/kb/group-conversations-firefox-hello-webrtc");
 pref("loop.contacts.gravatars.show", false);
 pref("loop.contacts.gravatars.promo", true);
 pref("loop.browserSharing.showInfoBar", true);
-pref("loop.contextInConverations.enabled", false);
+pref("loop.contextInConversations.enabled", false);
 
 pref("social.sidebar.unload_timeout_ms", 10000);
 
 // activation from inside of share panel is possible if activationPanelEnabled
 // is true. Pref'd off for release while usage testing is done through beta.
 #ifdef EARLY_BETA_OR_EARLIER
 pref("social.share.activationPanelEnabled", true);
 #else
@@ -1778,16 +1785,19 @@ pref("identity.fxaccounts.remote.signup.
 
 // The URL where remote content that forces re-authentication for Firefox Accounts
 // should be fetched.  Must use HTTPS.
 pref("identity.fxaccounts.remote.force_auth.uri", "https://accounts.firefox.com/force_auth?service=sync&context=fx_desktop_v1");
 
 // The remote content URL shown for signin in. Must use HTTPS.
 pref("identity.fxaccounts.remote.signin.uri", "https://accounts.firefox.com/signin?service=sync&context=fx_desktop_v1");
 
+// The remote content URL where FxAccountsWebChannel messages originate.
+pref("identity.fxaccounts.remote.webchannel.uri", "https://accounts.firefox.com/");
+
 // The URL we take the user to when they opt to "manage" their Firefox Account.
 // Note that this will always need to be in the same TLD as the
 // "identity.fxaccounts.remote.signup.uri" pref.
 pref("identity.fxaccounts.settings.uri", "https://accounts.firefox.com/settings");
 
 // The remote URL of the FxA Profile Server
 pref("identity.fxaccounts.remote.profile.uri", "https://profile.accounts.firefox.com/v1");
 
@@ -1842,25 +1852,25 @@ pref("media.gmp-provider.enabled", true)
 
 pref("browser.apps.URL", "https://marketplace.firefox.com/discovery/");
 
 #ifdef NIGHTLY_BUILD
 pref("browser.polaris.enabled", false);
 pref("privacy.trackingprotection.ui.enabled", false);
 #endif
 
-#ifdef NIGHTLY_BUILD
+#ifdef E10S_TESTING_ONLY
 // At the moment, autostart.2 is used, while autostart.1 is unused.
 // We leave it here set to false to reset users' defaults and allow
 // us to change everybody to true in the future, when desired.
 pref("browser.tabs.remote.autostart.1", false);
 pref("browser.tabs.remote.autostart.2", true);
 #endif
 
-#ifdef NIGHTLY_BUILD
+#ifdef E10S_TESTING_ONLY
 // Enable e10s add-on interposition by default.
 pref("extensions.interposition.enabled", true);
 pref("extensions.interposition.prefetching", true);
 #endif
 
 pref("browser.defaultbrowser.notificationbar", false);
 
 // How often to check for CPOW timeouts. CPOWs are only timed out by
@@ -1879,15 +1889,23 @@ pref("dom.ipc.reportProcessHangs", false
 pref("dom.ipc.reportProcessHangs", true);
 #endif
 
 pref("browser.readinglist.enabled", false);
 pref("browser.readinglist.sidebarEverOpened", false);
 pref("readinglist.scheduler.enabled", false);
 pref("readinglist.server", "https://readinglist.services.mozilla.com/v1");
 
+pref("browser.reader.detectedFirstArticle", false);
 // Don't limit how many nodes we care about on desktop:
 pref("reader.parse-node-limit", 0);
 
 // Enable Service workers for desktop on non-release builds
 #ifdef NIGHTLY_BUILD
 pref("dom.serviceWorkers.enabled", true);
 #endif
+
+pref("browser.pocket.enabled", true);
+pref("browser.pocket.api", "api.getpocket.com");
+pref("browser.pocket.site", "getpocket.com");
+pref("browser.pocket.oAuthConsumerKey", "40249-e88c401e1b1f2242d9e441c4");
+pref("browser.pocket.useLocaleList", true);
+pref("browser.pocket.enabledLocales", "en-US");
--- a/browser/base/content/aboutNetError.xhtml
+++ b/browser/base/content/aboutNetError.xhtml
@@ -203,17 +203,17 @@
         }
 
         window.addEventListener("AboutNetErrorOptions", function(evt) {
         // Pinning errors are of type nssFailure2
           if (getErrorCode() == "nssFailure2") {
             var learnMoreLink = document.getElementById("learnMoreLink");
             // nssFailure2 also gets us other non-overrideable errors. Choose
             // a "learn more" link based on description:
-            if (getDescription().contains("mozilla_pkix_error_key_pinning_failure")) {
+            if (getDescription().includes("mozilla_pkix_error_key_pinning_failure")) {
               learnMoreLink.href = "https://support.mozilla.org/kb/certificate-pinning-reports";
             }
 
             var options = JSON.parse(evt.detail);
             if (options && options.enabled) {
               var checkbox = document.getElementById('automaticallyReportInFuture');
               showCertificateErrorReporting();
               if (options.automatic) {
@@ -459,28 +459,32 @@
 
       <!-- UI for option to report certificate errors to Mozilla. Removed on
            init for other error types .-->
       <div id="certificateErrorReporting">
         <a id="showCertificateErrorReportingPanel" href="#">&errorReporting.title;<span class="downArrow"> ▼</span></a>
       </div>
 
       <div id="certificateErrorReportingPanel">
-        <p>&errorReporting.longDesc;</p>
-        <p>
-          <input type="checkbox" id="automaticallyReportInFuture" />
-          <label for="automaticallyReportInFuture" id="automaticallyReportInFuture">&errorReporting.automatic;</label>
-        </p>
-        <a href="https://support.mozilla.org/kb/tls-error-reports" id="learnMoreLink" target="new">&errorReporting.learnMore;</a>
-        <span id="reportingState">
-          <button id="reportCertificateError">&errorReporting.report;</button>
-          <button id="reportCertificateErrorRetry">&errorReporting.tryAgain;</button>
-          <span id="reportSendingMessage">&errorReporting.sending;</span>
-          <span id="reportSentMessage">&errorReporting.sent;</span>
-        </span>
+        <div id="certificateErrorReportingDescription">
+          <p>&errorReporting.longDesc;</p>
+          <p>
+            <input type="checkbox" id="automaticallyReportInFuture" />
+            <label for="automaticallyReportInFuture" id="automaticallyReportInFuture">&errorReporting.automatic;</label>
+          </p>
+        </div>
+        <div id="errorStatePanel">
+          <a href="https://support.mozilla.org/kb/tls-error-reports" id="learnMoreLink" target="new">&errorReporting.learnMore;</a>
+          <span id="reportingState">
+            <button id="reportCertificateError">&errorReporting.report;</button>
+            <button id="reportCertificateErrorRetry">&errorReporting.tryAgain;</button>
+            <span id="reportSendingMessage">&errorReporting.sending;</span>
+            <span id="reportSentMessage">&errorReporting.sent;</span>
+          </span>
+        </div>
       </div>
 
     </div>
 
     <!--
     - Note: It is important to run the script this way, instead of using
     - an onload handler. This is because error pages are loaded as
     - LOAD_BACKGROUND, which means that onload handlers will not be executed.
--- a/browser/base/content/aboutaccounts/aboutaccounts.js
+++ b/browser/base/content/aboutaccounts/aboutaccounts.js
@@ -108,17 +108,17 @@ let wrapper = {
     let iframe = document.getElementById("remote");
     this.iframe = iframe;
     iframe.addEventListener("load", this);
 
     // Ideally we'd just merge urlParams with new URL(url).searchParams, but our
     // URLSearchParams implementation doesn't support iteration (bug 1085284).
     let urlParamStr = urlParams.toString();
     if (urlParamStr) {
-      url += (url.contains("?") ? "&" : "?") + urlParamStr;
+      url += (url.includes("?") ? "&" : "?") + urlParamStr;
     }
     iframe.src = url;
   },
 
   handleEvent: function (evt) {
     switch (evt.type) {
       case "load":
         this.iframe.contentWindow.addEventListener("FirefoxAccountsCommand", this);
--- a/browser/base/content/baseMenuOverlay.xul
+++ b/browser/base/content/baseMenuOverlay.xul
@@ -109,10 +109,11 @@
              key="&hideOtherAppsCmdMac.commandkey;"
              modifiers="accel,alt"/>
 #endif
     </keyset>
 
     <stringbundleset id="stringbundleset">
         <stringbundle id="bundle_browser" src="chrome://browser/locale/browser.properties"/>
         <stringbundle id="bundle_browser_region" src="chrome://browser-region/locale/region.properties"/>
+        <stringbundle id="bundle_pocket" src="chrome://browser/content/browser-pocket.properties"/>
     </stringbundleset>
 </overlay>
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -261,16 +261,20 @@
       <menuitem id="context-sharepage"
                 label="&sharePageCmd.label;"
                 accesskey="&sharePageCmd.accesskey;"
                 oncommand="SocialShare.sharePage();"/>
       <menuitem id="context-savepage"
                 label="&savePageCmd.label;"
                 accesskey="&savePageCmd.accesskey2;"
                 oncommand="gContextMenu.savePageAs();"/>
+      <menuitem id="context-pocket"
+                label="&saveToPocketCmd.label;"
+                accesskey="&saveToPocketCmd.accesskey;"
+                oncommand="gContextMenu.saveToPocket();"/>
       <menu id="context-markpageMenu" label="&social.markpageMenu.label;"
             accesskey="&social.markpageMenu.accesskey;">
         <menupopup/>
       </menu>
       <menuseparator id="context-sep-viewbgimage"/>
       <menuitem id="context-viewbgimage"
                 label="&viewBGImageCmd.label;"
                 accesskey="&viewBGImageCmd.accesskey;"
--- a/browser/base/content/browser-doctype.inc
+++ b/browser/base/content/browser-doctype.inc
@@ -1,13 +1,15 @@
 <!DOCTYPE window [
 <!ENTITY % brandDTD SYSTEM "chrome://branding/locale/brand.dtd" >
 %brandDTD;
 <!ENTITY % browserDTD SYSTEM "chrome://browser/locale/browser.dtd" >
 %browserDTD;
+<!ENTITY % browserPocketDTD SYSTEM "chrome://browser/content/browser-pocket.dtd" >
+%browserPocketDTD;
 <!ENTITY % baseMenuDTD SYSTEM "chrome://browser/locale/baseMenuOverlay.dtd" >
 %baseMenuDTD;
 <!ENTITY % charsetDTD SYSTEM "chrome://global/locale/charsetMenu.dtd" >
 %charsetDTD;
 <!ENTITY % textcontextDTD SYSTEM "chrome://global/locale/textcontext.dtd" >
 %textcontextDTD;
 <!ENTITY % customizeToolbarDTD SYSTEM "chrome://global/locale/customizeToolbar.dtd">
   %customizeToolbarDTD;
--- a/browser/base/content/browser-eme.js
+++ b/browser/base/content/browser-eme.js
@@ -201,16 +201,17 @@ let gEMEHandler = {
       label: gNavigatorBundle.getString(btnLabelId),
       accessKey: gNavigatorBundle.getString(btnAccessKeyId),
       callback: function() { openPreferences("paneContent"); },
       dismiss: true
     };
     let options = {
       dismissed: true,
       eventCallback: aTopic => aTopic == "swapping",
+      learnMoreURL: Services.urlFormatter.formatURLPref("app.support.baseURL") + "drm-content",
     };
     PopupNotifications.show(browser, "drmContentPlaying", message, anchorId, mainAction, null, options);
   },
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIMessageListener])
 };
 
 XPCOMUtils.defineLazyGetter(gEMEHandler, "_brandShortName", function() {
   return document.getElementById("bundle_brand").getString("brandShortName");
--- a/browser/base/content/browser-fullScreen.js
+++ b/browser/base/content/browser-fullScreen.js
@@ -5,23 +5,25 @@
 
 var FullScreen = {
   _XULNS: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
 
   init: function() {
     // called when we go into full screen, even if initiated by a web page script
     window.addEventListener("fullscreen", this, true);
     window.messageManager.addMessageListener("MozEnteredDomFullscreen", this);
+    window.messageManager.addMessageListener("MozExitedDomFullscreen", this);
 
     if (window.fullScreen)
       this.toggle();
   },
 
   uninit: function() {
     window.messageManager.removeMessageListener("MozEnteredDomFullscreen", this);
+    window.messageManager.removeMessageListener("MozExitedDomFullscreen", this);
     this.cleanup();
   },
 
   toggle: function (event) {
     var enterFS = window.fullScreen;
 
     // We get the fullscreen event _before_ the window transitions into or out of FS mode.
     if (event && event.type == "fullscreen")
@@ -65,33 +67,26 @@ var FullScreen = {
 
     // show/hide menubars, toolbars (except the full screen toolbar)
     this.showXULChrome("toolbar", !enterFS);
 
     if (enterFS) {
       document.addEventListener("keypress", this._keyToggleCallback, false);
       document.addEventListener("popupshown", this._setPopupOpen, false);
       document.addEventListener("popuphidden", this._setPopupOpen, false);
+      this._shouldAnimate = true;
       // We don't animate the toolbar collapse if in DOM full-screen mode,
       // as the size of the content area would still be changing after the
       // mozfullscreenchange event fired, which could confuse content script.
-      this._shouldAnimate = !document.mozFullScreen;
-      this.mouseoverToggle(false);
+      this.hideNavToolbox(document.mozFullScreen);
     }
     else {
-      // The user may quit fullscreen during an animation
-      this._cancelAnimation();
-      gNavToolbox.style.marginTop = "";
-      if (this._isChromeCollapsed)
-        this.mouseoverToggle(true);
+      this.showNavToolbox(false);
       // This is needed if they use the context menu to quit fullscreen
       this._isPopupOpen = false;
-
-      document.documentElement.removeAttribute("inDOMFullscreen");
-
       this.cleanup();
     }
   },
 
   exitDomFullScreen : function() {
     document.mozCancelFullScreen();
   },
 
@@ -122,16 +117,26 @@ var FullScreen = {
       let data = aMessage.data;
       let browser = aMessage.target;
       if (gMultiProcessBrowser && browser.getAttribute("remote") == "true") {
         let windowUtils = window.QueryInterface(Ci.nsIInterfaceRequestor)
                                 .getInterface(Ci.nsIDOMWindowUtils);
         windowUtils.remoteFrameFullscreenChanged(browser, data.origin);
       }
       this.enterDomFullscreen(browser, data.origin);
+    } else if (aMessage.name == "MozExitedDomFullscreen") {
+      document.documentElement.removeAttribute("inDOMFullscreen");
+      this.cleanupDomFullscreen();
+      this.showNavToolbox();
+      // If we are still in fullscreen mode, re-hide
+      // the toolbox with animation.
+      if (window.fullScreen) {
+        this._shouldAnimate = true;
+        this.hideNavToolbox();
+      }
     }
   },
 
   enterDomFullscreen : function(aBrowser, aOrigin) {
     if (!document.mozFullScreen)
       return;
 
     // If we've received a fullscreen notification, we have to ensure that the
@@ -167,64 +172,67 @@ var FullScreen = {
     // If a fullscreen window loses focus, we show a warning when the
     // fullscreen window is refocused.
     if (!this.useLionFullScreen) {
       window.addEventListener("activate", this);
     }
 
     // Cancel any "hide the toolbar" animation which is in progress, and make
     // the toolbar hide immediately.
-    this._cancelAnimation();
-    this.mouseoverToggle(false);
+    this.hideNavToolbox(true);
+    this._fullScrToggler.hidden = true;
   },
 
   cleanup: function () {
     if (window.fullScreen) {
       MousePosTracker.removeListener(this);
       document.removeEventListener("keypress", this._keyToggleCallback, false);
       document.removeEventListener("popupshown", this._setPopupOpen, false);
       document.removeEventListener("popuphidden", this._setPopupOpen, false);
 
-      this.cancelWarning();
-      gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
-      gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
-      gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen);
-      if (!this.useLionFullScreen)
-        window.removeEventListener("activate", this);
+      this.cleanupDomFullscreen();
+    }
+  },
 
-      window.messageManager
-            .broadcastAsyncMessage("DOMFullscreen:Cleanup");
-    }
+  cleanupDomFullscreen: function () {
+    this.cancelWarning();
+    gBrowser.tabContainer.removeEventListener("TabOpen", this.exitDomFullScreen);
+    gBrowser.tabContainer.removeEventListener("TabClose", this.exitDomFullScreen);
+    gBrowser.tabContainer.removeEventListener("TabSelect", this.exitDomFullScreen);
+    if (!this.useLionFullScreen)
+      window.removeEventListener("activate", this);
+
+    window.messageManager
+          .broadcastAsyncMessage("DOMFullscreen:Cleanup");
   },
 
   getMouseTargetRect: function()
   {
     return this._mouseTargetRect;
   },
 
   // Event callbacks
   _expandCallback: function()
   {
-    FullScreen.mouseoverToggle(true);
+    FullScreen.showNavToolbox();
   },
   onMouseEnter: function()
   {
-    FullScreen.mouseoverToggle(false);
+    FullScreen.hideNavToolbox();
   },
   _keyToggleCallback: function(aEvent)
   {
     // if we can use the keyboard (eg Ctrl+L or Ctrl+E) to open the toolbars, we
     // should provide a way to collapse them too.
     if (aEvent.keyCode == aEvent.DOM_VK_ESCAPE) {
-      FullScreen._shouldAnimate = false;
-      FullScreen.mouseoverToggle(false, true);
+      FullScreen.hideNavToolbox(true);
     }
     // F6 is another shortcut to the address bar, but its not covered in OpenLocation()
     else if (aEvent.keyCode == aEvent.DOM_VK_F6)
-      FullScreen.mouseoverToggle(true);
+      FullScreen.showNavToolbox();
   },
 
   // Checks whether we are allowed to collapse the chrome
   _isPopupOpen: false,
   _isChromeCollapsed: false,
   _safeToCollapse: function(forceHide)
   {
     if (!gPrefService.getBoolPref("browser.fullscreen.autohide"))
@@ -268,57 +276,16 @@ var FullScreen = {
   },
   setAutohide: function()
   {
     gPrefService.setBoolPref("browser.fullscreen.autohide", !gPrefService.getBoolPref("browser.fullscreen.autohide"));
   },
 
   // Animate the toolbars disappearing
   _shouldAnimate: true,
-  _isAnimating: false,
-  _animationTimeout: 0,
-  _animationHandle: 0,
-  _animateUp: function() {
-    // check again, the user may have done something before the animation was due to start
-    if (!window.fullScreen || !this._safeToCollapse(false)) {
-      this._isAnimating = false;
-      this._shouldAnimate = true;
-      return;
-    }
-
-    this._animateStartTime = window.mozAnimationStartTime;
-    if (!this._animationHandle)
-      this._animationHandle = window.mozRequestAnimationFrame(this);
-  },
-
-  sample: function (timeStamp) {
-    const duration = 1500;
-    const timePassed = timeStamp - this._animateStartTime;
-    const pos = timePassed >= duration ? 1 :
-                1 - Math.pow(1 - timePassed / duration, 4);
-
-    if (pos >= 1) {
-      // We've animated enough
-      this._cancelAnimation();
-      gNavToolbox.style.marginTop = "";
-      this.mouseoverToggle(false);
-      return;
-    }
-
-    gNavToolbox.style.marginTop = (gNavToolbox.boxObject.height * pos * -1) + "px";
-    this._animationHandle = window.mozRequestAnimationFrame(this);
-  },
-
-  _cancelAnimation: function() {
-    window.mozCancelAnimationFrame(this._animationHandle);
-    this._animationHandle = 0;
-    clearTimeout(this._animationTimeout);
-    this._isAnimating = false;
-    this._shouldAnimate = false;
-  },
 
   cancelWarning: function(event) {
     if (!this.warningBox)
       return;
     this.warningBox.removeEventListener("transitionend", this);
     if (this.warningFadeOutTimeout) {
       clearTimeout(this.warningFadeOutTimeout);
       this.warningFadeOutTimeout = null;
@@ -465,63 +432,79 @@ var FullScreen = {
         setTimeout(
           function() {
             if (this.warningBox)
               this.warningBox.setAttribute("fade-warning-out", "true");
           }.bind(this),
           3000);
   },
 
-  mouseoverToggle: function(aShow, forceHide)
-  {
-    // Don't do anything if:
-    // a) we're already in the state we want,
-    // b) we're animating and will become collapsed soon, or
-    // c) we can't collapse because it would be undesirable right now
-    if (aShow != this._isChromeCollapsed || (!aShow && this._isAnimating) ||
-        (!aShow && !this._safeToCollapse(forceHide)))
-      return;
+  showNavToolbox: function(trackMouse = true) {
+    this._fullScrToggler.hidden = true;
+    gNavToolbox.removeAttribute("fullscreenShouldAnimate");
+    gNavToolbox.style.marginTop = "";
 
-    // browser.fullscreen.animateUp
-    // 0 - never animate up
-    // 1 - animate only for first collapse after entering fullscreen (default for perf's sake)
-    // 2 - animate every time it collapses
-    if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 0)
-      this._shouldAnimate = false;
-
-    if (!aShow && this._shouldAnimate) {
-      this._isAnimating = true;
-      this._shouldAnimate = false;
-      this._animationTimeout = setTimeout(this._animateUp.bind(this), 800);
+    if (!this._isChromeCollapsed) {
       return;
     }
 
-    // Hiding/collapsing the toolbox interferes with the tab bar's scrollbox,
-    // so we just move it off-screen instead. See bug 430687.
-    gNavToolbox.style.marginTop =
-      aShow ? "" : -gNavToolbox.getBoundingClientRect().height + "px";
-
-    this._fullScrToggler.hidden = aShow || document.mozFullScreen;
-
-    if (aShow) {
+    // Track whether mouse is near the toolbox
+    this._isChromeCollapsed = false;
+    if (trackMouse) {
       let rect = gBrowser.mPanelContainer.getBoundingClientRect();
       this._mouseTargetRect = {
         top: rect.top + 50,
         bottom: rect.bottom,
         left: rect.left,
         right: rect.right
       };
       MousePosTracker.addListener(this);
-    } else {
-      MousePosTracker.removeListener(this);
+    }
+  },
+
+  hideNavToolbox: function(forceHide = false) {
+    this._fullScrToggler.hidden = document.mozFullScreen;
+    if (this._isChromeCollapsed) {
+      if (forceHide) {
+        gNavToolbox.removeAttribute("fullscreenShouldAnimate");
+      }
+      return;
+    }
+    if (!this._safeToCollapse(forceHide)) {
+      this._fullScrToggler.hidden = true;
+      return;
     }
 
-    this._isChromeCollapsed = !aShow;
-    if (gPrefService.getIntPref("browser.fullscreen.animateUp") == 2)
+    // browser.fullscreen.animateUp
+    // 0 - never animate up
+    // 1 - animate only for first collapse after entering fullscreen (default for perf's sake)
+    // 2 - animate every time it collapses
+    let animateUp = gPrefService.getIntPref("browser.fullscreen.animateUp");
+    if (animateUp == 0) {
+      this._shouldAnimate = false;
+    } else if (animateUp == 2) {
       this._shouldAnimate = true;
+    }
+    if (this._shouldAnimate && !forceHide) {
+      gNavToolbox.setAttribute("fullscreenShouldAnimate", true);
+      this._shouldAnimate = false;
+      // Hide the fullscreen toggler until the transition ends.
+      let listener = () => {
+        gNavToolbox.removeEventListener("transitionend", listener, true);
+        if (this._isChromeCollapsed)
+          this._fullScrToggler.hidden = false;
+      };
+      gNavToolbox.addEventListener("transitionend", listener, true);
+      this._fullScrToggler.hidden = true;
+    }
+
+    gNavToolbox.style.marginTop =
+      -gNavToolbox.getBoundingClientRect().height + "px";
+    this._isChromeCollapsed = true;
+    MousePosTracker.removeListener(this);
   },
 
   showXULChrome: function(aTag, aShow)
   {
     var els = document.getElementsByTagNameNS(this._XULNS, aTag);
 
     for (let el of els) {
       // XXX don't interfere with previously collapsed toolbars
--- a/browser/base/content/browser-fxaccounts.js
+++ b/browser/base/content/browser-fxaccounts.js
@@ -83,16 +83,24 @@ let gFxAccounts = {
     addEventListener("activate", this);
     gNavToolbox.addEventListener("customizationstarting", this);
     gNavToolbox.addEventListener("customizationending", this);
 
     // Request the current Legacy-Sync-to-FxA migration status.  We'll be
     // notified of fxa-migration:state-changed in response if necessary.
     Services.obs.notifyObservers(null, "fxa-migration:state-request", null);
 
+    let contentUri = Services.urlFormatter.formatURLPref("identity.fxaccounts.remote.webchannel.uri");
+    // The FxAccountsWebChannel listens for events and updates
+    // the state machine accordingly.
+    let fxAccountsWebChannel = new FxAccountsWebChannel({
+      content_uri: contentUri,
+      channel_id: this.FxAccountsCommon.WEBCHANNEL_ID
+    });
+
     this._initialized = true;
 
     this.updateUI();
   },
 
   uninit: function () {
     if (!this._initialized) {
       return;
@@ -398,8 +406,11 @@ let gFxAccounts = {
 };
 
 XPCOMUtils.defineLazyGetter(gFxAccounts, "FxAccountsCommon", function () {
   return Cu.import("resource://gre/modules/FxAccountsCommon.js", {});
 });
 
 XPCOMUtils.defineLazyModuleGetter(gFxAccounts, "fxaMigrator",
   "resource://services-sync/FxaMigrator.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsWebChannel",
+  "resource://gre/modules/FxAccountsWebChannel.jsm");
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -23,20 +23,16 @@
                           key="key_newNavigator"
                           command="cmd_newNavigator"/>
                 <menuitem id="menu_newPrivateWindow"
                           label="&newPrivateWindow.label;"
                           accesskey="&newPrivateWindow.accesskey;"
                           command="Tools:PrivateBrowsing"
                           key="key_privatebrowsing"/>
 #ifdef E10S_TESTING_ONLY
-                <menuitem id="menu_newRemoteWindow"
-                          label="New e10s Window"
-                          hidden="true"
-                          command="Tools:RemoteWindow"/>
                 <menuitem id="menu_newNonRemoteWindow"
                           label="New Non-e10s Window"
                           hidden="true"
                           command="Tools:NonRemoteWindow"/>
 #endif
 #ifdef MAC_NON_BROWSER_WINDOW
                 <menuitem id="menu_openLocation"
                           label="&openLocationCmd.label;"
@@ -386,16 +382,17 @@
 #ifndef XP_MACOSX
                placespopup="true"
 #endif
                context="placesContext"
                openInTabs="children"
                oncommand="BookmarksEventHandler.onCommand(event, this.parentNode._placesView);"
                onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);"
                onpopupshowing="BookmarkingUI.onMainMenuPopupShowing(event);
+                               BookmarkingUI.updatePocketItemVisibility('menu_');
                                if (!this.parentNode._placesView)
                                  new PlacesMenu(event, 'place:folder=BOOKMARKS_MENU');"
                tooltip="bhTooltip" popupsinherittooltip="true">
       <menuitem id="bookmarksShowAll"
                 label="&showAllBookmarks2.label;"
                 command="Browser:ShowAllBookmarks"
                 key="manBookmarkKb"/>
       <menuseparator id="organizeBookmarksSeparator"/>
@@ -459,16 +456,19 @@
           <menuitem id="viewReadingListSidebar" class="subviewbutton"
                     oncommand="SidebarUI.toggle('readingListSidebar');"
                     label="&readingList.showSidebar.label;">
             <observes element="readingListSidebar" attribute="checked"/>
           </menuitem>
         </menupopup>
       </menu>
 #endif
+      <menuseparator id="menu_pocketSeparator"/>
+      <menuitem id="menu_pocket" label="&pocketMenuitem.label;"
+                oncommand="openUILink(Pocket.listURL, event);"/>
       <menuseparator id="bookmarksMenuItemsSeparator"/>
       <!-- Bookmarks menu items -->
       <menuseparator builder="end"
                      class="hide-if-empty-places-result"/>
       <menuitem id="menu_unsortedBookmarks"
                 label="&unsortedBookmarksCmd.label;"
                 oncommand="PlacesCommandHook.showPlacesOrganizer('UnfiledBookmarks');"/>
     </menupopup>
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -1560,16 +1560,22 @@ let BookmarkingUI = {
     this.broadcaster.setAttribute("label", this.broadcaster.getAttribute(label));
   },
 
   onMainMenuPopupShowing: function BUI_onMainMenuPopupShowing(event) {
     this._updateBookmarkPageMenuItem();
     PlacesCommandHook.updateBookmarkAllTabsCommand();
   },
 
+  updatePocketItemVisibility: function BUI_updatePocketItemVisibility(prefix) {
+    let hidden = !CustomizableUI.getPlacementOfWidget("pocket-button");
+    document.getElementById(prefix + "pocket").hidden = hidden;
+    document.getElementById(prefix + "pocketSeparator").hidden = hidden;
+  },
+
   _showBookmarkedNotification: function BUI_showBookmarkedNotification() {
     function getCenteringTransformForRects(rectToPosition, referenceRect) {
       let topDiff = referenceRect.top - rectToPosition.top;
       let leftDiff = referenceRect.left - rectToPosition.left;
       let heightDiff = referenceRect.height - rectToPosition.height;
       let widthDiff = referenceRect.width - rectToPosition.width;
       return [(leftDiff + .5 * widthDiff) + "px", (topDiff + .5 * heightDiff) + "px"];
     }
@@ -1677,16 +1683,17 @@ let BookmarkingUI = {
       case "ViewHiding":
         this.onPanelMenuViewHiding(aEvent);
         break;
     }
   },
 
   onPanelMenuViewShowing: function BUI_onViewShowing(aEvent) {
     this._updateBookmarkPageMenuItem();
+    this.updatePocketItemVisibility("panelMenu_");
     // Update checked status of the toolbar toggle.
     let viewToolbar = document.getElementById("panelMenu_viewBookmarksToolbar");
     let personalToolbar = document.getElementById("PersonalToolbar");
     if (personalToolbar.collapsed)
       viewToolbar.removeAttribute("checked");
     else
       viewToolbar.setAttribute("checked", "true");
     // Get all statically placed buttons to supply them with keyboard shortcuts.
--- a/browser/base/content/browser-plugins.js
+++ b/browser/base/content/browser-plugins.js
@@ -8,18 +8,17 @@ var gPluginHandler = {
   PREF_PERSISTENT_DAYS: "plugin.persistentPermissionAlways.intervalInDays",
   MESSAGES: [
     "PluginContent:ShowClickToPlayNotification",
     "PluginContent:RemoveNotification",
     "PluginContent:UpdateHiddenPluginUI",
     "PluginContent:HideNotificationBar",
     "PluginContent:ShowInstallNotification",
     "PluginContent:InstallSinglePlugin",
-    "PluginContent:ShowNPAPIPluginCrashedNotification",
-    "PluginContent:ShowGMPCrashedNotification",
+    "PluginContent:ShowPluginCrashedNotification",
     "PluginContent:SubmitReport",
     "PluginContent:LinkClickCallback",
   ],
 
   init: function () {
     const mm = window.messageManager;
     for (let msg of this.MESSAGES) {
       mm.addMessageListener(msg, this);
@@ -57,25 +56,19 @@ var gPluginHandler = {
       case "PluginContent:HideNotificationBar":
         this.hideNotificationBar(msg.target, msg.data.name);
         break;
       case "PluginContent:ShowInstallNotification":
         return this.showInstallNotification(msg.target, msg.data.pluginInfo);
       case "PluginContent:InstallSinglePlugin":
         this.installSinglePlugin(msg.data.pluginInfo);
         break;
-      case "PluginContent:ShowNPAPIPluginCrashedNotification":
-        this.showNPAPIPluginCrashedNotification(msg.target, msg.data.message,
-                                                msg.data.runID);
-        break;
-      case "PluginContent:ShowGMPCrashedNotification":
-        this.showGMPCrashedNotification(msg.target,
-                                        msg.data.messageString,
-                                        msg.data.pluginDumpID,
-                                        msg.data.browserDumpID);
+      case "PluginContent:ShowPluginCrashedNotification":
+        this.showPluginCrashedNotification(msg.target, msg.data.messageString,
+                                           msg.data.pluginID);
         break;
       case "PluginContent:SubmitReport":
         if (AppConstants.MOZ_CRASHREPORTER) {
           this.submitReport(msg.data.runID, msg.data.keyVals, msg.data.submitURLOptIn);
         }
         break;
       case "PluginContent:LinkClickCallback":
         switch (msg.data.name) {
@@ -493,103 +486,75 @@ var gPluginHandler = {
       state = "please";
     }
 
     let mm = window.getGroupMessageManager("browsers");
     mm.broadcastAsyncMessage("BrowserPlugins:NPAPIPluginProcessCrashed",
                              { pluginName, runID, state });
   },
 
-  showNPAPIPluginCrashedNotification: function (browser, messageString, runID) {
-    let crashReportCallback;
-
-    if (AppConstants.MOZ_CRASHREPORTER &&
-        PluginCrashReporter.hasCrashReport(runID)) {
-      crashReportCallback = () => {
-        PluginCrashReporter.submitCrashReport(runID);
-      };
-    }
-
-    this._showPluginCrashedNotification(browser, messageString, crashReportCallback);
-  },
-
   /**
-   * For now, GMP crashes are handled separately from NPAPI plugin crashes,
-   * since the latter are not yet working for e10s. These will be unified
-   * once e10s support is added for GMP crash reporting in bug 1146955.
-   */
-  showGMPCrashedNotification: function (browser, messageString,
-                                        pluginDumpID, browserDumpID) {
-    let crashReportCallback;
-
-    if (AppConstants.MOZ_CRASHREPORTER && pluginDumpID) {
-      crashReportCallback = () => {
-        PluginCrashReporter.submitGMPCrashReport(pluginDumpID, browserDumpID);
-      };
-    }
-
-    this._showPluginCrashedNotification(browser, messageString, crashReportCallback);
-  },
-
-  /**
-   * A helper function for showing the plugin crashed notification bar.
+   * Shows a plugin-crashed notification bar for a browser that has had an
+   * invisiable NPAPI plugin crash, or a GMP plugin crash.
    *
    * @param browser
-   *        The browser that contains the crashing plugin.
+   *        The browser to show the notification for.
    * @param messageString
-   *        The message to display in the notification.
-   * @param crashReportCallback
-   *        Optional. Pass a function to submit a crash report for this plugin
-   *        crash if a report exists. If no function is passed, the Submit Report
-   *        button will not be added.
+   *        The string to put in the notification bar
+   * @param pluginID
+   *        The unique-per-process identifier for the NPAPI plugin or GMP.
+   *        For a GMP, this is the pluginID. For NPAPI plugins (where "pluginID"
+   *        means something different), this is the runID.
    */
-  _showPluginCrashedNotification: function (browser, messageString, crashReportCallback) {
+  showPluginCrashedNotification: function (browser, messageString, pluginID) {
     // If there's already an existing notification bar, don't do anything.
     let notificationBox = gBrowser.getNotificationBox(browser);
     let notification = notificationBox.getNotificationWithValue("plugin-crashed");
-    if (notification)
+    if (notification) {
       return;
+    }
 
     // Configure the notification bar
     let priority = notificationBox.PRIORITY_WARNING_MEDIUM;
     let iconURL = "chrome://mozapps/skin/plugins/notifyPluginCrashed.png";
     let reloadLabel = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.label");
     let reloadKey   = gNavigatorBundle.getString("crashedpluginsMessage.reloadButton.accesskey");
-    let submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label");
-    let submitKey   = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey");
 
     let buttons = [{
       label: reloadLabel,
       accessKey: reloadKey,
       popup: null,
       callback: function() { browser.reload(); },
     }];
 
-    if (AppConstants.MOZ_CRASHREPORTER && crashReportCallback) {
+    if (AppConstants.MOZ_CRASHREPORTER &&
+        PluginCrashReporter.hasCrashReport(pluginID)) {
+      let submitLabel = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.label");
+      let submitKey   = gNavigatorBundle.getString("crashedpluginsMessage.submitButton.accesskey");
       let submitButton = {
         label: submitLabel,
         accessKey: submitKey,
         popup: null,
-        callback: crashReportCallback,
+        callback: () => {
+          PluginCrashReporter.submitCrashReport(pluginID);
+        },
       };
 
       buttons.push(submitButton);
     }
 
     notification = notificationBox.appendNotification(messageString, "plugin-crashed",
                                                       iconURL, priority, buttons);
 
     // Add the "learn more" link.
     let XULNS = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
     let link = notification.ownerDocument.createElementNS(XULNS, "label");
     link.className = "text-link";
     link.setAttribute("value", gNavigatorBundle.getString("crashedpluginsMessage.learnMore"));
     let crashurl = formatURL("app.support.baseURL", true);
     crashurl += "plugin-crashed-notificationbar";
     link.href = crashurl;
-
     let description = notification.ownerDocument.getAnonymousElementByAttribute(notification, "anonid", "messageText");
     description.appendChild(link);
   },
 };
 
 gPluginHandler.init();
-
new file mode 100644
--- /dev/null
+++ b/browser/base/content/browser-pocket.dtd
@@ -0,0 +1,10 @@
+<!-- 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/. -->
+
+<!-- This is a temporary file and not meant for localization; later versions
+   - of Firefox include these strings in browser.dtd -->
+
+<!ENTITY saveToPocketCmd.label     "Save Page to Pocket">
+<!ENTITY saveToPocketCmd.accesskey "k">
+<!ENTITY pocketMenuitem.label      "View Pocket List">
new file mode 100644
--- /dev/null
+++ b/browser/base/content/browser-pocket.properties
@@ -0,0 +1,9 @@
+# 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/.
+
+# This is a temporary file and not meant for localization; later versions
+# of Firefox include these strings in browser.properties
+
+pocket-button.label = Pocket
+pocket-button.tooltiptext = Save to Pocket
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -109,18 +109,16 @@
     <command id="Tools:Addons" oncommand="BrowserOpenAddonsMgr();"/>
     <command id="Tools:ErrorConsole" oncommand="toJavaScriptConsole()" disabled="true" hidden="true"/>
     <command id="Tools:DevToolsConnect" oncommand="gDevToolsBrowser.openConnectScreen(gBrowser)" disabled="true" hidden="true"/>
     <command id="Tools:Sanitize"
      oncommand="Cc['@mozilla.org/browser/browserglue;1'].getService(Ci.nsIBrowserGlue).sanitize(window);"/>
     <command id="Tools:PrivateBrowsing"
       oncommand="OpenBrowserWindow({private: true});" reserved="true"/>
 #ifdef E10S_TESTING_ONLY
-    <command id="Tools:RemoteWindow"
-      oncommand="OpenBrowserWindow({remote: true});"/>
     <command id="Tools:NonRemoteWindow"
       oncommand="OpenBrowserWindow({remote: false});"/>
 #endif
     <command id="History:UndoCloseTab" oncommand="undoCloseTab();"/>
     <command id="History:UndoCloseWindow" oncommand="undoCloseWindow();"/>
     <command id="Social:SharePage" oncommand="SocialShare.sharePage();"/>
     <command id="Social:ToggleSidebar" oncommand="SocialSidebar.toggleSidebar();" hidden="true"/>
     <command id="Social:ToggleNotifications" oncommand="Social.toggleNotifications();" hidden="true"/>
--- a/browser/base/content/browser-social.js
+++ b/browser/base/content/browser-social.js
@@ -199,18 +199,18 @@ SocialUI = {
     }
   },
 
   get _chromeless() {
     // Is this a popup window that doesn't want chrome shown?
     let docElem = document.documentElement;
     // extrachrome is not restored during session restore, so we need
     // to check for the toolbar as well.
-    let chromeless = docElem.getAttribute("chromehidden").contains("extrachrome") ||
-                     docElem.getAttribute('chromehidden').contains("toolbar");
+    let chromeless = docElem.getAttribute("chromehidden").includes("extrachrome") ||
+                     docElem.getAttribute('chromehidden').includes("toolbar");
     // This property is "fixed" for a window, so avoid doing the check above
     // multiple times...
     delete this._chromeless;
     this._chromeless = chromeless;
     return chromeless;
   },
 
   get enabled() {
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -295,16 +295,20 @@ toolbar[customizing] > .overflow-button 
   visibility: collapse;
 }
 
 #main-window[inFullscreen] #global-notificationbox,
 #main-window[inFullscreen] #high-priority-global-notificationbox {
   visibility: collapse;
 }
 
+#navigator-toolbox[fullscreenShouldAnimate] {
+  transition: 1.5s margin-top ease-out;
+}
+
 /* Rules to help integrate SDK widgets */
 toolbaritem[sdkstylewidget="true"] > toolbarbutton,
 toolbarpaletteitem > toolbaritem[sdkstylewidget="true"] > iframe,
 toolbarpaletteitem > toolbaritem[sdkstylewidget="true"] > .toolbarbutton-text {
   display: none;
 }
 
 toolbarpaletteitem:-moz-any([place="palette"], [place="panel"]) > toolbaritem[sdkstylewidget="true"] > toolbarbutton {
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -37,25 +37,28 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
                                   "resource:///modules/ContentSearch.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AboutHome",
                                   "resource:///modules/AboutHome.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Log",
                                   "resource://gre/modules/Log.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
                                   "resource://gre/modules/AppConstants.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "UpdateChannel",
+                                  "resource://gre/modules/UpdateChannel.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "Favicons",
                                    "@mozilla.org/browser/favicon-service;1",
                                    "mozIAsyncFavicons");
 XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
                                    "@mozilla.org/network/dns-service;1",
                                    "nsIDNSService");
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
                                   "resource://gre/modules/LightweightThemeManager.jsm");
-
+XPCOMUtils.defineLazyModuleGetter(this, "Pocket",
+                                  "resource:///modules/Pocket.jsm");
 
 const nsIWebNavigation = Ci.nsIWebNavigation;
 
 var gLastBrowserCharset = null;
 var gProxyFavIcon = null;
 var gLastValidURLStr = "";
 var gInPrintPreviewMode = false;
 var gContextMenu = null; // nsContextMenu instance
@@ -1947,17 +1950,17 @@ function loadOneOrMoreURIs(aURIString)
   }
   catch (e) {
   }
 }
 
 function focusAndSelectUrlBar() {
   if (gURLBar) {
     if (window.fullScreen)
-      FullScreen.mouseoverToggle(true);
+      FullScreen.showNavToolbox();
 
     gURLBar.select();
     if (document.activeElement == gURLBar.inputField)
       return true;
   }
   return false;
 }
 
@@ -2753,17 +2756,17 @@ let BrowserOnClick = {
       port: location.port,
       timestamp: Math.round(Date.now() / 1000),
       errorCode: transportSecurityInfo.errorCode,
       failedCertChain: asciiCertChain,
       userAgent: window.navigator.userAgent,
       version: 1,
       build: gAppInfo.appBuildID,
       product: gAppInfo.name,
-      channel: Services.prefs.getCharPref("app.update.channel")
+      channel: UpdateChannel.get()
     }
 
     let reportURL = Services.prefs.getCharPref("security.ssl.errorReporting.url");
 
     let xhr = Cc["@mozilla.org/xmlextras/xmlhttprequest;1"]
         .createInstance(Ci.nsIXMLHttpRequest);
     try {
       xhr.open("POST", reportURL);
@@ -2981,17 +2984,17 @@ let BrowserOnClick = {
 function getMeOutOfHere() {
   // Get the start page from the *default* pref branch, not the user's
   var prefs = Services.prefs.getDefaultBranch(null);
   var url = BROWSER_NEW_TAB_URL;
   try {
     url = prefs.getComplexValue("browser.startup.homepage",
                                 Ci.nsIPrefLocalizedString).data;
     // If url is a pipe-delimited set of pages, just take the first one.
-    if (url.contains("|"))
+    if (url.includes("|"))
       url = url.split("|")[0];
   } catch(e) {
     Components.utils.reportError("Couldn't get homepage pref: " + e);
   }
   gBrowser.loadURI(url);
 }
 
 function BrowserFullScreen()
@@ -3410,17 +3413,17 @@ const BrowserSearch = {
       let navBar = document.getElementById(CustomizableUI.AREA_NAVBAR);
       navBar.overflowable.show().then(() => {
         focusSearchBar();
       });
       return;
     }
     if (searchBar) {
       if (window.fullScreen)
-        FullScreen.mouseoverToggle(true);
+        FullScreen.showNavToolbox();
       searchBar.select();
     }
     openSearchPageIfFieldIsNotActive(searchBar);
   },
 
   /**
    * Loads a search results page, given a set of search terms. Uses the current
    * engine if the search bar is visible, or the default engine otherwise.
@@ -3673,17 +3676,17 @@ function FillHistoryMenu(aParent) {
     aParent.appendChild(item);
   }
   return true;
 }
 
 function addToUrlbarHistory(aUrlToAdd) {
   if (!PrivateBrowsingUtils.isWindowPrivate(window) &&
       aUrlToAdd &&
-      !aUrlToAdd.contains(" ") &&
+      !aUrlToAdd.includes(" ") &&
       !/[\x00-\x1F]/.test(aUrlToAdd))
     PlacesUIUtils.markPageAsTyped(aUrlToAdd);
 }
 
 function toJavaScriptConsole()
 {
   toOpenWindowByType("global:console", "chrome://global/content/console.xul");
 }
@@ -4155,16 +4158,17 @@ var XULBrowserWindow = {
       }
 
       if (gURLBar) {
         URLBarSetURI(aLocationURI);
 
         BookmarkingUI.onLocationChange();
         SocialUI.updateState(location);
         UITour.onLocationChange(location);
+        Pocket.onLocationChange(browser, aLocationURI);
       }
 
       // Utility functions for disabling find
       var shouldDisableFind = function shouldDisableFind(aDocument) {
         let docElt = aDocument.documentElement;
         return docElt && docElt.getAttribute("disablefastfind") == "true";
       }
 
@@ -5271,61 +5275,27 @@ function UpdateDynamicShortcutTooltipTex
         args.push(ShortcutUtils.prettifyShortcut(shortcut));
       }
     }
     gDynamicTooltipCache.set(nodeId, gNavigatorBundle.getFormattedString(strId, args));
   }
   aTooltip.setAttribute("label", gDynamicTooltipCache.get(nodeId));
 }
 
-/**
- * Gets the selected text in the active browser. Leading and trailing
- * whitespace is removed, and consecutive whitespace is replaced by a single
- * space. A maximum of 150 characters will be returned, regardless of the value
- * of aCharLen.
- *
- * @param aCharLen
- *        The maximum number of characters to return.
- */
 function getBrowserSelection(aCharLen) {
-  // selections of more than 150 characters aren't useful
-  const kMaxSelectionLen = 150;
-  const charLen = Math.min(aCharLen || kMaxSelectionLen, kMaxSelectionLen);
-
-  let [element, focusedWindow] = BrowserUtils.getFocusSync(document);
-  var selection = focusedWindow.getSelection().toString();
-  // try getting a selected text in text input.
-  if (!selection) {
-    var isOnTextInput = function isOnTextInput(elem) {
-      // we avoid to return a value if a selection is in password field.
-      // ref. bug 565717
-      return elem instanceof HTMLTextAreaElement ||
-             (elem instanceof HTMLInputElement && elem.mozIsTextField(true));
-    };
-
-    if (isOnTextInput(element)) {
-      selection = element.QueryInterface(Ci.nsIDOMNSEditableElement)
-                         .editor.selection.toString();
-    }
-  }
-
-  if (selection) {
-    if (selection.length > charLen) {
-      // only use the first charLen important chars. see bug 221361
-      var pattern = new RegExp("^(?:\\s*.){0," + charLen + "}");
-      pattern.test(selection);
-      selection = RegExp.lastMatch;
-    }
-
-    selection = selection.trim().replace(/\s+/g, " ");
-
-    if (selection.length > charLen)
-      selection = selection.substr(0, charLen);
-  }
-  return selection;
+  Deprecated.warning("getBrowserSelection",
+                     "https://bugzilla.mozilla.org/show_bug.cgi?id=1134769");
+
+  let focusedElement = document.activeElement;
+  if (focusedElement && focusedElement.localName == "browser" &&
+      focusedElement.isRemoteBrowser) {
+    throw "getBrowserSelection doesn't support child process windows";
+  }
+
+  return BrowserUtils.getSelectionDetails(window, aCharLen).text;
 }
 
 var gWebPanelURI;
 function openWebPanel(title, uri) {
   // Ensure that the web panels sidebar is open.
   SidebarUI.show("viewWebPanelsSidebar");
 
   // Set the title of the panel.
@@ -6452,17 +6422,17 @@ function GetSearchFieldBookmarkData(node
     }
   }
 
   var postData;
 
   if (isURLEncoded)
     postData = formData.join("&");
   else {
-    let separator = spec.contains("?") ? "&" : "?";
+    let separator = spec.includes("?") ? "&" : "?";
     spec += separator + formData.join("&");
   }
 
   return {
     spec: spec,
     title: title,
     description: description,
     postData: postData,
@@ -7228,17 +7198,17 @@ let gPrivateBrowsingUI = {
       }
     }
 
     if (gURLBar &&
         !PrivateBrowsingUtils.permanentPrivateBrowsing) {
       // Disable switch to tab autocompletion for private windows.
       // We leave it enabled for permanent private browsing mode though.
       let value = gURLBar.getAttribute("autocompletesearchparam") || "";
-      if (!value.contains("disable-private-actions")) {
+      if (!value.includes("disable-private-actions")) {
         gURLBar.setAttribute("autocompletesearchparam",
                              value + " disable-private-actions");
       }
     }
   }
 };
 
 let gRemoteTabsUI = {
@@ -7257,20 +7227,18 @@ let gRemoteTabsUI = {
 #ifdef XP_MACOSX
     if (Services.prefs.getBoolPref("layers.acceleration.disabled")) {
       // On OS X, "Disable Hardware Acceleration" also disables OMTC and forces
       // a fallback to Basic Layers. This is incompatible with e10s.
       return;
     }
 #endif
 
-    let newRemoteWindow = document.getElementById("menu_newRemoteWindow");
     let newNonRemoteWindow = document.getElementById("menu_newNonRemoteWindow");
     let autostart = Services.appinfo.browserTabsRemoteAutostart;
-    newRemoteWindow.hidden = autostart;
     newNonRemoteWindow.hidden = !autostart;
   }
 };
 
 /**
  * Switch to a tab that has a given URI, and focusses its browser window.
  * If a matching tab is in this window, it will be switched to. Otherwise, other
  * windows will be searched.
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -725,19 +725,19 @@
            to the default placements of buttons in CustomizableUI.jsm, so the
            customization code doesn't get confused.
       -->
     <toolbar id="nav-bar"
              aria-label="&navbarCmd.label;"
              fullscreentoolbar="true" mode="icons" customizable="true"
              iconsize="small"
 #ifdef MOZ_DEV_EDITION
-             defaultset="urlbar-container,search-container,developer-button,bookmarks-menu-button,downloads-button,home-button,loop-button"
+             defaultset="urlbar-container,search-container,developer-button,bookmarks-menu-button,pocket-button,downloads-button,home-button,loop-button"
 #else
-             defaultset="urlbar-container,search-container,bookmarks-menu-button,downloads-button,home-button,loop-button"
+             defaultset="urlbar-container,search-container,bookmarks-menu-button,pocket-button,downloads-button,home-button,loop-button"
 #endif
              customizationtarget="nav-bar-customization-target"
              overflowable="true"
              overflowbutton="nav-bar-overflow-button"
              overflowtarget="widget-overflow-list"
              overflowpanel="widget-overflow"
              context="toolbar-context-menu">
 
@@ -878,16 +878,17 @@
           <menupopup id="BMB_bookmarksPopup"
                      class="cui-widget-panel cui-widget-panelview cui-widget-panelWithFooter PanelUI-subView"
                      placespopup="true"
                      context="placesContext"
                      openInTabs="children"
                      oncommand="BookmarksEventHandler.onCommand(event, this.parentNode._placesView);"
                      onclick="BookmarksEventHandler.onClick(event, this.parentNode._placesView);"
                      onpopupshowing="BookmarkingUI.onPopupShowing(event);
+                                     BookmarkingUI.updatePocketItemVisibility('BMB_');
                                      BookmarkingUI.attachPlacesView(event, this);"
                      tooltip="bhTooltip" popupsinherittooltip="true">
             <menuitem id="BMB_viewBookmarksSidebar"
                       class="subviewbutton"
                       label="&viewBookmarksSidebar2.label;"
                       type="checkbox"
                       oncommand="SidebarUI.toggle('viewBookmarksSidebar');">
               <observes element="viewBookmarksSidebar" attribute="checked"/>
@@ -965,16 +966,21 @@
               <menupopup id="BMB_readingListPopup"
                          placespopup="true"
                          onpopupshowing="ReadingListUI.onReadingListPopupShowing(this);">
                 <menuitem id="BMB_viewReadingListSidebar" class="subviewbutton"
                           oncommand="SidebarUI.show('readingListSidebar');"
                           label="&readingList.showSidebar.label;"/>
               </menupopup>
             </menu>
+            <menuseparator id="BMB_pocketSeparator"/>
+            <menuitem id="BMB_pocket"
+                      class="menuitem-iconic bookmark-item subviewbutton"
+                      label="&pocketMenuitem.label;"
+                      oncommand="openUILink(Pocket.listURL, event);"/>
             <menuseparator/>
             <!-- Bookmarks menu items will go here -->
             <menuitem id="BMB_bookmarksShowAll"
                       class="subviewbutton panel-subview-footer"
                       label="&showAllBookmarks2.label;"
                       command="Browser:ShowAllBookmarks"
                       key="manBookmarkKb"/>
           </menupopup>
@@ -1295,9 +1301,12 @@
   </svg:svg>
 
 </vbox>
 # <iframe id="tab-view"> is dynamically appended as the 2nd child of #tab-view-deck.
 #     Introducing the iframe dynamically, as needed, was found to be better than
 #     starting with an empty iframe here in browser.xul from a Ts standpoint.
 </deck>
 
+<script type="application/javascript" src="chrome://browser/content/pocket/pktApi.js"/>
+<script type="application/javascript" src="chrome://browser/content/pocket/main.js"/>
+
 </window>
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -96,29 +96,33 @@ let handleContentContextMenu = function 
 
   // Media related cache info parent needs for saving
   let contentType = null;
   let contentDisposition = null;
   if (event.target.nodeType == Ci.nsIDOMNode.ELEMENT_NODE &&
       event.target instanceof Ci.nsIImageLoadingContent &&
       event.target.currentURI) {
     try {
-      let imageCache = Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
-                                                       .getImgCacheForDocument(doc);
+      let imageCache = 
+        Cc["@mozilla.org/image/tools;1"].getService(Ci.imgITools)
+                                        .getImgCacheForDocument(doc);
       let props =
         imageCache.findEntryProperties(event.target.currentURI);
-      if (props) {
+      try {
         contentType = props.get("type", Ci.nsISupportsCString).data;
-        contentDisposition = props.get("content-disposition", Ci.nsISupportsCString).data;
-      }
-    } catch (e) {
-      Cu.reportError(e);
-    }
+      } catch(e) {}
+      try {
+        contentDisposition =
+          props.get("content-disposition", Ci.nsISupportsCString).data;
+      } catch(e) {}
+    } catch(e) {}
   }
 
+  let selectionInfo = BrowserUtils.getSelectionDetails(content);
+
   if (Services.appinfo.processType == Services.appinfo.PROCESS_TYPE_CONTENT) {
     let editFlags = SpellCheckHelper.isEditable(event.target, content);
     let spellInfo;
     if (editFlags &
         (SpellCheckHelper.EDITABLE | SpellCheckHelper.CONTENTEDITABLE)) {
       spellInfo =
         InlineSpellCheckerContent.initContextMenu(event, editFlags, this);
     }
@@ -131,17 +135,17 @@ let handleContentContextMenu = function 
     event.target.ownerDocument.defaultView.updateCommands("contentcontextmenu");
 
     let customMenuItems = PageMenuChild.build(event.target);
     let principal = doc.nodePrincipal;
     sendSyncMessage("contextmenu",
                     { editFlags, spellInfo, customMenuItems, addonInfo,
                       principal, docLocation, charSet, baseURI, referrer,
                       referrerPolicy, contentType, contentDisposition,
-                      frameOuterWindowID },
+                      frameOuterWindowID, selectionInfo },
                     { event, popupNode: event.target });
   }
   else {
     // Break out to the parent window and pass the add-on info along
     let browser = docShell.chromeEventHandler;
     let mainWin = browser.ownerDocument.defaultView;
     mainWin.gContextMenuContentData = {
       isRemote: false,
@@ -151,16 +155,17 @@ let handleContentContextMenu = function 
       addonInfo: addonInfo,
       documentURIObject: doc.documentURIObject,
       docLocation: docLocation,
       charSet: charSet,
       referrer: referrer,
       referrerPolicy: referrerPolicy,
       contentType: contentType,
       contentDisposition: contentDisposition,
+      selectionInfo: selectionInfo,
     };
   }
 }
 
 Cc["@mozilla.org/eventlistenerservice;1"]
   .getService(Ci.nsIEventListenerService)
   .addSystemEventListener(global, "contextmenu", handleContentContextMenu, false);
 
@@ -200,16 +205,25 @@ let AboutNetErrorListener = {
               enabled: Services.prefs.getBoolPref("security.ssl.errorReporting.enabled"),
             automatic: automatic
             })
           }
     ));
     if (automatic) {
       this.onSendReport(evt);
     }
+    // hide parts of the UI we don't need yet
+    let contentDoc = content.document;
+
+    let reportSendingMsg = contentDoc.getElementById("reportSendingMessage");
+    let reportSentMsg = contentDoc.getElementById("reportSentMessage");
+    let retryBtn = contentDoc.getElementById("reportCertificateErrorRetry");
+    reportSendingMsg.style.display = "none";
+    reportSentMsg.style.display = "none";
+    retryBtn.style.display = "none";
   },
 
   onSetAutomatic: function(evt) {
     sendAsyncMessage("Browser:SetSSLErrorReportAuto", {
         automatic: evt.detail
       });
   },
 
@@ -226,33 +240,32 @@ let AboutNetErrorListener = {
       // document - we'll compare on document URI
       if (contentDoc.documentURI === message.data.documentURI) {
         switch(message.data.reportStatus) {
         case "activity":
           // Hide the button that was just clicked
           reportBtn.style.display = "none";
           retryBtn.style.display = "none";
           reportSentMsg.style.display = "none";
-          reportSendingMsg.style.display = "inline";
+          reportSendingMsg.style.removeProperty("display");
           break;
         case "error":
           // show the retry button
-          retryBtn.style.display = "inline";
+          retryBtn.style.removeProperty("display");
           reportSendingMsg.style.display = "none";
           break;
         case "complete":
           // Show a success indicator
-          reportSentMsg.style.display = "inline";
+          reportSentMsg.style.removeProperty("display");
           reportSendingMsg.style.display = "none";
           break;
         }
       }
     });
 
-
     let failedChannel = docShell.failedChannel;
     let location = contentDoc.location.href;
 
     let serhelper = Cc["@mozilla.org/network/serialization-helper;1"]
                      .getService(Ci.nsISerializationHelper);
 
     let serializable =  docShell.failedChannel.securityInfo
                                 .QueryInterface(Ci.nsITransportSecurityInfo)
--- a/browser/base/content/newtab/sites.js
+++ b/browser/base/content/newtab/sites.js
@@ -128,17 +128,17 @@ Site.prototype = {
     let link = this._querySelector(".newtab-link");
     link.setAttribute("title", tooltip);
     link.setAttribute("href", url);
     this._querySelector(".newtab-title").textContent = title;
     this.node.setAttribute("type", this.link.type);
 
     if (this.link.targetedSite) {
       this.node.setAttribute("suggested", true);
-      let targetedSite = `<strong> ${this.link.targetedSite} </strong>`;
+      let targetedSite = `<strong> ${this.link.targetedName} </strong>`;
       this._querySelector(".newtab-suggested").innerHTML =
         `<div class='newtab-suggested-bounds'> ${newTabString("suggested.button", [targetedSite])} </div>`;
     }
 
     if (this.isPinned())
       this._updateAttributes(true);
     // Capture the page if the thumbnail is missing, which will cause page.js
     // to be notified and call our refreshThumbnail() method.
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -37,17 +37,17 @@ nsContextMenu.prototype = {
 
     this.isFrameImage = document.getElementById("isFrameImage");
     this.ellipsis = "\u2026";
     try {
       this.ellipsis = gPrefService.getComplexValue("intl.ellipsis",
                                                    Ci.nsIPrefLocalizedString).data;
     } catch (e) { }
 
-    this.isContentSelected = this.isContentSelection();
+    this.isContentSelected = !this.selectionInfo.docSelectionIsCollapsed;
     this.onPlainTextLink = false;
 
     // Initialize (disable/remove) menu items.
     this.initItems();
 
     // Register this opening of the menu with telemetry:
     this._checkTelemetryForMenu(aXulMenu);
   },
@@ -88,77 +88,25 @@ nsContextMenu.prototype = {
       var mailtoHandler = Cc["@mozilla.org/uriloader/external-protocol-service;1"].
                           getService(Ci.nsIExternalProtocolService).
                           getProtocolHandlerInfo("mailto");
       isMailtoInternal = (!mailtoHandler.alwaysAskBeforeHandling &&
                           mailtoHandler.preferredAction == Ci.nsIHandlerInfo.useHelperApp &&
                           (mailtoHandler.preferredApplicationHandler instanceof Ci.nsIWebHandlerApp));
     }
 
-    // Time to do some bad things and see if we've highlighted a URL that
-    // isn't actually linked.
-    if (this.isTextSelected && !this.onLink) {
-      // Ok, we have some text, let's figure out if it looks like a URL.
-      let selection =  this.focusedWindow.getSelection();
-      let linkText = selection.toString().trim();
-      let uri;
-      if (/^(?:https?|ftp):/i.test(linkText)) {
-        try {
-          uri = makeURI(linkText);
-        } catch (ex) {}
-      }
-      // Check if this could be a valid url, just missing the protocol.
-      else if (/^(?:[a-z\d-]+\.)+[a-z]+$/i.test(linkText)) {
-        // Now let's see if this is an intentional link selection. Our guess is
-        // based on whether the selection begins/ends with whitespace or is
-        // preceded/followed by a non-word character.
-
-        // selection.toString() trims trailing whitespace, so we look for
-        // that explicitly in the first and last ranges.
-        let beginRange = selection.getRangeAt(0);
-        let delimitedAtStart = /^\s/.test(beginRange);
-        if (!delimitedAtStart) {
-          let container = beginRange.startContainer;
-          let offset = beginRange.startOffset;
-          if (container.nodeType == Node.TEXT_NODE && offset > 0)
-            delimitedAtStart = /\W/.test(container.textContent[offset - 1]);
-          else
-            delimitedAtStart = true;
-        }
+    if (this.isTextSelected && !this.onLink &&
+        this.selectionInfo && this.selectionInfo.linkURL) {
+      this.linkURL = this.selectionInfo.linkURL;
+      try {
+        this.linkURI = makeURI(this.linkURL);
+      } catch (ex) {}
 
-        let delimitedAtEnd = false;
-        if (delimitedAtStart) {
-          let endRange = selection.getRangeAt(selection.rangeCount - 1);
-          delimitedAtEnd = /\s$/.test(endRange);
-          if (!delimitedAtEnd) {
-            let container = endRange.endContainer;
-            let offset = endRange.endOffset;
-            if (container.nodeType == Node.TEXT_NODE &&
-                offset < container.textContent.length)
-              delimitedAtEnd = /\W/.test(container.textContent[offset]);
-            else
-              delimitedAtEnd = true;
-          }
-        }
-
-        if (delimitedAtStart && delimitedAtEnd) {
-          let uriFixup = Cc["@mozilla.org/docshell/urifixup;1"]
-                           .getService(Ci.nsIURIFixup);
-          try {
-            uri = uriFixup.createFixupURI(linkText, uriFixup.FIXUP_FLAG_NONE);
-          } catch (ex) {}
-        }
-      }
-
-      if (uri && uri.host) {
-        this.linkURI = uri;
-        this.linkURL = this.linkURI.spec;
-        this.linkText = linkText;
-        this.onPlainTextLink = true;
-      }
+      this.linkTextStr = this.selectionInfo.linkText;
+      this.onPlainTextLink = true;
     }
 
     var shouldShow = this.onSaveableLink || isMailtoInternal || this.onPlainTextLink;
     var isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
     this.showItem("context-openlink", shouldShow && !isWindowPrivate);
     this.showItem("context-openlinkprivate", shouldShow);
     this.showItem("context-openlinkintab", shouldShow);
     this.showItem("context-openlinkincurrent", this.onPlainTextLink);
@@ -224,16 +172,27 @@ nsContextMenu.prototype = {
     // SimpleServiceDiscovery.services), but SimpleServiceDiscovery is guaranteed
     // to be already loaded, since we load it on startup in nsBrowserGlue,
     // and CastingApps isn't, so check SimpleServiceDiscovery.services first
     // to avoid needing to load CastingApps.jsm if we don't need to.
     shouldShowCast = shouldShowCast && this.mediaURL &&
                      SimpleServiceDiscovery.services.length > 0 &&
                      CastingApps.getServicesForVideo(this.target).length > 0;
     this.setItemAttr("context-castvideo", "disabled", !shouldShowCast);
+
+    let canPocket = false;
+    if (shouldShow && window.gBrowser &&
+        this.browser.getTabBrowser() == window.gBrowser) {
+      let uri = this.browser.currentURI;
+      canPocket =
+        CustomizableUI.getPlacementOfWidget("pocket-button") &&
+        (uri.schemeIs("http") || uri.schemeIs("https") ||
+         (uri.schemeIs("about") && ReaderMode.getOriginalUrl(uri.spec)));
+    }
+    this.showItem("context-pocket", canPocket && window.pktApi && window.pktApi.isUserLoggedIn());
   },
 
   initViewItems: function CM_initViewItems() {
     // View source is always OK, unless in directory listing.
     this.showItem("context-viewpartialsource-selection",
                   this.isContentSelected);
     this.showItem("context-viewpartialsource-mathml",
                   this.onMathML && !this.isContentSelected);
@@ -571,40 +530,43 @@ nsContextMenu.prototype = {
     this.onKeywordField    = false;
     this.mediaURL          = "";
     this.onLink            = false;
     this.onMailtoLink      = false;
     this.onSaveableLink    = false;
     this.link              = null;
     this.linkURL           = "";
     this.linkURI           = null;
-    this.linkText          = "";
+    this.linkTextStr       = "";
     this.linkProtocol      = "";
     this.linkDownload      = "";
     this.linkHasNoReferrer = false;
     this.onMathML          = false;
     this.inFrame           = false;
     this.inSrcdocFrame     = false;
     this.inSyntheticDoc    = false;
     this.hasBGImage        = false;
     this.bgImageURL        = "";
     this.onEditableArea    = false;
     this.isDesignMode      = false;
     this.onCTPPlugin       = false;
     this.canSpellCheck     = false;
-    this.textSelected      = getBrowserSelection();
+
+    if (this.isRemote) {
+      this.selectionInfo = gContextMenuContentData.selectionInfo;
+    } else {
+      this.selectionInfo = BrowserUtils.getSelectionDetails(window);
+    }
+
+    this.textSelected      = this.selectionInfo.text;
     this.isTextSelected    = this.textSelected.length != 0;
 
     // Remember the node that was clicked.
     this.target = aNode;
 
-    let [elt, win] = BrowserUtils.getFocusSync(document);
-    this.focusedWindow = win;
-    this.focusedElement = elt;
-
     let ownerDoc = this.target.ownerDocument;
     this.ownerDoc = ownerDoc;
 
     // If this is a remote context menu event, use the information from
     // gContextMenuContentData instead.
     if (this.isRemote) {
       this.browser = gContextMenuContentData.browser;
       this.principal = gContextMenuContentData.principal;
@@ -744,17 +706,17 @@ nsContextMenu.prototype = {
 
           // Target is a link or a descendant of a link.
           this.onLink = true;
 
           // Remember corresponding element.
           this.link = elem;
           this.linkURL = this.getLinkURL();
           this.linkURI = this.getLinkURI();
-          this.linkText = this.getLinkText();
+          this.linkTextStr = this.getLinkText();
           this.linkProtocol = this.getLinkProtocol();
           this.onMailtoLink = (this.linkProtocol == "mailto");
           this.onSaveableLink = this.isLinkSaveable( this.link );
           this.linkHasNoReferrer = BrowserUtils.linkHasNoReferrer(elem);
           try {
             if (elem.download) {
               // Ignore download attribute on cross-origin links
               this.principal.checkMayLoad(this.linkURI, false, true);
@@ -1325,17 +1287,17 @@ nsContextMenu.prototype = {
 
     // kick off the channel with our proxy object as the listener
     channel.asyncOpen(new saveAsListener(), null);
   },
 
   // Save URL of clicked-on link.
   saveLink: function() {
     urlSecurityCheck(this.linkURL, this.principal);
-    this.saveHelper(this.linkURL, this.linkText, null, true, this.ownerDoc,
+    this.saveHelper(this.linkURL, this.linkTextStr, null, true, this.ownerDoc,
                     gContextMenuContentData.documentURIObject,
                     gContextMenuContentData.frameOuterWindowID,
                     this.linkDownload);
   },
 
   // Backwards-compatibility wrapper
   saveImage : function() {
     if (this.onCanvas || this.onImage)
@@ -1540,19 +1502,19 @@ nsContextMenu.prototype = {
         if (!text || !text.match(/\S/))
           text = this.linkURL;
       }
     }
 
     return text;
   },
 
-  // Returns true if anything is selected.
-  isContentSelection: function() {
-    return !this.focusedWindow.getSelection().isCollapsed;
+  // Kept for addon compat
+  linkText: function() {
+    return this.linkTextStr;
   },
 
   isMediaURLReusable: function(aURL) {
     return !/^(?:blob|mediasource):/.test(aURL);
   },
 
   toString: function () {
     return "contextMenu.target     = " + this.target + "\n" +
@@ -1612,17 +1574,17 @@ nsContextMenu.prototype = {
   },
 
   bookmarkThisPage: function CM_bookmarkThisPage() {
     window.top.PlacesCommandHook.bookmarkPage(this.browser, PlacesUtils.bookmarksMenuFolderId, true);
   },
 
   bookmarkLink: function CM_bookmarkLink() {
     window.top.PlacesCommandHook.bookmarkLink(PlacesUtils.bookmarksMenuFolderId,
-                                              this.linkURL, this.linkText);
+                                              this.linkURL, this.linkTextStr);
   },
 
   addBookmarkForFrame: function CM_addBookmarkForFrame() {
     var doc = this.target.ownerDocument;
     var uri = doc.documentURIObject;
 
     var itemId = PlacesUtils.getMostRecentBookmarkForURI(uri);
     if (itemId == -1) {
@@ -1665,16 +1627,32 @@ nsContextMenu.prototype = {
   shareSelect: function CM_shareSelect() {
     SocialShare.sharePage(null, { url: this.browser.currentURI.spec, text: this.textSelected }, this.target);
   },
 
   savePageAs: function CM_savePageAs() {
     saveDocument(this.browser.contentDocumentAsCPOW);
   },
 
+  saveToPocket: function CM_saveToPocket() {
+    let pocketWidget = document.getElementById("pocket-button");
+    let placement = CustomizableUI.getPlacementOfWidget("pocket-button");
+    if (!placement)
+      return;
+
+    if (placement.area == CustomizableUI.AREA_PANEL) {
+      PanelUI.show().then(function() {
+        pocketWidget = document.getElementById("pocket-button");
+        pocketWidget.doCommand();
+      });
+    } else {
+      pocketWidget.doCommand();
+    }
+  },
+
   printFrame: function CM_printFrame() {
     PrintUtils.print(this.target.ownerDocument.defaultView, this.browser);
   },
 
   switchPageDirection: function CM_switchPageDirection() {
     this.browser.messageManager.sendAsyncMessage("SwitchDocumentDirection");
   },
 
@@ -1706,17 +1684,17 @@ nsContextMenu.prototype = {
     if (this.onImage)
       return this.mediaURL;
     return "";
   },
 
   // Formats the 'Search <engine> for "<selection or link text>"' context menu.
   formatSearchContextItem: function() {
     var menuItem = document.getElementById("context-searchselect");
-    let selectedText = this.isTextSelected ? this.textSelected : this.linkText;
+    let selectedText = this.isTextSelected ? this.textSelected : this.linkTextStr;
 
     // Store searchTerms in context menu item so we know what to search onclick
     menuItem.searchTerms = selectedText;
 
     // If the JS character after our truncation point is a trail surrogate,
     // include it in the truncated string to avoid splitting a surrogate pair.
     if (selectedText.length > 15) {
       let truncLength = 15;
--- a/browser/base/content/pageinfo/permissions.js
+++ b/browser/base/content/pageinfo/permissions.js
@@ -25,17 +25,17 @@ var permissionObserver = {
           setPluginsRadioState();
       }
     }
   }
 };
 
 function onLoadPermission()
 {
-  var uri = gDocument.documentURIObject;
+  var uri = BrowserUtils.makeURIFromCPOW(gDocument.documentURIObject);
   var permTab = document.getElementById("permTab");
   if (SitePermissions.isSupportedURI(uri)) {
     gPermURI = uri;
     var hostText = document.getElementById("hostText");
     hostText.value = gPermURI.host;
 
     for (var i of gPermissions)
       initRow(i);
--- a/browser/base/content/pageinfo/security.js
+++ b/browser/base/content/pageinfo/security.js
@@ -1,13 +1,15 @@
 /* -*- indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* 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/. */
 
+Components.utils.import("resource://gre/modules/BrowserUtils.jsm");
+
 var security = {
   // Display the server certificate (static)
   viewCert : function () {
     var cert = security._cert;
     viewCertHelper(window, cert);
   },
 
   _getSecurityInfo : function() {
@@ -130,17 +132,17 @@ var security = {
   {
     var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
                        .getService(Components.interfaces.nsIWindowMediator);
     var win = wm.getMostRecentWindow("Browser:Cookies");
     var eTLDService = Components.classes["@mozilla.org/network/effective-tld-service;1"].
                       getService(Components.interfaces.nsIEffectiveTLDService);
 
     var eTLD;
-    var uri = gDocument.documentURIObject;
+    var uri = BrowserUtils.makeURIFromCPOW(gDocument.documentURIObject);
     try {
       eTLD = eTLDService.getBaseDomain(uri);
     }
     catch (e) {
       // getBaseDomain will fail if the host is an IP address or is empty
       eTLD = uri.asciiHost;
     }
 
@@ -227,17 +229,17 @@ function securityOnLoad() {
   }
   else
     viewCert.collapsed = true;
 
   /* Set Privacy & History section text */
   var yesStr = pageInfoBundle.getString("yes");
   var noStr = pageInfoBundle.getString("no");
 
-  var uri = gDocument.documentURIObject;
+  var uri = BrowserUtils.makeURIFromCPOW(gDocument.documentURIObject);
   setText("security-privacy-cookies-value",
           hostHasCookies(uri) ? yesStr : noStr);
   setText("security-privacy-passwords-value",
           realmHasPasswords(uri) ? yesStr : noStr);
   
   var visitCount = previousVisitCount(info.hostName);
   if(visitCount > 1) {
     setText("security-privacy-history-value",
--- a/browser/base/content/sync/aboutSyncTabs.js
+++ b/browser/base/content/sync/aboutSyncTabs.js
@@ -62,18 +62,18 @@ let RemoteTabViewer = {
     let numTabs = this._tabsList.getRowCount();
     let clientTabs = 0;
     let currentClient = null;
 
     for (let i = 0; i < numTabs; i++) {
       let item = this._tabsList.getItemAtIndex(i);
       let hide = false;
       if (item.getAttribute("type") == "tab") {
-        if (!item.getAttribute("url").toLowerCase().contains(val) &&
-            !item.getAttribute("title").toLowerCase().contains(val)) {
+        if (!item.getAttribute("url").toLowerCase().includes(val) &&
+            !item.getAttribute("title").toLowerCase().includes(val)) {
           hide = true;
         } else {
           clientTabs++;
         }
       }
       else if (item.getAttribute("type") == "client") {
         if (currentClient) {
           if (clientTabs == 0) {
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -550,17 +550,19 @@ function gKeywordURIFixup(fixupInfo) {
   sendAsyncMessage("Browser:URIFixup", data);
 }
 Services.obs.addObserver(gKeywordURIFixup, "keyword-uri-fixup", false);
 addEventListener("unload", () => {
   Services.obs.removeObserver(gKeywordURIFixup, "keyword-uri-fixup");
 }, false);
 
 addMessageListener("Browser:AppTab", function(message) {
-  docShell.isAppTab = message.data.isAppTab;
+  if (docShell) {
+    docShell.isAppTab = message.data.isAppTab;
+  }
 });
 
 let WebBrowserChrome = {
   onBeforeLinkTraversal: function(originalTarget, linkURI, linkNode, isAppTab) {
     return BrowserUtils.onBeforeLinkTraversal(originalTarget, linkURI, linkNode, isAppTab);
   },
 
   // Check whether this URI should load in the current process
@@ -583,16 +585,17 @@ if (Services.appinfo.processType == Serv
 
 let DOMFullscreenHandler = {
   _fullscreenDoc: null,
 
   init: function() {
     addMessageListener("DOMFullscreen:Approved", this);
     addMessageListener("DOMFullscreen:CleanUp", this);
     addEventListener("MozEnteredDomFullscreen", this);
+    addEventListener("MozExitedDomFullscreen", this);
   },
 
   receiveMessage: function(aMessage) {
     switch(aMessage.name) {
       case "DOMFullscreen:Approved": {
         if (this._fullscreenDoc) {
           Services.obs.notifyObservers(this._fullscreenDoc,
                                        "fullscreen-approved",
@@ -608,12 +611,14 @@ let DOMFullscreenHandler = {
   },
 
   handleEvent: function(aEvent) {
     if (aEvent.type == "MozEnteredDomFullscreen") {
       this._fullscreenDoc = aEvent.target;
       sendAsyncMessage("MozEnteredDomFullscreen", {
         origin: this._fullscreenDoc.nodePrincipal.origin,
       });
+    } else if (aEvent.type == "MozExitedDomFullscreen") {
+      sendAsyncMessage("MozExitedDomFullscreen");
     }
   }
 };
 DOMFullscreenHandler.init();
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -526,48 +526,42 @@
         <parameter name="aBrowser"/>
         <parameter name="aMethod"/>
         <parameter name="aArguments"/>
         <parameter name="aCallGlobalListeners"/>
         <parameter name="aCallTabsListeners"/>
         <body><![CDATA[
           var rv = true;
 
-          if (!aBrowser)
-            aBrowser = this.mCurrentBrowser;
-
-          if (aCallGlobalListeners != false &&
-              aBrowser == this.mCurrentBrowser) {
-            for (let p of this.mProgressListeners) {
+          function callListeners(listeners, args) {
+            for (let p of listeners) {
               if (aMethod in p) {
                 try {
-                  if (!p[aMethod].apply(p, aArguments))
+                  if (!p[aMethod].apply(p, args))
                     rv = false;
                 } catch (e) {
                   // don't inhibit other listeners
                   Components.utils.reportError(e);
                 }
               }
             }
           }
 
+          if (!aBrowser)
+            aBrowser = this.mCurrentBrowser;
+
+          if (aCallGlobalListeners != false &&
+              aBrowser == this.mCurrentBrowser) {
+            callListeners(this.mProgressListeners, aArguments);
+          }
+
           if (aCallTabsListeners != false) {
             aArguments.unshift(aBrowser);
 
-            for (let p of this.mTabsProgressListeners) {
-              if (aMethod in p) {
-                try {
-                  if (!p[aMethod].apply(p, aArguments))
-                    rv = false;
-                } catch (e) {
-                  // don't inhibit other listeners
-                  Components.utils.reportError(e);
-                }
-              }
-            }
+            callListeners(this.mTabsProgressListeners, aArguments);
           }
 
           return rv;
         ]]></body>
       </method>
 
       <!-- A web progress listener object definition for a given tab. -->
       <method name="mTabProgressListener">
@@ -777,19 +771,22 @@
 
               if (topLevel) {
                 // If userTypedClear > 0, the document loaded correctly and we should be
                 // clearing the user typed value. We also need to clear the typed value
                 // if the document failed to load, to make sure the urlbar reflects the
                 // failed URI (particularly for SSL errors). However, don't clear the value
                 // if the error page's URI is about:blank, because that causes complete
                 // loss of urlbar contents for invalid URI errors (see bug 867957).
+                // Another reason to clear the userTypedValue is if this was an anchor
+                // navigation.
                 if (this.mBrowser.userTypedClear > 0 ||
                     ((aFlags & Ci.nsIWebProgressListener.LOCATION_CHANGE_ERROR_PAGE) &&
-                     aLocation.spec != "about:blank"))
+                     aLocation.spec != "about:blank") ||
+                     aFlags && Ci.nsIWebProgressListener.LOCATION_CHANGE_SAME_DOCUMENT)
                   this.mBrowser.userTypedValue = null;
 
                 if (this.mTabBrowser.isFindBarInitialized(this.mTab)) {
                   let findBar = this.mTabBrowser.getFindBar(this.mTab);
 
                   // Close the Find toolbar if we're in old-style TAF mode
                   if (findBar.findMode != findBar.FIND_NORMAL)
                     findBar.close();
@@ -993,17 +990,17 @@
                 newTitle += sep;
             }
             newTitle += modifier;
 
             // If location bar is hidden and the URL type supports a host,
             // add the scheme and host to the title to prevent spoofing.
             // XXX https://bugzilla.mozilla.org/show_bug.cgi?id=22183#c239
             try {
-              if (docElement.getAttribute("chromehidden").contains("location")) {
+              if (docElement.getAttribute("chromehidden").includes("location")) {
                 var uri = this.mURIFixup.createExposableURI(
                             aBrowser.currentURI);
                 if (uri.scheme == "about")
                   newTitle = uri.spec + sep + newTitle;
                 else
                   newTitle = uri.prePath + sep + newTitle;
               }
             } catch (e) {}
@@ -1033,18 +1030,22 @@
         <body>
           <![CDATA[
             var newBrowser = this.getBrowserAtIndex(this.tabContainer.selectedIndex);
             if (this.mCurrentBrowser == newBrowser && !aForceUpdate)
               return;
 
             if (!aForceUpdate) {
               TelemetryStopwatch.start("FX_TAB_SWITCH_UPDATE_MS");
-              window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils)
-                                                             .beginTabSwitch();
+              if (!Services.appinfo.browserTabsRemoteAutostart) {
+                // old way of measuring tab paint which is not
+                // valid with e10s.
+                window.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils)
+                                                               .beginTabSwitch();
+              }
             }
 
             var oldTab = this.mCurrentTab;
 
             // Preview mode should not reset the owner
             if (!this._previewMode && !oldTab.selected)
               oldTab.owner = null;
 
@@ -1498,35 +1499,29 @@
             let index = tab._tPos;
             let filter = this.mTabFilters[index];
             aBrowser.webProgress.removeProgressListener(filter);
             // Make sure the browser is destroyed so it unregisters from observer notifications
             aBrowser.destroy();
 
             // Change the "remote" attribute.
             let parent = aBrowser.parentNode;
-            let permanentKey = aBrowser.permanentKey;
             parent.removeChild(aBrowser);
             aBrowser.setAttribute("remote", aShouldBeRemote ? "true" : "false");
-            // Tearing down the browser gives a new permanentKey but we want to
-            // keep the old one. Re-set it explicitly after unbinding from DOM.
-            aBrowser._permanentKey = permanentKey;
             parent.appendChild(aBrowser);
 
             // Restore the progress listener.
             aBrowser.webProgress.addProgressListener(filter, Ci.nsIWebProgress.NOTIFY_ALL);
 
             if (aShouldBeRemote) {
-              tab.setAttribute("remote", "true");
               // Switching the browser to be remote will connect to a new child
               // process so the browser can no longer be considered to be
               // crashed.
               tab.removeAttribute("crashed");
             } else {
-              tab.removeAttribute("remote");
               aBrowser.messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: tab.pinned })
             }
 
             if (wasActive)
               aBrowser.focus();
 
             let evt = document.createEvent("Events");
             evt.initEvent("TabRemotenessChange", true, false);
@@ -1624,16 +1619,17 @@
           <![CDATA[
             const NS_XUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
             let remote = aParams && aParams.remote;
             let uriIsAboutBlank = aParams && aParams.uriIsAboutBlank;
             let isPreloadBrowser = aParams && aParams.isPreloadBrowser;
 
             let b = document.createElementNS(NS_XUL, "browser");
+            b.permanentKey = {};
             b.setAttribute("type", "content-targetable");
             b.setAttribute("message", "true");
             b.setAttribute("messagemanagergroup", "browsers");
             b.setAttribute("contextmenu", this.getAttribute("contentcontextmenu"));
             b.setAttribute("tooltip", this.getAttribute("contenttooltip"));
 
             if (remote)
               b.setAttribute("remote", "true");
@@ -1733,18 +1729,16 @@
             t.setAttribute("onerror", "this.removeAttribute('image');");
             t.className = "tabbrowser-tab";
 
             // The new browser should be remote if this is an e10s window and
             // the uri to load can be loaded remotely.
             let remote = gMultiProcessBrowser &&
                          !aForceNotRemote &&
                          E10SUtils.canLoadURIInProcess(aURI, Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT);
-            if (remote)
-              t.setAttribute("remote", "true");
 
             this.tabContainer._unlockTabSizing();
 
             // When overflowing, new tabs are scrolled into view smoothly, which
             // doesn't go well together with the width transition. So we skip the
             // transition in that case.
             let animate = !aSkipAnimation &&
                           this.tabContainer.getAttribute("overflow") != "true" &&
@@ -2489,16 +2483,21 @@
             filter.removeProgressListener(tabListener);
 
             // Make sure to unregister any open URIs.
             this._swapRegisteredOpenURIs(ourBrowser, aOtherBrowser);
 
             // Swap the docshells
             ourBrowser.swapDocShells(aOtherBrowser);
 
+            // Swap permanentKey properties.
+            let ourPermanentKey = ourBrowser.permanentKey;
+            ourBrowser.permanentKey = aOtherBrowser.permanentKey;
+            aOtherBrowser.permanentKey = ourPermanentKey;
+
             // Restore the progress listener
             this.mTabListeners[index] = tabListener =
               this.mTabProgressListener(aOurTab, ourBrowser, false);
 
             const notifyAll = Ci.nsIWebProgress.NOTIFY_ALL;
             filter.addProgressListener(tabListener, notifyAll);
             ourBrowser.webProgress.addProgressListener(filter, notifyAll);
           ]]>
@@ -2987,18 +2986,16 @@
             // removed from the set upon MozAfterPaint.
             maybeVisibleTabs: new Set([this.selectedTab]),
 
             STATE_UNLOADED: 0,
             STATE_LOADING: 1,
             STATE_LOADED: 2,
             STATE_UNLOADING: 3,
 
-            logging: false,
-
             getTabState: function(tab) {
               let state = this.tabState.get(tab);
               if (state === undefined) {
                 return this.STATE_UNLOADED;
               }
               return state;
             },
 
@@ -3090,26 +3087,28 @@
               } else {
                 // Show the requested tab. If it's not available, we'll show the spinner.
                 showTab = this.requestedTab;
               }
 
               // Show or hide the spinner as needed.
               let needSpinner = this.getTabState(showTab) != this.STATE_LOADED;
               if (!needSpinner && this.spinnerTab) {
+                this.spinnerHidden();
                 this.tabbrowser.removeAttribute("pendingpaint");
                 this.spinnerTab.linkedBrowser.removeAttribute("pendingpaint");
                 this.spinnerTab = null;
               } else if (needSpinner && this.spinnerTab !== showTab) {
                 if (this.spinnerTab) {
                   this.spinnerTab.linkedBrowser.removeAttribute("pendingpaint");
                 }
                 this.spinnerTab = showTab;
                 this.tabbrowser.setAttribute("pendingpaint", "true");
                 this.spinnerTab.linkedBrowser.setAttribute("pendingpaint", "true");
+                this.spinnerDisplayed();
               }
 
               // Switch to the tab we've decided to make visible.
               if (this.visibleTab !== showTab) {
                 this.visibleTab = showTab;
 
                 this.maybeVisibleTabs.add(showTab);
 
@@ -3282,16 +3281,17 @@
               }
             },
 
             // Fires when we paint the screen. Any tab switches we initiated
             // previously are done, so there's no need to keep the old layers
             // around.
             onPaint: function() {
               this.maybeVisibleTabs.clear();
+              this.finishTabSwitch();
             },
 
             // Called when we're done clearing the layers for a tab.
             onLayersCleared: function(browser) {
               this.logState("onLayersCleared");
 
               let tab = this.tabbrowser.getTabForBrowser(browser);
               if (tab) {
@@ -3315,16 +3315,17 @@
 
             // Called when the user asks to switch to a given tab.
             requestTab: function(tab) {
               if (tab === this.requestedTab) {
                 return;
               }
 
               this.logState("requestTab " + this.tinfo(tab));
+              this.startTabSwitch();
 
               this.requestedTab = tab;
 
               this.preActions();
 
               clearTimeout(this.unloadTimer);
               this.unloadTimer = setTimeout(() => this.onUnloadTimeout(), this.UNLOAD_DELAY);
 
@@ -3342,50 +3343,125 @@
                 this.onLayersCleared(event.originalTarget);
               } else if (event.type == "TabRemotenessChange") {
                 this.onRemotenessChange(event.target);
               }
 
               this.postActions();
             },
 
+            /*
+             * Telemetry and Profiler related helpers for recording tab switch
+             * timing.
+             */
+
+            startTabSwitch: function () {
+              TelemetryStopwatch.start("FX_TAB_SWITCH_TOTAL_E10S_MS", window);
+              this.addMarker("AsyncTabSwitch:Start");
+            },
+
+            finishTabSwitch: function () {
+              if (this.requestedTab && this.getTabState(this.requestedTab) == this.STATE_LOADED) {
+                let time = TelemetryStopwatch.timeElapsed("FX_TAB_SWITCH_TOTAL_E10S_MS", window);
+                if (time != -1) {
+                  TelemetryStopwatch.finish("FX_TAB_SWITCH_TOTAL_E10S_MS", window);
+                  this.log("DEBUG: tab switch time = " + time);
+                  this.addMarker("AsyncTabSwitch:Finish");
+                }
+              }
+            },
+
+            spinnerDisplayed: function () {
+              if (this.spinnerTab) {
+                TelemetryStopwatch.start("FX_TAB_SWITCH_SPINNER_VISIBLE_MS", window);
+                this.addMarker("AsyncTabSwitch:SpinnerShown");
+              }
+            },
+
+            spinnerHidden: function () {
+              if (this.spinnerTab) {
+                this.log("DEBUG: spinner time = " +
+                         TelemetryStopwatch.timeElapsed("FX_TAB_SWITCH_SPINNER_VISIBLE_MS", window));
+                TelemetryStopwatch.finish("FX_TAB_SWITCH_SPINNER_VISIBLE_MS", window);
+                this.addMarker("AsyncTabSwitch:SpinnerHidden");
+                // we do not get a onPaint after displaying the spinner
+                this.finishTabSwitch();
+              }
+            },
+
+            addMarker: function(marker) {
+              if (Services.profiler) {
+                Services.profiler.AddMarker(marker);
+              }
+            },
+
+            /*
+             * Debug related logging for switcher.
+             */
+
+            _useDumpForLogging: false,
+            _logInit: false,
+
+            logging: function () {
+              if (this._useDumpForLogging)
+                return true;
+              if (this._logInit)
+                return this._shouldLog;
+              let result = false;
+              try {
+                result = Services.prefs.getBoolPref("browser.tabs.remote.logSwitchTiming");
+              } catch (ex) {
+              }
+              this._shouldLog = result;
+              this._logInit = true;
+              return this._shouldLog;
+            },
+
             tinfo: function(tab) {
               if (tab) {
                 return tab._tPos + "(" + tab.linkedBrowser.currentURI.spec + ")";
               } else {
                 return "null";
               }
             },
 
             log: function(s) {
-              if (!this.logging)
+              if (!this.logging())
                 return;
-              dump(s + "\n");
+              if (this._useDumpForLogging) {
+                dump(s + "\n");
+              } else {
+                Services.console.logStringMessage(s);
+              }
             },
 
             logState: function(prefix) {
-              if (!this.logging)
+              if (!this.logging())
                 return;
 
-              dump(prefix + " ");
+              let accum = prefix + " ";
               for (let i = 0; i < this.tabbrowser.tabs.length; i++) {
                 let tab = this.tabbrowser.tabs[i];
                 let state = this.getTabState(tab);
 
-                dump(i + ":");
+                accum += i + ":";
                 if (tab === this.lastVisibleTab) dump("V");
                 if (tab === this.loadingTab) dump("L");
                 if (tab === this.requestedTab) dump("R");
                 if (state == this.STATE_LOADED) dump("(+)");
                 if (state == this.STATE_LOADING) dump("(+?)");
                 if (state == this.STATE_UNLOADED) dump("(-)");
                 if (state == this.STATE_UNLOADING) dump("(-?)");
-                dump(" ");
+                accum += " ";
               }
-              dump("\n");
+              if (this._useDumpForLogging) {
+                dump(accum + "\n");
+              } else {
+                Services.console.logStringMessage(accum);
+              }
             },
           };
           this._switcher = switcher;
           switcher.init();
           return switcher;
         ]]></body>
       </method>
 
@@ -3677,19 +3753,21 @@
         <parameter name="event"/>
         <body><![CDATA[
           event.stopPropagation();
           var tab = document.tooltipNode;
           if (tab.localName != "tab") {
             event.preventDefault();
             return;
           }
-          event.target.setAttribute("label", tab.mOverCloseButton ?
-                                             tab.getAttribute("closetabtext") :
-                                             tab.getAttribute("label"));
+          event.target.setAttribute("label",
+                                    tab.mOverCloseButton ?
+                                    tab.getAttribute("closetabtext") :
+                                    tab.getAttribute("label") +
+                                      (this.AppConstants.E10S_TESTING_ONLY && tab.linkedBrowser && tab.linkedBrowser.isRemoteBrowser ? " - e10s" : ""));
         ]]></body>
       </method>
 
       <method name="handleEvent">
         <parameter name="aEvent"/>
         <body><![CDATA[
           switch (aEvent.type) {
             case "keydown":
@@ -3755,16 +3833,17 @@
                                           documentURIObject: documentURIObject,
                                           docLocation: aMessage.data.docLocation,
                                           charSet: aMessage.data.charSet,
                                           referrer: aMessage.data.referrer,
                                           referrerPolicy: aMessage.data.referrerPolicy,
                                           contentType: aMessage.data.contentType,
                                           contentDisposition: aMessage.data.contentDisposition,
                                           frameOuterWindowID: aMessage.data.frameOuterWindowID,
+                                          selectionInfo: aMessage.data.selectionInfo,
                                         };
               let popup = browser.ownerDocument.getElementById("contentAreaContextMenu");
               let event = gContextMenuContentData.event;
               popup.openPopupAtScreen(event.screenX, event.screenY, true);
               break;
             }
             case "DOMWebNotificationClicked": {
               let tab = this.getTabForBrowser(browser);
@@ -3794,16 +3873,17 @@
           }
         ]]></body>
       </method>
 
       <constructor>
         <![CDATA[
           let browserStack = document.getAnonymousElementByAttribute(this, "anonid", "browserStack");
           this.mCurrentBrowser = document.getAnonymousElementByAttribute(this, "anonid", "initialBrowser");
+          this.mCurrentBrowser.permanentKey = {};
 
           this.mCurrentTab = this.tabContainer.firstChild;
           const nsIEventListenerService =
             Components.interfaces.nsIEventListenerService;
           let els = Components.classes["@mozilla.org/eventlistenerservice;1"]
                               .getService(nsIEventListenerService);
           els.addSystemEventListener(document, "keydown", this, false);
           if (this.AppConstants.platform == "macosx") {
--- a/browser/base/content/test/chat/browser_chatwindow.js
+++ b/browser/base/content/test/chat/browser_chatwindow.js
@@ -1,40 +1,16 @@
 /* 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/. */
 
 Components.utils.import("resource://gre/modules/Promise.jsm", this);
 
 let chatbar = document.getElementById("pinnedchats");
 
-function waitForCondition(condition, errorMsg) {
-  let deferred = Promise.defer();
-  var tries = 0;
-  var interval = setInterval(function() {
-    if (tries >= 30) {
-      ok(false, errorMsg);
-      moveOn();
-    }
-    var conditionPassed;
-    try {
-      conditionPassed = condition();
-    } catch (e) {
-      ok(false, e + "\n" + e.stack);
-      conditionPassed = false;
-    }
-    if (conditionPassed) {
-      moveOn();
-    }
-    tries++;
-  }, 100);
-  var moveOn = function() { clearInterval(interval); deferred.resolve(); };
-  return deferred.promise;
-}
-
 add_chat_task(function* testOpenCloseChat() {
   let chatbox = yield promiseOpenChat("http://example.com");
   Assert.strictEqual(chatbox, chatbar.selectedChat);
   // we requested a "normal" chat, so shouldn't be minimized
   Assert.ok(!chatbox.minimized, "chat is not minimized");
   Assert.equal(chatbar.childNodes.length, 1, "should be 1 chat open");
 
 
@@ -110,56 +86,48 @@ add_chat_task(function* testSecondTopLev
   yield promiseOneEvent(secondWindow, "load");
   yield promiseOpenChat(chatUrl);
   // the chat was created - let's make sure it was created in the second window.
   Assert.equal(numChatsInWindow(window), 0, "main window has no chats");
   Assert.equal(numChatsInWindow(secondWindow), 1, "second window has 1 chat");
   secondWindow.close();
 });
 
-// Test that chats are created in the correct window.
+// Test that findChromeWindowForChats() returns the expected window.
 add_chat_task(function* testChatWindowChooser() {
   let chat = yield promiseOpenChat("http://example.com");
   Assert.equal(numChatsInWindow(window), 1, "first window has the chat");
   // create a second window - this will be the "most recent" and will
   // therefore be the window that hosts the new chat (see bug 835111)
   let secondWindow = OpenBrowserWindow();
   yield promiseOneEvent(secondWindow, "load");
   Assert.equal(secondWindow, Chat.findChromeWindowForChats(null), "Second window is the preferred chat window");
-  Assert.equal(numChatsInWindow(secondWindow), 0, "second window starts with no chats");
-  yield promiseOpenChat("http://example.com#2");
-  Assert.equal(numChatsInWindow(secondWindow), 1, "second window now has chats");
-  Assert.equal(numChatsInWindow(window), 1, "first window still has 1 chat");
-  chat.close();
 
-  // a bit heavy handed, but handy fixing bug 1090633
-  yield waitForCondition(function () !chat.parentNode, "chat has been detached");
-  Assert.equal(numChatsInWindow(window), 0, "first window now has no chats");
-  // now open another chat - it should still open in the second.
-  yield promiseOpenChat("http://example.com#3");
-  Assert.equal(numChatsInWindow(window), 0, "first window still has no chats");
-  Assert.equal(numChatsInWindow(secondWindow), 2, "second window has both chats");
+  // focus the first window, and check it will be selected for future chats.
+  // Bug 1090633 - there are lots of issues around focus, especially when the
+  // browser itself doesn't have focus. We can end up with
+  // Services.wm.getMostRecentWindow("navigator:browser") returning a different
+  // window than, say, Services.focus.activeWindow. But the focus manager isn't
+  // the point of this test.
+  // So we simply keep focusing the first window until it is reported as the
+  // most recent.
+  do {
+    dump("trying to force window to become the most recent.\n");
+    secondWindow.focus();
+    window.focus();
+    yield promiseWaitForFocus();
+  } while (Services.wm.getMostRecentWindow("navigator:browser") != window)
 
-  // focus the first window, and open yet another chat - it
-  // should open in the first window.
-  window.focus();
-  yield promiseWaitForFocus();
-  chat = yield promiseOpenChat("http://example.com#4");
-  Assert.equal(numChatsInWindow(window), 1, "first window got new chat");
-  chat.close();
-  Assert.equal(numChatsInWindow(window), 0, "first window has no chats");
+  Assert.equal(window, Chat.findChromeWindowForChats(null), "First window now the preferred chat window");
 
   let privateWindow = OpenBrowserWindow({private: true});
   yield promiseOneEvent(privateWindow, "load")
 
-  // open a last chat - the focused window can't accept
-  // chats (it's a private window), so the chat should open
-  // in the window that was selected before. This is known
-  // to be broken on Linux.
-  chat = yield promiseOpenChat("http://example.com#5");
-  let os = Services.appinfo.OS;
-  const BROKEN_WM_Z_ORDER = os != "WINNT" && os != "Darwin";
-  let fn = BROKEN_WM_Z_ORDER ? todo : ok;
-  fn(numChatsInWindow(window) == 1, "first window got the chat");
-  chat.close();
+  // The focused window can't accept chats (it's a private window), so the
+  // chat should open in the window that was selected before. This will be
+  // either window or secondWindow (linux may choose a different one) but the
+  // point is that the window is *not* the private one.
+  Assert.ok(Chat.findChromeWindowForChats(null) == window ||
+            Chat.findChromeWindowForChats(null) == secondWindow,
+            "Private window isn't selected for new chats.");
   privateWindow.close();
   secondWindow.close();
 });
--- a/browser/base/content/test/chat/browser_focus.js
+++ b/browser/base/content/test/chat/browser_focus.js
@@ -5,22 +5,26 @@
 // Tests the focus functionality.
 
 Components.utils.import("resource://gre/modules/Promise.jsm", this);
 const CHAT_URL = "https://example.com/browser/browser/base/content/test/chat/chat.html";
 
 // Is the currently opened tab focused?
 function isTabFocused() {
   let tabb = gBrowser.getBrowserForTab(gBrowser.selectedTab);
-  return Services.focus.focusedWindow == tabb.contentWindow;
+  // focus sucks in tests - our window may have lost focus.
+  let elt = Services.focus.getFocusedElementForWindow(window, false, {});
+  return elt == tabb;
 }
 
 // Is the specified chat focused?
 function isChatFocused(chat) {
-  return chat.chatbar._isChatFocused(chat);
+  // focus sucks in tests - our window may have lost focus.
+  let elt = Services.focus.getFocusedElementForWindow(window, false, {});
+  return elt == chat.content;
 }
 
 let chatbar = document.getElementById("pinnedchats");
 
 function* setUp() {
   // Note that (probably) due to bug 604289, if a tab is focused but the
   // focused element is null, our chat windows can "steal" focus.  This is
   // avoided if we explicitly focus an element in the tab.
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -8,17 +8,17 @@ support-files =
   authenticate.sjs
   aboutHome_content_script.js
   browser_bug479408_sample.html
   browser_bug678392-1.html
   browser_bug678392-2.html
   browser_bug970746.xhtml
   browser_fxa_oauth.html
   browser_fxa_oauth_with_keys.html
-  browser_fxa_profile_channel.html
+  browser_fxa_web_channel.html
   browser_registerProtocolHandler_notification.html
   browser_ssl_error_reports_content.js
   browser_star_hsts.sjs
   browser_tab_dragdrop2_frame1.xul
   browser_web_channel.html
   bug592338.html
   bug792517-2.html
   bug792517.html
@@ -146,85 +146,77 @@ skip-if = buildapp == 'mulet' || toolkit
 [browser_bug304198.js]
 [browser_bug321000.js]
 skip-if = true # browser_bug321000.js is disabled because newline handling is shaky (bug 592528)
 [browser_bug329212.js]
 [browser_bug331772_xul_tooltiptext_in_html.js]
 [browser_bug356571.js]
 [browser_bug380960.js]
 [browser_bug386835.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug405137.js]
 [browser_bug406216.js]
 [browser_bug409481.js]
 [browser_bug409624.js]
 [browser_bug413915.js]
 [browser_bug416661.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug417483.js]
 skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode
 [browser_bug419612.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug422590.js]
 [browser_bug423833.js]
 skip-if = true # bug 428712
 [browser_bug424101.js]
-skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode
 [browser_bug427559.js]
 [browser_bug431826.js]
 [browser_bug432599.js]
 [browser_bug435035.js]
 [browser_bug435325.js]
 skip-if = buildapp == 'mulet' || e10s # Bug 1099156 - test directly manipulates content
 [browser_bug441778.js]
-skip-if = buildapp == 'mulet' || e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
+skip-if = buildapp == 'mulet'
 [browser_bug455852.js]
 [browser_bug460146.js]
-skip-if = e10s # Bug 866413 - PageInfo doesn't work in e10s
 [browser_bug462289.js]
 skip-if = toolkit == "cocoa" || e10s # Bug 1102017 - middle-button mousedown on selected tab2 does not activate tab - Didn't expect [object XULElement], but got it
 [browser_bug462673.js]
 [browser_bug477014.js]
 [browser_bug479408.js]
 skip-if = buildapp == 'mulet'
 [browser_bug481560.js]
 [browser_bug484315.js]
 [browser_bug491431.js]
 skip-if = buildapp == 'mulet'
 [browser_bug495058.js]
 [browser_bug517902.js]
-skip-if = e10s # Bug 866413 - PageInfo doesn't work in e10s
 [browser_bug519216.js]
 [browser_bug520538.js]
 [browser_bug521216.js]
 [browser_bug533232.js]
 [browser_bug537013.js]
 skip-if = buildapp == 'mulet' || e10s # Bug 1134458 - Find bar doesn't work correctly in a detached tab
 [browser_bug537474.js]
 skip-if = e10s # Bug 1102020 - test tries to use browserDOMWindow.openURI to open a link, and gets a null rv where it expects a window
 [browser_bug550565.js]
 [browser_bug553455.js]
 skip-if = buildapp == 'mulet' # Bug 1066070 - I don't think either popup notifications nor addon install stuff works on mulet?
 [browser_bug555224.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug555767.js]
 skip-if = e10s # Bug 1093373 - relies on browser.sessionHistory
 [browser_bug556061.js]
 [browser_bug559991.js]
 [browser_bug561623.js]
 [browser_bug561636.js]
 [browser_bug562649.js]
 [browser_bug563588.js]
 [browser_bug565575.js]
 [browser_bug565667.js]
 skip-if = toolkit != "cocoa"
 [browser_bug567306.js]
 [browser_bug575561.js]
 [browser_bug575830.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug577121.js]
 [browser_bug578534.js]
 [browser_bug579872.js]
 [browser_bug580638.js]
 [browser_bug580956.js]
 [browser_bug581242.js]
 [browser_bug581253.js]
 skip-if = e10s # Bug 1093756 - can't bookmark the data: url in e10s somehow
@@ -241,26 +233,25 @@ skip-if = e10s # Bug 653065 - Make the l
 [browser_bug597218.js]
 [browser_bug609700.js]
 [browser_bug623155.js]
 skip-if = e10s && debug
 [browser_bug623893.js]
 [browser_bug624734.js]
 [browser_bug633691.js]
 [browser_bug647886.js]
-skip-if = buildapp == 'mulet' || e10s # Bug 1093373 - Relies on browser.sessionHistory
+skip-if = buildapp == 'mulet'
 [browser_bug655584.js]
 [browser_bug664672.js]
 [browser_bug676619.js]
 skip-if = buildapp == 'mulet' || os == "mac" # mac: Intermittent failures, bug 925225
 [browser_bug678392.js]
 skip-if = e10s # bug 1102331 - does focus things on the content window which break in e10s mode
 [browser_bug710878.js]
 [browser_bug719271.js]
-skip-if = e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
 [browser_bug724239.js]
 [browser_bug734076.js]
 skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode
 [browser_bug735471.js]
 [browser_bug749738.js]
 [browser_bug763468_perwindowpb.js]
 [browser_bug767836_perwindowpb.js]
 [browser_bug771331.js]
@@ -272,19 +263,18 @@ skip-if = e10s # Bug 1093155 - tries to 
 [browser_bug880101.js]
 skip-if = e10s # Bug 1126316 - New e10s windows erroneously fire initial about:blank location through nsIWebProgressListener
 [browser_bug882977.js]
 [browser_bug902156.js]
 [browser_bug906190.js]
 skip-if = buildapp == "mulet" || e10s # Bug 1093642 - test manipulates content and relies on content focus
 [browser_mixedContentFromOnunload.js]
 [browser_bug970746.js]
-skip-if = e10s # Bug 1093155 - tries to use context menu from browser-chrome and gets in a mess when in e10s mode
 [browser_bug1015721.js]
-skip-if = os == 'win' || e10s # Bug 1056146 - zoom tests use FullZoomHelper and break in e10s
+skip-if = os == 'win' || e10s # Bug 1159268 - Need a content-process safe version of synthesizeWheel
 [browser_bug1064280_changeUrlInPinnedTab.js]
 [browser_bug1070778.js]
 [browser_canonizeURL.js]
 skip-if = e10s # Bug 1094510 - test hits the network in e10s mode only
 [browser_clipboard.js]
 [browser_contentAreaClick.js]
 [browser_contextSearchTabPosition.js]
 skip-if = os == "mac" || e10s # bug 967013; e10s: bug 1094761 - test hits the network in e10s, causing next test to crash
@@ -307,17 +297,17 @@ skip-if = true # browser_drag.js is disa
 [browser_favicon_change.js]
 [browser_favicon_change_not_in_document.js]
 skip-if = e10s
 [browser_findbarClose.js]
 [browser_fullscreen-window-open.js]
 skip-if = buildapp == 'mulet' || e10s || os == "linux" # Bug 933103 - mochitest's EventUtils.synthesizeMouse functions not e10s friendly. Linux: Intermittent failures - bug 941575.
 [browser_fxa_migrate.js]
 [browser_fxa_oauth.js]
-[browser_fxa_profile_channel.js]
+[browser_fxa_web_channel.js]
 [browser_gestureSupport.js]
 skip-if = e10s # Bug 863514 - no gesture support.
 [browser_getshortcutoruri.js]
 [browser_hide_removing.js]
 [browser_homeDrop.js]
 skip-if = buildapp == 'mulet'
 [browser_identity_UI.js]
 skip-if = e10s && debug # Seeing lots of timeouts (bug 1095517)
@@ -338,17 +328,17 @@ skip-if = os != "win" # The Fitts Law me
 skip-if = e10s # Bug 1100664 - test directly access content docShells (TypeError: gBrowser.docShell is null)
 [browser_mixedcontent_securityflags.js]
 [browser_notification_tab_switching.js]
 skip-if = buildapp == 'mulet' || e10s # Bug 1100662 - content access causing uncaught exception - Error: cannot ipc non-cpow object at chrome://mochitests/content/browser/browser/base/content/test/general/browser_notification_tab_switching.js:32 (or in RemoteAddonsChild.jsm)
 [browser_offlineQuotaNotification.js]
 skip-if = buildapp == 'mulet' || e10s # Bug 1093603 - test breaks with PopupNotifications.panel.firstElementChild is null
 [browser_overflowScroll.js]
 [browser_pageInfo.js]
-skip-if = buildapp == 'mulet' || e10s # Bug 866413 - PageInfo doesn't work in e10s
+skip-if = buildapp == 'mulet'
 [browser_page_style_menu.js]
 
 [browser_parsable_css.js]
 skip-if = e10s
 [browser_parsable_script.js]
 skip-if = asan # Disabled because it takes a long time (see test for more information)
 
 [browser_pinnedTabs.js]
@@ -431,20 +421,18 @@ support-files =
   benignPage.html
 [browser_typeAheadFind.js]
 skip-if = buildapp == 'mulet' || e10s # Bug 921935 - focusmanager issues with e10s (test calls waitForFocus)
 [browser_unknownContentType_title.js]
 [browser_unloaddialogs.js]
 skip-if = e10s # Bug 1100700 - test relies on unload event firing on closed tabs, which it doesn't
 [browser_urlHighlight.js]
 [browser_urlbarAutoFillTrimURLs.js]
-skip-if = e10s # Bug 1093941 - Waits indefinitely for onSearchComplete
 [browser_urlbarCopying.js]
 [browser_urlbarEnter.js]
-skip-if = e10s # Bug 1093941 - used to cause obscure non-windows child process crashes on try
 [browser_urlbarEnterAfterMouseOver.js]
 skip-if = os == "linux" || e10s # Bug 1073339 - Investigate autocomplete test unreliability on Linux/e10s
 [browser_urlbarRevert.js]
 [browser_urlbarSearchSingleWordNotification.js]
 [browser_urlbarStop.js]
 [browser_urlbarTrimURLs.js]
 [browser_urlbar_search_healthreport.js]
 [browser_utilityOverlay.js]
@@ -484,8 +472,9 @@ skip-if = e10s # bug 1100687 - test dire
 [browser_contextmenu_childprocess.js]
 [browser_bug963945.js]
 [browser_readerMode.js]
 support-files =
   readerModeArticle.html
 [browser_bug1124271_readerModePinnedTab.js]
 support-files =
   readerModeArticle.html
+[browser_domFullscreen_fullscreenMode.js]
--- a/browser/base/content/test/general/browser_bug424101.js
+++ b/browser/base/content/test/general/browser_bug424101.js
@@ -1,53 +1,52 @@
 /* Make sure that the context menu appears on form elements */
 
-function test() {
-  waitForExplicitFinish();
+add_task(function *() {
+  yield BrowserTestUtils.openNewForegroundTab(gBrowser, "data:text/html,test");
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  
-  gBrowser.selectedBrowser.addEventListener("load", function() {
-    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+  let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
 
-    let doc = gBrowser.contentDocument;
-    let testInput = function(type, expected) {
-      let element = doc.createElement("input");
-      element.setAttribute("type", type);
-      doc.body.appendChild(element);
-      document.popupNode = element;
+  let tests = [
+    { element: "input", type: "text" },
+    { element: "input", type: "password" },
+    { element: "input", type: "image" },
+    { element: "input", type: "button" },
+    { element: "input", type: "submit" },
+    { element: "input", type: "reset" },
+    { element: "input", type: "checkbox" },
+    { element: "input", type: "radio" },
+    { element: "button" },
+    { element: "select" },
+    { element: "option" },
+    { element: "optgroup" }
+  ];
 
-      let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
-      let contextMenu = new nsContextMenu(contentAreaContextMenu);
-
-      is(contextMenu.shouldDisplay, expected, "context menu behavior for <input type=" + type + "> is wrong");
-    };
-    let testElement = function(tag, expected) {
-      let element = doc.createElement(tag);
-      doc.body.appendChild(element);
-      document.popupNode = element;
+  for (let index = 0; index < tests.length; index++) {
+    let test = tests[index];
 
-      let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
-      let contextMenu = new nsContextMenu(contentAreaContextMenu);
-
-      is(contextMenu.shouldDisplay, expected, "context menu behavior for <" + tag + "> is wrong");
-    };
+    yield ContentTask.spawn(gBrowser.selectedBrowser,
+                            { element: test.element, type: test.type, index: index },
+                            function* (arg) {
+      let element = content.document.createElement(arg.element);
+      element.id = "element" + arg.index;
+      if (arg.type) {
+        element.setAttribute("type", arg.type);
+      }
+      content.document.body.appendChild(element);
+    });
 
-    testInput("text", true);
-    testInput("password", true);
-    testInput("image", true);
-    testInput("button", true);
-    testInput("submit", true);
-    testInput("reset", true);
-    testInput("checkbox", true);
-    testInput("radio", true);
-    testElement("button", true);
-    testElement("select", true);
-    testElement("option", true);
-    testElement("optgroup", true);
+    let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
+    yield BrowserTestUtils.synthesizeMouseAtCenter("#element" + index,
+          { type: "contextmenu", button: 2}, gBrowser.selectedBrowser);
+    yield popupShownPromise;
 
-    // cleanup
-    document.popupNode = null;
-    gBrowser.removeCurrentTab();
-    finish();
-  }, true);
-  content.location = "data:text/html,test";
-}
+    let typeAttr = test.type ? "type=" + test.type + " " : "";
+    is(gContextMenu.shouldDisplay, true,
+        "context menu behavior for <" + test.element + " " + typeAttr + "> is wrong");
+
+    let popupHiddenPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popuphidden");
+    contentAreaContextMenu.hidePopup();
+    yield popupHiddenPromise;
+  }
+
+  gBrowser.removeCurrentTab();
+});
--- a/browser/base/content/test/general/browser_bug427559.js
+++ b/browser/base/content/test/general/browser_bug427559.js
@@ -1,49 +1,53 @@
-/* This Source Code Form is subject to the terms of the Mozilla Public
- * License, v. 2.0. If a copy of the MPL was not distributed with this
- * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
+"use strict";
 
 /*
  * Test bug 427559 to make sure focused elements that are no longer on the page
  * will have focus transferred to the window when changing tabs back to that
  * tab with the now-gone element.
  */
 
-// Default focus on a button and have it kill itself on blur
-let testPage = 'data:text/html,<body><button onblur="this.parentNode.removeChild(this);"><script>document.body.firstChild.focus();</script></body>';
-
-function test() {
-  waitForExplicitFinish();
-
-  gBrowser.selectedTab = gBrowser.addTab();
-  var browser = gBrowser.selectedBrowser;
+// Default focus on a button and have it kill itself on blur.
+const URL = 'data:text/html;charset=utf-8,' +
+            '<body><button onblur="this.remove()">' +
+            '<script>document.body.firstChild.focus()</script></body>';
 
-  browser.addEventListener("load", function () {
-    browser.removeEventListener("load", arguments.callee, true);
-    executeSoon(function () {
-      var testPageWin = content;
+function getFocusedLocalName(browser) {
+  return ContentTask.spawn(browser, null, function* () {
+    return content.document.activeElement.localName;
+  });
+}
 
-      is(browser.contentDocumentAsCPOW.activeElement.localName, "button", "button is focused");
+add_task(function* () {
+  gBrowser.selectedTab = gBrowser.addTab(URL);
+  let browser = gBrowser.selectedBrowser;
+  yield BrowserTestUtils.browserLoaded(browser);
 
-      addEventListener("focus", function focusedWindow(event) {
-        if (!String(event.target.location).startsWith("data:"))
-          return;
+  is((yield getFocusedLocalName(browser)), "button", "button is focused");
 
-        removeEventListener("focus", focusedWindow, true);
-
-        // Make sure focus is given to the window because the element is now gone
-        is(browser.contentDocumentAsCPOW.activeElement.localName, "body", "body is focused");
-
-        gBrowser.removeCurrentTab();
-        finish();
-      }, true);
+  let promiseFocused = ContentTask.spawn(browser, null, function* () {
+    return new Promise(resolve => {
+      content.addEventListener("focus", function onFocus({target}) {
+        if (String(target.location).startsWith("data:")) {
+          content.removeEventListener("focus", onFocus);
+          resolve();
+        }
+      });
+    });
+  });
 
-      // The test page loaded, so open an empty tab, select it, then restore
-      // the test tab. This causes the test page's focused element to be removed
-      // from its document.
-      gBrowser.selectedTab = gBrowser.addTab();
-      gBrowser.removeCurrentTab();
-    });
-  }, true);
+  // The test page loaded, so open an empty tab, select it, then restore
+  // the test tab. This causes the test page's focused element to be removed
+  // from its document.
+  gBrowser.selectedTab = gBrowser.addTab("about:blank");
+  yield BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
+  gBrowser.removeCurrentTab();
 
-  content.location = testPage;
-}
+  // Wait until the original tab is focused again.
+  yield promiseFocused;
+
+  // Make sure focus is given to the window because the element is now gone.
+  is((yield getFocusedLocalName(browser)), "body", "body is focused");
+
+  // Cleanup.
+  gBrowser.removeCurrentTab();
+});
--- a/browser/base/content/test/general/browser_bug580956.js
+++ b/browser/base/content/test/general/browser_bug580956.js
@@ -14,14 +14,14 @@ function test() {
   is(numClosedTabs(), 0, "There should be 0 closed tabs.");
   ok(!isUndoCloseEnabled(), "Undo Close Tab should be disabled.");
 
   var tab = gBrowser.addTab("http://mochi.test:8888/");
   var browser = gBrowser.getBrowserForTab(tab);
   browser.addEventListener("load", function() {
     browser.removeEventListener("load", arguments.callee, true);
 
-    gBrowser.removeTab(tab);
-    ok(isUndoCloseEnabled(), "Undo Close Tab should be enabled.");
-
-    finish();
+    BrowserTestUtils.removeTab(tab).then(() => {
+      ok(isUndoCloseEnabled(), "Undo Close Tab should be enabled.");
+      finish();
+    });
   }, true);
 }
--- a/browser/base/content/test/general/browser_bug623155.js
+++ b/browser/base/content/test/general/browser_bug623155.js
@@ -110,17 +110,17 @@ function delayed(aIsSelectedTab) {
 
   ok(isRedirectedURISpec(content.location.href),
      "The content area is redirected. aIsSelectedTab:" + aIsSelectedTab);
   is(gURLBar.value, content.location.href,
      "The URL bar shows the content URI. aIsSelectedTab:" + aIsSelectedTab);
 
   if (!aIsSelectedTab) {
     // If this was a background request, go on a foreground request.
-    content.location = REDIRECT_FROM + "#FG";
+    gBrowser.selectedBrowser.loadURI(REDIRECT_FROM + "#FG");
   }
   else {
     // Othrewise, nothing to do remains.
     finish();
   }
 }
 
 /* Cleanup */
--- a/browser/base/content/test/general/browser_bug647886.js
+++ b/browser/base/content/test/general/browser_bug647886.js
@@ -1,36 +1,25 @@
 /* Any copyright is dedicated to the Public Domain.
    http://creativecommons.org/publicdomain/zero/1.0/ */
 
-function test() {
-  waitForExplicitFinish();
+add_task(function* () {
+  yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com");
 
-  gBrowser.selectedTab = gBrowser.addTab();
-  gBrowser.selectedBrowser.addEventListener("load", function () {
-    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
-
+  yield ContentTask.spawn(gBrowser.selectedBrowser, {}, function* () {
     content.history.pushState({}, "2", "2.html");
-
-    testBackButton();
-  }, true);
+  });
 
-  loadURI("http://example.com");
-}
-
-function testBackButton() {
   var backButton = document.getElementById("back-button");
   var rect = backButton.getBoundingClientRect();
 
   info("waiting for the history menu to open");
 
-  backButton.addEventListener("popupshown", function (event) {
-    backButton.removeEventListener("popupshown", arguments.callee, false);
-
-    ok(true, "history menu opened");
-    event.target.hidePopup();
-    gBrowser.removeTab(gBrowser.selectedTab);
-    finish();
-  }, false);
-
+  let popupShownPromise = BrowserTestUtils.waitForEvent(backButton, "popupshown");
   EventUtils.synthesizeMouseAtCenter(backButton, {type: "mousedown"});
   EventUtils.synthesizeMouse(backButton, rect.width / 2, rect.height, {type: "mouseup"});
-}
+  let event = yield popupShownPromise;
+
+  ok(true, "history menu opened");
+
+  event.target.hidePopup();
+  gBrowser.removeTab(gBrowser.selectedTab);
+});
--- a/browser/base/content/test/general/browser_bug817947.js
+++ b/browser/base/content/test/general/browser_bug817947.js
@@ -29,24 +29,25 @@ function test() {
     });
   });
 }
 
 function preparePendingTab(aCallback) {
   let tab = gBrowser.addTab(URL);
 
   whenLoaded(tab.linkedBrowser, function () {
-    gBrowser.removeTab(tab);
-    let [{state}] = JSON.parse(SessionStore.getClosedTabData(window));
+    BrowserTestUtils.removeTab(tab).then(() => {
+      let [{state}] = JSON.parse(SessionStore.getClosedTabData(window));
 
-    tab = gBrowser.addTab("about:blank");
-    whenLoaded(tab.linkedBrowser, function () {
-      SessionStore.setTabState(tab, JSON.stringify(state));
-      ok(tab.hasAttribute("pending"), "tab should be pending");
-      aCallback(tab);
+      tab = gBrowser.addTab("about:blank");
+      whenLoaded(tab.linkedBrowser, function () {
+        SessionStore.setTabState(tab, JSON.stringify(state));
+        ok(tab.hasAttribute("pending"), "tab should be pending");
+        aCallback(tab);
+      });
     });
   });
 }
 
 function whenLoaded(aElement, aCallback) {
   aElement.addEventListener("load", function onLoad() {
     aElement.removeEventListener("load", onLoad, true);
     executeSoon(aCallback);
--- a/browser/base/content/test/general/browser_bug839103.js
+++ b/browser/base/content/test/general/browser_bug839103.js
@@ -13,17 +13,17 @@ function test() {
 }
 
 function initialStylesheetAdded(evt) {
   gBrowser.removeEventListener("StyleSheetAdded", initialStylesheetAdded, true);
   ok(true, "received initial style sheet event");
   is(evt.type, "StyleSheetAdded", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
   ok(evt.documentSheet, "style sheet is a document sheet");
 }
 
 function tabLoad(evt) {
   gTab.linkedBrowser.removeEventListener(evt.type, tabLoad, true);
   executeSoon(continueTest);
 }
 
@@ -58,17 +58,17 @@ function continueTest() {
 }
 
 function dynamicStylesheetAdded(evt) {
   gBrowser.removeEventListener("StyleSheetAdded", dynamicStylesheetAdded, true);
   ok(true, "received dynamic style sheet event");
   is(evt.type, "StyleSheetAdded", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
   ok(evt.documentSheet, "style sheet is a document sheet");
 }
 
 function dynamicStylesheetApplicableStateChanged(evt) {
   gBrowser.removeEventListener("StyleSheetApplicableStateChanged", dynamicStylesheetApplicableStateChanged, true);
   ok(true, "received dynamic style sheet applicable state change event");
   is(evt.type, "StyleSheetApplicableStateChanged", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
@@ -92,58 +92,58 @@ function dynamicStylesheetApplicableStat
 }
 
 function dynamicStylesheetRemoved(evt) {
   gBrowser.removeEventListener("StyleSheetRemoved", dynamicStylesheetRemoved, true);
   ok(true, "received dynamic style sheet removal");
   is(evt.type, "StyleSheetRemoved", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
-  ok(evt.stylesheet.href.contains(gStyleSheet), "evt.stylesheet is the removed stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.href.includes(gStyleSheet), "evt.stylesheet is the removed stylesheet");
 
   gBrowser.addEventListener("StyleRuleAdded", styleRuleAdded, true);
   gBrowser.contentDocument.querySelector("style").sheet.insertRule("*{color:black}", 0);
 }
 
 function styleRuleAdded(evt) {
   gBrowser.removeEventListener("StyleRuleAdded", styleRuleAdded, true);
   ok(true, "received style rule added event");
   is(evt.type, "StyleRuleAdded", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
   ok(evt.rule, "evt.rule is defined");
   is(evt.rule.cssText, "* { color: black; }", "evt.rule.cssText has expected value");
 
   gBrowser.addEventListener("StyleRuleChanged", styleRuleChanged, true);
   evt.rule.style.cssText = "color:green";
 }
 
 function styleRuleChanged(evt) {
   gBrowser.removeEventListener("StyleRuleChanged", styleRuleChanged, true);
   ok(true, "received style rule changed event");
   is(evt.type, "StyleRuleChanged", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
   ok(evt.rule, "evt.rule is defined");
   is(evt.rule.cssText, "* { color: green; }", "evt.rule.cssText has expected value");
 
   gBrowser.addEventListener("StyleRuleRemoved", styleRuleRemoved, true);
   evt.stylesheet.deleteRule(0);
 }
 
 function styleRuleRemoved(evt) {
   gBrowser.removeEventListener("StyleRuleRemoved", styleRuleRemoved, true);
   ok(true, "received style rule removed event");
   is(evt.type, "StyleRuleRemoved", "evt.type has expected value");
   is(evt.target, gBrowser.contentDocument, "event targets correct document");
   ok(evt.stylesheet, "evt.stylesheet is defined");
-  ok(evt.stylesheet.toString().contains("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
+  ok(evt.stylesheet.toString().includes("CSSStyleSheet"), "evt.stylesheet is a stylesheet");
   ok(evt.rule, "evt.rule is defined");
 
   executeSoon(concludeTest);
 }
 
 function concludeTest() {
   let doc = gBrowser.contentDocument;
   doc.removeEventListener("StyleSheetAdded", unexpectedContentEvent, false);
--- a/browser/base/content/test/general/browser_bug970746.js
+++ b/browser/base/content/test/general/browser_bug970746.js
@@ -1,125 +1,121 @@
 /* Make sure context menu includes option to search hyperlink text on search engine */
 
-function test() {
-  waitForExplicitFinish();
-
-  gBrowser.selectedTab = gBrowser.addTab();
-
-  gBrowser.selectedBrowser.addEventListener("load", function() {
-    gBrowser.selectedBrowser.removeEventListener("load", arguments.callee, true);
+add_task(function *() {
+  const url = "http://mochi.test:8888/browser/browser/base/content/test/general/browser_bug970746.xhtml";
+  yield BrowserTestUtils.openNewForegroundTab(gBrowser, url);
 
-    let doc = gBrowser.contentDocument;
-    let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
-    let ellipsis = "\u2026";
+  const ellipsis = "\u2026";
 
-    // Tests if the "Search <engine> for '<some terms>'" context menu item is shown for the
-    // given query string of an element. Tests to make sure label includes the proper search terms.
-    //
-    // Options:
-    //
-    //   id: The id of the element to test.
-    //   isSelected: Flag to enable selection (text hilight) the contents of the element
-    //   shouldBeShown: The display state of the menu item
-    //   expectedLabelContents: The menu item label should contain a portion of this string.
-    //                          Will only be tested if shouldBeShown is true.
+  let contentAreaContextMenu = document.getElementById("contentAreaContextMenu");
 
-    let testElement = function(opts) {
-      let element = doc.getElementById(opts.id);
-      document.popupNode = element;
-
-      let selection = content.getSelection();
-      selection.removeAllRanges();
-
-      if(opts.isSelected) {
-        selection.selectAllChildren(element);
-      }
-
-      let contextMenu = new nsContextMenu(contentAreaContextMenu);
-      let menuItem = document.getElementById("context-searchselect");
-
-      is(document.getElementById("context-searchselect").hidden, !opts.shouldBeShown, "search context menu item is shown for  '#" + opts.id + "' and selected is '" + opts.isSelected + "'");
-
-      if(opts.shouldBeShown) {
-        ok(menuItem.label.contains(opts.expectedLabelContents), "Menu item text '" + menuItem.label  + "' contains the correct search terms '" + opts.expectedLabelContents  + "'");
-      }
-    }
-
-    testElement({
+  // Tests if the "Search <engine> for '<some terms>'" context menu item is shown for the
+  // given query string of an element. Tests to make sure label includes the proper search terms.
+  //
+  // Each test:
+  //
+  //   id: The id of the element to test.
+  //   isSelected: Flag to enable selecting (text highlight) the contents of the element
+  //   shouldBeShown: The display state of the menu item
+  //   expectedLabelContents: The menu item label should contain a portion of this string.
+  //                          Will only be tested if shouldBeShown is true.
+  let tests = [
+    {
       id: "link",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "I'm a link!",
-    });
-    testElement({
+    },
+    {
       id: "link",
       isSelected: false,
       shouldBeShown: true,
       expectedLabelContents: "I'm a link!",
-    });
-
-    testElement({
+    },
+    {
       id: "longLink",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "I'm a really lo" + ellipsis,
-    });
-    testElement({
+    },
+    {
       id: "longLink",
       isSelected: false,
       shouldBeShown: true,
       expectedLabelContents: "I'm a really lo" + ellipsis,
-    });
-
-    testElement({
+    },
+    {
       id: "plainText",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "Right clicking " + ellipsis,
-    });
-    testElement({
+    },
+    {
       id: "plainText",
       isSelected: false,
       shouldBeShown: false,
-    });
-
-    testElement({
+    },
+    {
       id: "mixedContent",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "I'm some text, " + ellipsis,
-    });
-    testElement({
+    },
+    {
       id: "mixedContent",
       isSelected: false,
       shouldBeShown: false,
-    });
-
-    testElement({
+    },
+    {
       id: "partialLink",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "link selection",
-    });
-
-    testElement({
+    },
+    {
       id: "partialLink",
       isSelected: false,
       shouldBeShown: true,
       expectedLabelContents: "A partial link " + ellipsis,
-    });
-
-    testElement({
+    },
+    {
       id: "surrogatePair",
       isSelected: true,
       shouldBeShown: true,
       expectedLabelContents: "This character\uD83D\uDD25" + ellipsis,
+    }
+  ];
+
+  for (let test of tests) {
+    yield ContentTask.spawn(gBrowser.selectedBrowser,
+                            { selectElement: test.isSelected ? test.id : null },
+                            function* (arg) {
+      let selection = content.getSelection();
+      selection.removeAllRanges();
+
+      if (arg.selectElement) {
+        selection.selectAllChildren(content.document.getElementById(arg.selectElement));
+      }
     });
 
-    // cleanup
-    document.popupNode = null;
-    gBrowser.removeCurrentTab();
-    finish();
-  }, true);
+    let popupShownPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popupshown");
+    yield BrowserTestUtils.synthesizeMouseAtCenter("#" + test.id,
+          { type: "contextmenu", button: 2}, gBrowser.selectedBrowser);
+    yield popupShownPromise;
+
+    let menuItem = document.getElementById("context-searchselect");
+    is(menuItem.hidden, !test.shouldBeShown,
+        "search context menu item is shown for  '#" + test.id + "' and selected is '" + test.isSelected + "'");
 
-  content.location = "http://mochi.test:8888/browser/browser/base/content/test/general/browser_bug970746.xhtml";
-}
+    if (test.shouldBeShown) {
+      ok(menuItem.label.includes(test.expectedLabelContents),
+         "Menu item text '" + menuItem.label  + "' contains the correct search terms '" + test.expectedLabelContents  + "'");
+    }
+
+    let popupHiddenPromise = BrowserTestUtils.waitForEvent(contentAreaContextMenu, "popuphidden");
+    contentAreaContextMenu.hidePopup();
+    yield popupHiddenPromise;
+  }
+
+  // cleanup
+  gBrowser.removeCurrentTab();
+});
--- a/browser/base/content/test/general/browser_devices_get_user_media.js
+++ b/browser/base/content/test/general/browser_devices_get_user_media.js
@@ -149,17 +149,17 @@ function activateSecondaryAction(aAction
       EventUtils.synthesizeKey("VK_DOWN", {});
 
     // Activate
     EventUtils.synthesizeKey("VK_RETURN", {});
   }, false);
 
   // One down event to open the popup
   EventUtils.synthesizeKey("VK_DOWN",
-                           { altKey: !navigator.platform.contains("Mac") });
+                           { altKey: !navigator.platform.includes("Mac") });
 }
 
 registerCleanupFunction(function() {
   gBrowser.removeCurrentTab();
   kObservedTopics.forEach(topic => {
     Services.obs.removeObserver(observer, topic);
   });
   Services.prefs.clearUserPref(PREF_PERMISSION_FAKE);
--- a/browser/base/content/test/general/browser_devices_get_user_media_in_frame.js
+++ b/browser/base/content/test/general/browser_devices_get_user_media_in_frame.js
@@ -143,17 +143,17 @@ function activateSecondaryAction(aAction
       EventUtils.synthesizeKey("VK_DOWN", {});
 
     // Activate
     EventUtils.synthesizeKey("VK_RETURN", {});
   }, false);
 
   // One down event to open the popup
   EventUtils.synthesizeKey("VK_DOWN",
-                           { altKey: !navigator.platform.contains("Mac") });
+                           { altKey: !navigator.platform.includes("Mac") });
 }
 
 registerCleanupFunction(function() {
   gBrowser.removeCurrentTab();
   kObservedTopics.forEach(topic => {
     Services.obs.removeObserver(observer, topic);
   });
   Services.prefs.clearUserPref(PREF_PERMISSION_FAKE);
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/general/browser_domFullscreen_fullscreenMode.js
@@ -0,0 +1,208 @@
+"use strict";
+
+let gMessageManager;
+
+function frameScript() {
+  addMessageListener("Test:RequestFullscreen", () => {
+    content.document.body.mozRequestFullScreen();
+  });
+  addMessageListener("Test:ExitFullscreen", () => {
+    content.document.mozCancelFullScreen();
+  });
+  addMessageListener("Test:QueryFullscreenState", () => {
+    sendAsyncMessage("Test:FullscreenState", {
+      inDOMFullscreen: content.document.mozFullScreen,
+      inFullscreen: content.fullScreen
+    });
+  });
+  content.document.addEventListener("mozfullscreenchange", () => {
+    sendAsyncMessage("Test:FullscreenChanged", {
+      inDOMFullscreen: content.document.mozFullScreen,
+      inFullscreen: content.fullScreen
+    });
+  });
+  function waitUntilActive() {
+    let doc = content.document;
+    if (doc.docShell.isActive && doc.hasFocus()) {
+      sendAsyncMessage("Test:Activated");
+    } else {
+      setTimeout(waitUntilActive, 10);
+    }
+  }
+  waitUntilActive();
+}
+
+function listenOneMessage(aMsg, aListener) {
+  function listener({ data }) {
+    gMessageManager.removeMessageListener(aMsg, listener);
+    aListener(data);
+  }
+  gMessageManager.addMessageListener(aMsg, listener);
+}
+
+function listenOneEvent(aEvent, aListener) {
+  function listener(evt) {
+    removeEventListener(aEvent, listener);
+    aListener(evt);
+  }
+  addEventListener(aEvent, listener);
+}
+
+function queryFullscreenState() {
+  return new Promise(resolve => {
+    listenOneMessage("Test:FullscreenState", resolve);
+    gMessageManager.sendAsyncMessage("Test:QueryFullscreenState");
+  });
+}
+
+function captureUnexpectedFullscreenChange() {
+  ok(false, "catched an unexpected fullscreen change");
+}
+
+const FS_CHANGE_DOM = 1 << 0;
+const FS_CHANGE_SIZE = 1 << 1;
+const FS_CHANGE_BOTH = FS_CHANGE_DOM | FS_CHANGE_SIZE;
+
+function waitForFullscreenChanges(aFlags) {
+  return new Promise(resolve => {
+    let fullscreenData = null;
+    let sizemodeChanged = false;
+    function tryResolve() {
+      if ((!(aFlags & FS_CHANGE_DOM) || fullscreenData) &&
+          (!(aFlags & FS_CHANGE_SIZE) || sizemodeChanged)) {
+        if (!fullscreenData) {
+          queryFullscreenState().then(resolve);
+        } else {
+          resolve(fullscreenData);
+        }
+      }
+    }
+    if (aFlags & FS_CHANGE_SIZE) {
+      listenOneEvent("sizemodechange", () => {
+        sizemodeChanged = true;
+        tryResolve();
+      });
+    }
+    if (aFlags & FS_CHANGE_DOM) {
+      gMessageManager.removeMessageListener(
+        "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+      listenOneMessage("Test:FullscreenChanged", data => {
+        gMessageManager.addMessageListener(
+          "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+        fullscreenData = data;
+        tryResolve();
+      });
+    }
+  });
+}
+
+let gTests = [
+  {
+    desc: "document method",
+    affectsFullscreenMode: false,
+    exitFunc: () => {
+      gMessageManager.sendAsyncMessage("Test:ExitFullscreen");
+    }
+  },
+  {
+    desc: "escape key",
+    affectsFullscreenMode: false,
+    exitFunc: () => {
+      executeSoon(() => EventUtils.synthesizeKey("VK_ESCAPE", {}));
+    }
+  },
+  {
+    desc: "F11 key",
+    affectsFullscreenMode: true,
+    exitFunc: function () {
+      executeSoon(() => EventUtils.synthesizeKey("VK_F11", {}));
+    }
+  }
+];
+
+add_task(function* () {
+  let tab = gBrowser.addTab("about:robots");
+  let browser = tab.linkedBrowser;
+  gBrowser.selectedTab = tab;
+  yield waitForDocLoadComplete();
+
+  registerCleanupFunction(() => {
+    if (browser.contentWindow.fullScreen) {
+      BrowserFullScreen();
+    }
+    gBrowser.removeTab(tab);
+  });
+
+  gMessageManager = browser.messageManager;
+  gMessageManager.loadFrameScript(
+    "data:,(" + frameScript.toString() + ")();", false);
+  gMessageManager.addMessageListener(
+    "Test:FullscreenChanged", captureUnexpectedFullscreenChange);
+
+  // Wait for the document being activated, so that
+  // fullscreen request won't be denied.
+  yield new Promise(resolve => listenOneMessage("Test:Activated", resolve));
+
+  for (let test of gTests) {
+    info("Testing exit DOM fullscreen via " + test.desc);
+
+    var { inDOMFullscreen, inFullscreen } = yield queryFullscreenState();
+    ok(!inDOMFullscreen, "Shouldn't have been in DOM fullscreen");
+    ok(!inFullscreen, "Shouldn't have been in fullscreen");
+
+    /* DOM fullscreen without fullscreen mode */
+
+    // Enter DOM fullscreen
+    gMessageManager.sendAsyncMessage("Test:RequestFullscreen");
+    var { inDOMFullscreen, inFullscreen } =
+      yield waitForFullscreenChanges(FS_CHANGE_BOTH);
+    ok(inDOMFullscreen, "Should now be in DOM fullscreen");
+    ok(inFullscreen, "Should now be in fullscreen");
+
+    // Exit DOM fullscreen
+    test.exitFunc();
+    var { inDOMFullscreen, inFullscreen } =
+      yield waitForFullscreenChanges(FS_CHANGE_BOTH);
+    ok(!inDOMFullscreen, "Should no longer be in DOM fullscreen");
+    ok(!inFullscreen, "Should no longer be in fullscreen");
+
+    /* DOM fullscreen with fullscreen mode */
+
+    // Enter fullscreen mode
+    // Need to be asynchronous because sizemodechange event could be
+    // dispatched synchronously, which would cause the event listener
+    // miss that event and wait infinitely.
+    executeSoon(() => BrowserFullScreen());
+    var { inDOMFullscreen, inFullscreen } =
+      yield waitForFullscreenChanges(FS_CHANGE_SIZE);
+    ok(!inDOMFullscreen, "Shouldn't have been in DOM fullscreen");
+    ok(inFullscreen, "Should now be in fullscreen mode");
+
+    // Enter DOM fullscreen
+    gMessageManager.sendAsyncMessage("Test:RequestFullscreen");
+    var { inDOMFullscreen, inFullscreen } =
+      yield waitForFullscreenChanges(FS_CHANGE_DOM);
+    ok(inDOMFullscreen, "Should now be in DOM fullscreen");
+    ok(inFullscreen, "Should still be in fullscreen");
+
+    // Exit DOM fullscreen
+    test.exitFunc();
+    var { inDOMFullscreen, inFullscreen } =
+      yield waitForFullscreenChanges(test.affectsFullscreenMode ?
+                                     FS_CHANGE_BOTH : FS_CHANGE_DOM);
+    ok(!inDOMFullscreen, "Should no longer be in DOM fullscreen");
+    if (test.affectsFullscreenMode) {
+      ok(!inFullscreen, "Should no longer be in fullscreen mode");
+    } else {
+      ok(inFullscreen, "Should still be in fullscreen mode");
+    }
+
+    /* Cleanup */
+
+    // Exit fullscreen mode if we are still in
+    if (browser.contentWindow.fullScreen) {
+      executeSoon(() => BrowserFullScreen());
+      yield waitForFullscreenChanges(FS_CHANGE_SIZE);
+    }
+  }
+});
--- a/browser/base/content/test/general/browser_e10s_switchbrowser.js
+++ b/browser/base/content/test/general/browser_e10s_switchbrowser.js
@@ -102,158 +102,158 @@ let forward = Task.async(function*() {
   gBrowser.goForward();
   yield waitForDocLoadComplete();
   gExpectedHistory.index++;
 });
 
 // Tests that navigating from a page that should be in the remote process and
 // a page that should be in the main process works and retains history
 add_task(function* test_navigation() {
-  let expectedRemote = gMultiProcessBrowser ? "true" : "";
+  let expectedRemote = gMultiProcessBrowser;
 
   info("1");
   // Create a tab and load a remote page in it
   gBrowser.selectedTab = gBrowser.addTab("about:blank", {skipAnimation: true});
   let {permanentKey} = gBrowser.selectedBrowser;
   yield waitForLoad("http://example.org/" + DUMMY_PATH);
-  is(gBrowser.selectedTab.getAttribute("remote"), expectedRemote, "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
 
   info("2");
   // Load another page
   yield waitForLoad("http://example.com/" + DUMMY_PATH);
-  is(gBrowser.selectedTab.getAttribute("remote"), expectedRemote, "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
   yield check_history();
 
   info("3");
   // Load a non-remote page
   yield waitForLoad("about:robots");
-  is(gBrowser.selectedTab.getAttribute("remote"), "", "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
   yield check_history();
 
   info("4");
   // Load a remote page
   yield waitForLoad("http://example.org/" + DUMMY_PATH);
-  is(gBrowser.selectedTab.getAttribute("remote"), expectedRemote, "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
   yield check_history();
 
   info("5");
   yield back();
-  is(gBrowser.selectedTab.getAttribute("remote"), "", "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
   yield check_history();
 
   info("6");
   yield back();
-  is(gBrowser.selectedTab.getAttribute("remote"), expectedRemote, "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
   yield check_history();
 
   info("7");
   yield forward();
-  is(gBrowser.selectedTab.getAttribute("remote"), "", "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
   yield check_history();
 
   info("8");
   yield forward();
-  is(gBrowser.selectedTab.getAttribute("remote"), expectedRemote, "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
   yield check_history();
 
   info("9");
   yield back();
-  is(gBrowser.selectedTab.getAttribute("remote"), "", "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
   yield check_history();
 
   info("10");
   // Load a new remote page, this should replace the last history entry
   gExpectedHistory.entries.splice(gExpectedHistory.entries.length - 1, 1);
   yield waitForLoad("http://example.com/" + DUMMY_PATH);
-  is(gBrowser.selectedTab.getAttribute("remote"), expectedRemote, "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
   yield check_history();
 
   info("11");
   gBrowser.removeCurrentTab();
   clear_history();
 });
 
 // Tests that calling gBrowser.loadURI or browser.loadURI to load a page in a
 // different process updates the browser synchronously
 add_task(function* test_synchronous() {
-  let expectedRemote = gMultiProcessBrowser ? "true" : "";
+  let expectedRemote = gMultiProcessBrowser;
 
   info("1");
   // Create a tab and load a remote page in it
   gBrowser.selectedTab = gBrowser.addTab("about:blank", {skipAnimation: true});
   let {permanentKey} = gBrowser.selectedBrowser;
   yield waitForLoad("http://example.org/" + DUMMY_PATH);
-  is(gBrowser.selectedTab.getAttribute("remote"), expectedRemote, "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
 
   info("2");
   // Load another page
   info("Loading about:robots");
   gBrowser.selectedBrowser.loadURI("about:robots");
-  is(gBrowser.selectedTab.getAttribute("remote"), "", "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
 
   yield waitForDocLoadComplete();
-  is(gBrowser.selectedTab.getAttribute("remote"), "", "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
 
   info("3");
   // Load the remote page again
   info("Loading http://example.org/" + DUMMY_PATH);
   gBrowser.loadURI("http://example.org/" + DUMMY_PATH);
-  is(gBrowser.selectedTab.getAttribute("remote"), expectedRemote, "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
 
   yield waitForDocLoadComplete();
-  is(gBrowser.selectedTab.getAttribute("remote"), expectedRemote, "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct");
   is(gBrowser.selectedBrowser.permanentKey, permanentKey, "browser.permanentKey is still the same");
 
   info("4");
   gBrowser.removeCurrentTab();
   clear_history();
 });
 
 // Tests that load flags are correctly passed through to the child process with
 // normal loads
 add_task(function* test_loadflags() {
-  let expectedRemote = gMultiProcessBrowser ? "true" : "";
+  let expectedRemote = gMultiProcessBrowser;
 
   info("1");
   // Create a tab and load a remote page in it
   gBrowser.selectedTab = gBrowser.addTab("about:blank", {skipAnimation: true});
   yield waitForLoadWithFlags("about:robots");
-  is(gBrowser.selectedTab.getAttribute("remote"), "", "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct");
   yield check_history();
 
   info("2");
   // Load a page in the remote process with some custom flags
   yield waitForLoadWithFlags("http://example.com/" + DUMMY_PATH, Ci.nsIWebNavigation.LOAD_FLAGS_BYPASS_HISTORY);
-  is(gBrowser.selectedTab.getAttribute("remote"), expectedRemote, "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct");
   yield check_history();
 
   info("3");
   // Load a non-remote page
   yield waitForLoadWithFlags("about:robots");
-  is(gBrowser.selectedTab.getAttribute("remote"), "", "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, false, "Remote attribute should be correct");
   yield check_history();
 
   info("4");
   // Load another remote page
   yield waitForLoadWithFlags("http://example.org/" + DUMMY_PATH, Ci.nsIWebNavigation.LOAD_FLAGS_REPLACE_HISTORY);
-  is(gBrowser.selectedTab.getAttribute("remote"), expectedRemote, "Remote attribute should be correct");
+  is(gBrowser.selectedBrowser.isRemoteBrowser, expectedRemote, "Remote attribute should be correct");
   yield check_history();
 
   is(gExpectedHistory.entries.length, 2, "Should end with the right number of history entries");
 
   info("5");
   gBrowser.removeCurrentTab();
   clear_history();
 });
--- a/browser/base/content/test/general/browser_fxa_migrate.js
+++ b/browser/base/content/test/general/browser_fxa_migrate.js
@@ -27,17 +27,17 @@ add_task(function* test() {
                                imports.fxaMigrator.STATE_USER_FXA_VERIFIED);
   buttonState = yield buttonPromise;
   assertButtonState(buttonState, "migrate-verify", true,
                     "foo@example.com not verified");
   let note = Weave.Notifications.notifications.find(n => {
     return n.title == NOTIFICATION_TITLE;
   });
   Assert.ok(!!note, "Needs-verification notification should be present");
-  Assert.ok(note.description.contains(email.data),
+  Assert.ok(note.description.includes(email.data),
             "Needs-verification notification should include email");
 
   // Fake the state where no migration is needed.
   buttonPromise = promiseButtonMutation();
   Services.obs.notifyObservers(null, STATE_CHANGED_TOPIC, null);
   buttonState = yield buttonPromise;
   // In this case, the front end has called fxAccounts.getSignedInUser() to
   // update the button label and status.  But since there isn't actually a user,
rename from browser/base/content/test/general/browser_fxa_profile_channel.html
rename to browser/base/content/test/general/browser_fxa_web_channel.html
--- a/browser/base/content/test/general/browser_fxa_profile_channel.html
+++ b/browser/base/content/test/general/browser_fxa_web_channel.html
@@ -1,26 +1,98 @@
 <!DOCTYPE html>
 <html>
 <head>
   <meta charset="utf-8">
-  <title>fxa_profile_channel_test</title>
+  <title>fxa_web_channel_test</title>
 </head>
 <body>
 <script>
+  var webChannelId = "account_updates_test";
+
   window.onload = function(){
+    var testName = window.location.search.replace(/^\?/, "");
+
+    switch(testName) {
+      case "profile_change":
+        test_profile_change();
+        break;
+      case "login":
+        test_login();
+        break;
+      case "can_link_account":
+        test_can_link_account();
+        break;
+    }
+  };
+
+  function test_profile_change() {
     var event = new window.CustomEvent("WebChannelMessageToChrome", {
       detail: {
-        id: "account_updates",
+        id: webChannelId,
         message: {
           command: "profile:change",
           data: {
             uid: "abc123",
           },
         },
       },
     });
 
     window.dispatchEvent(event);
-  };
+  }
+
+  function test_login() {
+    var event = new window.CustomEvent("WebChannelMessageToChrome", {
+      detail: {
+        id: webChannelId,
+        message: {
+          command: "fxaccounts:login",
+          data: {
+            authAt: Date.now(),
+            email: "testuser@testuser.com",
+            keyFetchToken: 'key_fetch_token',
+            sessionToken: 'session_token',
+            uid: 'uid',
+            unwrapBKey: 'unwrap_b_key',
+            verified: true,
+          },
+          messageId: 1,
+        },
+      },
+    });
+
+    window.dispatchEvent(event);
+  }
+
+  function test_can_link_account() {
+    window.addEventListener("WebChannelMessageToContent", function (e) {
+      // echo any responses from the browser back to the tests on the
+      // fxaccounts_webchannel_response_echo WebChannel. The tests are
+      // listening for events and do the appropriate checks.
+      var event = new window.CustomEvent("WebChannelMessageToChrome", {
+        detail: {
+          id: 'fxaccounts_webchannel_response_echo',
+          message: e.detail.message,
+        }
+      });
+
+      window.dispatchEvent(event);
+    }, true);
+
+    var event = new window.CustomEvent("WebChannelMessageToChrome", {
+      detail: {
+        id: webChannelId,
+        message: {
+          command: "fxaccounts:can_link_account",
+          data: {
+            email: "testuser@testuser.com",
+          },
+          messageId: 2,
+        },
+      },
+    });
+
+    window.dispatchEvent(event);
+  }
 </script>
 </body>
 </html>
rename from browser/base/content/test/general/browser_fxa_profile_channel.js
rename to browser/base/content/test/general/browser_fxa_web_channel.js
--- a/browser/base/content/test/general/browser_fxa_profile_channel.js
+++ b/browser/base/content/test/general/browser_fxa_web_channel.js
@@ -4,49 +4,124 @@
 
 Cu.import("resource://gre/modules/Promise.jsm");
 Cu.import("resource://gre/modules/Task.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "FxAccountsCommon", function () {
   return Components.utils.import("resource://gre/modules/FxAccountsCommon.js", {});
 });
 
-XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsProfileChannel",
-  "resource://gre/modules/FxAccountsProfileChannel.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "WebChannel",
+                                  "resource://gre/modules/WebChannel.jsm");
 
-const HTTP_PATH = "http://example.com";
+XPCOMUtils.defineLazyModuleGetter(this, "FxAccountsWebChannel",
+  "resource://gre/modules/FxAccountsWebChannel.jsm");
+
+const TEST_HTTP_PATH = "http://example.com";
+const TEST_BASE_URL = TEST_HTTP_PATH + "/browser/browser/base/content/test/general/browser_fxa_web_channel.html";
+const TEST_CHANNEL_ID = "account_updates_test";
 
 let gTests = [
   {
-    desc: "FxA Profile Channel - should receive message about account updates",
+    desc: "FxA Web Channel - should receive message about profile changes",
     run: function* () {
-      return new Promise(function(resolve, reject) {
-        let tabOpened = false;
-        let properUrl = "http://example.com/browser/browser/base/content/test/general/browser_fxa_profile_channel.html";
+      let client = new FxAccountsWebChannel({
+        content_uri: TEST_HTTP_PATH,
+        channel_id: TEST_CHANNEL_ID,
+      });
+      let promiseObserver = new Promise((resolve, reject) => {
+        makeObserver(FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION, function (subject, topic, data) {
+          Assert.equal(data, "abc123");
+          client.tearDown();
+          resolve();
+        });
+      });
+
+      yield BrowserTestUtils.withNewTab({
+        gBrowser: gBrowser,
+        url: TEST_BASE_URL + "?profile_change"
+      }, function* () {
+        yield promiseObserver;
+      });
+    }
+  },
+  {
+    desc: "fxa web channel - login messages should notify the fxAccounts object",
+    run: function* () {
+
+      let promiseLogin = new Promise((resolve, reject) => {
+        let login = (accountData) => {
+          Assert.equal(typeof accountData.authAt, 'number');
+          Assert.equal(accountData.email, 'testuser@testuser.com');
+          Assert.equal(accountData.keyFetchToken, 'key_fetch_token');
+          Assert.equal(accountData.sessionToken, 'session_token');
+          Assert.equal(accountData.uid, 'uid');
+          Assert.equal(accountData.unwrapBKey, 'unwrap_b_key');
+          Assert.equal(accountData.verified, true);
 
-        waitForTab(function (tab) {
-          Assert.ok("Tab successfully opened");
-          let match = gBrowser.currentURI.spec == properUrl;
-          Assert.ok(match);
+          client.tearDown();
+          resolve();
+        };
+
+        let client = new FxAccountsWebChannel({
+          content_uri: TEST_HTTP_PATH,
+          channel_id: TEST_CHANNEL_ID,
+          helpers: {
+            login: login
+          }
+        });
+      });
 
-          tabOpened = true;
+      yield BrowserTestUtils.withNewTab({
+        gBrowser: gBrowser,
+        url: TEST_BASE_URL + "?login"
+      }, function* () {
+        yield promiseLogin;
+      });
+    }
+  },
+  {
+    desc: "fxa web channel - can_link_account messages should respond",
+    run: function* () {
+      let properUrl = TEST_BASE_URL + "?can_link_account";
+
+      let promiseEcho = new Promise((resolve, reject) => {
+
+        let webChannelOrigin = Services.io.newURI(properUrl, null, null);
+        // responses sent to content are echoed back over the
+        // `fxaccounts_webchannel_response_echo` channel. Ensure the
+        // fxaccounts:can_link_account message is responded to.
+        let echoWebChannel = new WebChannel('fxaccounts_webchannel_response_echo', webChannelOrigin);
+        echoWebChannel.listen((webChannelId, message, target) => {
+          Assert.equal(message.command, 'fxaccounts:can_link_account');
+          Assert.equal(message.messageId, 2);
+          Assert.equal(message.data.ok, true);
+
+          client.tearDown();
+          echoWebChannel.stopListening();
+
+          resolve();
         });
 
-        let client = new FxAccountsProfileChannel({
-          content_uri: HTTP_PATH,
+        let client = new FxAccountsWebChannel({
+          content_uri: TEST_HTTP_PATH,
+          channel_id: TEST_CHANNEL_ID,
+          helpers: {
+            shouldAllowRelink(acctName) {
+              return acctName === 'testuser@testuser.com';
+            }
+          }
         });
+      });
 
-        makeObserver(FxAccountsCommon.ON_PROFILE_CHANGE_NOTIFICATION, function (subject, topic, data) {
-          Assert.ok(tabOpened);
-          Assert.equal(data, "abc123");
-          resolve();
-          gBrowser.removeCurrentTab();
-        });
-
-        gBrowser.selectedTab = gBrowser.addTab(properUrl);
+      yield BrowserTestUtils.withNewTab({
+        gBrowser: gBrowser,
+        url: properUrl
+      }, function* () {
+        yield promiseEcho;
       });
     }
   }
 ]; // gTests
 
 function makeObserver(aObserveTopic, aObserveFunc) {
   let callback = function (aSubject, aTopic, aData) {
     if (aTopic == aObserveTopic) {
@@ -58,28 +133,16 @@ function makeObserver(aObserveTopic, aOb
   function removeMe() {
     Services.obs.removeObserver(callback, aObserveTopic);
   }
 
   Services.obs.addObserver(callback, aObserveTopic, false);
   return removeMe;
 }
 
-function waitForTab(aCallback) {
-  let container = gBrowser.tabContainer;
-  container.addEventListener("TabOpen", function tabOpener(event) {
-    container.removeEventListener("TabOpen", tabOpener, false);
-    gBrowser.addEventListener("load", function listener() {
-      gBrowser.removeEventListener("load", listener, true);
-      let tab = event.target;
-      aCallback(tab);
-    }, true);
-  }, false);
-}
-
 function test() {
   waitForExplicitFinish();
 
   Task.spawn(function () {
     for (let test of gTests) {
       info("Running: " + test.desc);
       yield test.run();
     }
--- a/browser/base/content/test/general/browser_homeDrop.js
+++ b/browser/base/content/test/general/browser_homeDrop.js
@@ -32,17 +32,17 @@ function test() {
     ok(true, "dialog appeared in response to home button drop");
     domwindow.document.documentElement.cancelDialog();
     Services.wm.removeListener(dialogListener);
 
     // Now trigger the invalid URI test
     executeSoon(function () {
       let consoleListener = {
         observe: function (m) {
-          if (m.message.contains("NS_ERROR_DOM_BAD_URI")) {
+          if (m.message.includes("NS_ERROR_DOM_BAD_URI")) {
             ok(true, "drop was blocked");
             executeSoon(finish);
           }
         }
       }
       Services.console.registerListener(consoleListener);
       registerCleanupFunction(function () {
         Services.console.unregisterListener(consoleListener);
--- a/browser/base/content/test/general/browser_identity_UI.js
+++ b/browser/base/content/test/general/browser_identity_UI.js
@@ -1,11 +1,12 @@
 /* Tests for correct behaviour of getEffectiveHost on identity handler */
 function test() {
   waitForExplicitFinish();
+  requestLongerTimeout(2);
 
   ok(gIdentityHandler, "gIdentityHandler should exist");
 
   gBrowser.selectedTab = gBrowser.addTab();
   gBrowser.selectedBrowser.addEventListener("load", checkResult, true);
 
   nextTest();
 }
--- a/browser/base/content/test/general/browser_parsable_css.js
+++ b/browser/base/content/test/general/browser_parsable_css.js
@@ -18,17 +18,19 @@ const kWhitelist = [
   {sourceName: /web\/viewer\.css/i,
    errorMessage: /Unknown pseudo-class.*(fullscreen|selection)/i},
   // Tracked in bug 1004428.
   {sourceName: /aboutaccounts\/(main|normalize)\.css/i},
   // TokBox SDK assets, see bug 1032469.
   {sourceName: /loop\/.*sdk-content\/.*\.css$/i},
   // Highlighter CSS uses chrome-only pseudo-class, see bug 985597.
   {sourceName: /highlighter\.css/i,
-   errorMessage: /Unknown pseudo-class.*moz-native-anonymous/i}
+   errorMessage: /Unknown pseudo-class.*moz-native-anonymous/i},
+  // Tracked in bug 1160629.
+  {sourceName: /pocket\/panels\/css\/.*\.css/i},
 ];
 
 let moduleLocation = gTestPath.replace(/\/[^\/]*$/i, "/parsingTestHelpers.jsm");
 let {generateURIsFromDirTree} = Cu.import(moduleLocation, {});
 
 /**
  * Check if an error should be ignored due to matching one of the whitelist
  * objects defined in kWhitelist
@@ -68,17 +70,17 @@ add_task(function checkAllTheCSS() {
 
   // Listen for errors caused by the CSS:
   let errorListener = {
     observe: function(aMessage) {
       if (!aMessage || !(aMessage instanceof Ci.nsIScriptError)) {
         return;
       }
       // Only care about CSS errors generated by our iframe:
-      if (aMessage.category.contains("CSS") && aMessage.innerWindowID === 0 && aMessage.outerWindowID === 0) {
+      if (aMessage.category.includes("CSS") && aMessage.innerWindowID === 0 && aMessage.outerWindowID === 0) {
         // Check if this error is whitelisted in kWhitelist
         if (!ignoredError(aMessage)) {
           ok(false, "Got error message for " + aMessage.sourceName + ": " + aMessage.errorMessage);
           errors++;
         } else {
           info("Ignored error for " + aMessage.sourceName + " because of filter.");
         }
       }
--- a/browser/base/content/test/general/browser_parsable_script.js
+++ b/browser/base/content/test/general/browser_parsable_script.js
@@ -78,32 +78,32 @@ add_task(function* checkAllTheJS() {
       return;
     }
     // Request a 10 minutes timeout (30 seconds * 20) for debug builds.
     requestLongerTimeout(20);
   }
 
   let uris;
   // If an absolute URI is specified on the command line, use it immediately.
-  if (parseValue && parseValue.contains(":")) {
+  if (parseValue && parseValue.includes(":")) {
     uris = [NetUtil.newURI(parseValue)];
   } else {
     let appDir = Services.dirsvc.get("XCurProcD", Ci.nsIFile);
     // This asynchronously produces a list of URLs (sadly, mostly sync on our
     // test infrastructure because it runs against jarfiles there, and
     // our zipreader APIs are all sync)
     let startTimeMs = Date.now();
     info("Collecting URIs");
     uris = yield generateURIsFromDirTree(appDir, [".js", ".jsm"]);
     info("Collected URIs in " + (Date.now() - startTimeMs) + "ms");
 
     // Apply the filter specified on the command line, if any.
     if (parseValue) {
       uris = uris.filter(uri => {
-        if (uri.spec.contains(parseValue)) {
+        if (uri.spec.includes(parseValue)) {
           return true;
         }
         info("Not checking filtered out " + uri.spec);
         return false;
       });
     }
   }
 
--- a/browser/base/content/test/general/browser_readerMode.js
+++ b/browser/base/content/test/general/browser_readerMode.js
@@ -27,29 +27,39 @@ add_task(function* test_reader_button() 
       gBrowser.removeCurrentTab();
     }
   });
 
   // Set required test prefs.
   TEST_PREFS.forEach(([name, value]) => {
     Services.prefs.setBoolPref(name, value);
   });
+  Services.prefs.setBoolPref("browser.reader.detectedFirstArticle", false);
 
   let tab = gBrowser.selectedTab = gBrowser.addTab();
   is_element_hidden(readerButton, "Reader mode button is not present on a new tab");
+  ok(!UITour.isInfoOnTarget(window, "readerMode-urlBar"),
+     "Info panel shouldn't appear without the reader mode button");
+  ok(!Services.prefs.getBoolPref("browser.reader.detectedFirstArticle"),
+     "Shouldn't have detected the first article");
 
   // Point tab to a test page that is reader-able.
   let url = TEST_PATH + "readerModeArticle.html";
   yield promiseTabLoadEvent(tab, url);
   yield promiseWaitForCondition(() => !readerButton.hidden);
   is_element_visible(readerButton, "Reader mode button is present on a reader-able page");
+  ok(UITour.isInfoOnTarget(window, "readerMode-urlBar"),
+     "Info panel should be anchored at the reader mode button");
+  ok(Services.prefs.getBoolPref("browser.reader.detectedFirstArticle"),
+     "Should have detected the first article");
 
   // Switch page into reader mode.
   readerButton.click();
   yield promiseTabLoadEvent(tab);
+  ok(!UITour.isInfoOnTarget(window, "readerMode-urlBar"), "Info panel should have closed");
 
   let readerUrl = gBrowser.selectedBrowser.currentURI.spec;
   ok(readerUrl.startsWith("about:reader"), "about:reader loaded after clicking reader mode button&q