Merge m-c to oak
authorRobert Strong <robert.bugzilla@gmail.com>
Tue, 24 May 2016 22:57:27 -0700
changeset 491549 a1f26b5d541f1dd2fe6b9b44032133cb3c172d86
parent 491548 fac56d4f0fd7e86d04f5bd397dc576ef9ddf19ac (current diff)
parent 370474 5511d54a3f172c1d68f98cc55dce4de1d0ba1b51 (diff)
child 491550 67ca0e62166daffd06b648eec304bc44c2a57beb
push id47343
push userbmo:dothayer@mozilla.com
push dateWed, 01 Mar 2017 22:58:58 +0000
milestone49.0a1
Merge m-c to oak
CLOBBER
b2g/app/b2g.js
b2g/installer/package-manifest.in
browser/app/macbuild/Contents/Info.plist.in
browser/app/nsBrowserApp.cpp
browser/app/profile/firefox.js
browser/base/content/browser.js
browser/extensions/loop/chrome/content/shared/js/models.js
browser/installer/package-manifest.in
browser/modules/UserContextUI.jsm
browser/themes/shared/usercontext/usercontext.inc.css
devtools/client/fronts/highlighters.js
devtools/client/fronts/moz.build
devtools/client/fronts/storage.js
devtools/client/fronts/styles.js
devtools/client/fronts/stylesheets.js
devtools/client/shared/widgets/ViewHelpers.jsm
dom/animation/Animation.cpp
dom/base/PerformanceCompositeTiming.cpp
dom/base/PerformanceCompositeTiming.h
dom/base/PerformanceRenderTiming.cpp
dom/base/PerformanceRenderTiming.h
dom/browser-element/mochitest/browserElement_getStructuredData.js
dom/browser-element/mochitest/test_browserElement_inproc_getStructuredData.html
dom/browser-element/mochitest/test_browserElement_oop_getStructuredData.html
dom/cache/CachePushStreamChild.cpp
dom/cache/CachePushStreamChild.h
dom/cache/CachePushStreamParent.cpp
dom/cache/CachePushStreamParent.h
dom/cache/PCachePushStream.ipdl
dom/html/HTMLPropertiesCollection.cpp
dom/html/HTMLPropertiesCollection.h
dom/media/tests/mochitest/test_peerConnection_addTrack.html
dom/presentation/interfaces/nsITCPPresentationServer.idl
dom/presentation/provider/TCPPresentationServer.js
dom/presentation/tests/mochitest/file_presentation_1ua_receiver_oop.html
dom/presentation/tests/mochitest/file_presentation_non_receiver_inner_iframe_oop.html
dom/presentation/tests/mochitest/file_presentation_non_receiver_oop.html
dom/presentation/tests/mochitest/file_presentation_receiver_inner_iframe_oop.html
dom/presentation/tests/mochitest/file_presentation_receiver_oop.html
dom/webidl/HTMLPropertiesCollection.webidl
dom/webidl/PerformanceCompositeTiming.webidl
dom/webidl/PerformanceRenderTiming.webidl
gfx/layers/apz/src/FlingOverScrollerAnimation.cpp
gfx/layers/apz/src/FlingOverScrollerAnimation.h
gfx/layers/apz/test/mochitest/test_scroll_window.html
gfx/layers/apz/test/mochitest/test_tap.html
ipc/app/sha256.c
ipc/app/sha256.h
js/src/devtools/automation/variants/generational
js/src/tests/ecma_3/Date/15.9.3.2-1.js
js/src/tests/js1_5/Date/regress-301738-02.js
js/xpconnect/src/XPCShellImpl.cpp
mobile/android/base/java/org/mozilla/gecko/firstrun/WelcomePanel.java
mobile/android/base/java/org/mozilla/gecko/home/ReadingListPanel.java
mobile/android/base/java/org/mozilla/gecko/mozglue/ContextUtils.java
mobile/android/base/resources/drawable-hdpi/ic_menu_share_icon.png
mobile/android/base/resources/drawable-hdpi/menu_popup_bg.9.png
mobile/android/base/resources/drawable-hdpi/reading_list_migration.png
mobile/android/base/resources/drawable-large-hdpi-v11/firstrun_background_coffee.png
mobile/android/base/resources/drawable-large-xhdpi-v11/firstrun_background_coffee.png
mobile/android/base/resources/drawable-large-xxhdpi-v11/firstrun_background_coffee.png
mobile/android/base/resources/drawable-large/ic_menu_share.xml
mobile/android/base/resources/drawable-nodpi/firstrun_background_coffee.png
mobile/android/base/resources/drawable-xhdpi/ic_menu_share_icon.png
mobile/android/base/resources/drawable-xhdpi/menu_popup_bg.9.png
mobile/android/base/resources/drawable-xhdpi/reading_list_migration.png
mobile/android/base/resources/drawable-xxhdpi/ic_menu_share_icon.png
mobile/android/base/resources/drawable-xxhdpi/reading_list_migration.png
mobile/android/base/resources/drawable/bookmark_folder.xml
mobile/android/base/resources/drawable/ic_menu_share.xml
mobile/android/base/resources/layout/firstrun_basepanel_fragment.xml
mobile/android/base/resources/layout/firstrun_welcome_fragment.xml
mobile/android/base/resources/layout/readinglistpanel_gone_fragment.xml
mobile/android/components/extensions/extension.svg
netwerk/base/nsAutodialQt.cpp
netwerk/base/nsAutodialQt.h
netwerk/base/nsAutodialWin.cpp
netwerk/base/nsAutodialWin.h
netwerk/base/nsNativeConnectionHelper.cpp
netwerk/base/nsNativeConnectionHelper.h
old-configure.in
python/mozbuild/mozbuild/base.py
security/manager/ssl/tests/unit/head_psm.js
security/sandbox/objs.mozbuild
security/sandbox/staticruntime/moz.build
services/common/KintoBlocklist.js
services/common/kinto-updater.js
services/common/tests/unit/test_kintoAddonPluginBlocklist.js
services/common/tests/unit/test_kintoCertBlocklist.js
services/common/tests/unit/test_kinto_updater.js
testing/eslint-plugin-mozilla/LICENSE
testing/eslint-plugin-mozilla/docs/balanced-listeners.rst
testing/eslint-plugin-mozilla/docs/import-browserjs-globals.rst
testing/eslint-plugin-mozilla/docs/import-globals.rst
testing/eslint-plugin-mozilla/docs/import-headjs-globals.rst
testing/eslint-plugin-mozilla/docs/index.rst
testing/eslint-plugin-mozilla/docs/mark-test-function-used.rst
testing/eslint-plugin-mozilla/docs/no-aArgs.rst
testing/eslint-plugin-mozilla/docs/no-cpows-in-tests.rst
testing/eslint-plugin-mozilla/docs/reject-importGlobalProperties.rst
testing/eslint-plugin-mozilla/docs/var-only-at-top-level.rst
testing/eslint-plugin-mozilla/lib/globals.js
testing/eslint-plugin-mozilla/lib/helpers.js
testing/eslint-plugin-mozilla/lib/index.js
testing/eslint-plugin-mozilla/lib/processors/xbl-bindings.js
testing/eslint-plugin-mozilla/lib/rules/.eslintrc
testing/eslint-plugin-mozilla/lib/rules/balanced-listeners.js
testing/eslint-plugin-mozilla/lib/rules/import-browserjs-globals.js
testing/eslint-plugin-mozilla/lib/rules/import-globals.js
testing/eslint-plugin-mozilla/lib/rules/import-headjs-globals.js
testing/eslint-plugin-mozilla/lib/rules/mark-test-function-used.js
testing/eslint-plugin-mozilla/lib/rules/no-aArgs.js
testing/eslint-plugin-mozilla/lib/rules/no-cpows-in-tests.js
testing/eslint-plugin-mozilla/lib/rules/reject-importGlobalProperties.js
testing/eslint-plugin-mozilla/lib/rules/var-only-at-top-level.js
testing/eslint-plugin-mozilla/moz.build
testing/eslint-plugin-mozilla/package.json
testing/firefox-ui/tests/puppeteer/mn-restartless-unsigned.xpi
testing/mochitest/mochitest_options.py
testing/mochitest/runtests.py
testing/moz.build
testing/taskcluster/docs/index.rst
testing/taskcluster/tasks/builds/b2g_emulator_base.yml
testing/taskcluster/tasks/builds/b2g_emulator_ics_debug.yml
testing/taskcluster/tasks/builds/b2g_emulator_ics_opt.yml
testing/taskcluster/tasks/builds/b2g_emulator_jb_debug.yml
testing/taskcluster/tasks/builds/b2g_emulator_jb_opt.yml
testing/taskcluster/tasks/builds/b2g_emulator_kk_debug.yml
testing/taskcluster/tasks/builds/b2g_emulator_kk_opt.yml
testing/taskcluster/tasks/builds/b2g_emulator_l_debug.yml
testing/taskcluster/tasks/builds/b2g_emulator_l_opt.yml
testing/taskcluster/tasks/builds/b2g_emulator_x86_base.yml
testing/taskcluster/tasks/builds/b2g_emulator_x86_kk_debug.yml
testing/taskcluster/tasks/builds/b2g_emulator_x86_kk_opt.yml
testing/taskcluster/tasks/builds/b2g_emulator_x86_l_opt.yml
testing/taskcluster/tasks/tests/b2g_emulator_cpp_unit.yml
testing/taskcluster/tasks/tests/b2g_emulator_crashtest.yml
testing/taskcluster/tasks/tests/b2g_emulator_js_reftest.yml
testing/taskcluster/tasks/tests/b2g_emulator_marionette.yml
testing/taskcluster/tasks/tests/b2g_emulator_marionette_webapi.yml
testing/taskcluster/tasks/tests/b2g_emulator_mochitest.yml
testing/taskcluster/tasks/tests/b2g_emulator_mochitest_media.yml
testing/taskcluster/tasks/tests/b2g_emulator_reftest.yml
testing/taskcluster/tasks/tests/b2g_emulator_xpcshell_chunked.yml
testing/web-platform/meta/DOMEvents/constructors.html.ini
testing/web-platform/meta/DOMEvents/init-event-while-dispatching.html.ini
testing/web-platform/meta/DOMEvents/tests/approved/EventObject.after.dispatchEvent.html.ini
testing/web-platform/meta/DOMEvents/tests/submissions/Microsoft/converted/EventObject.after.dispatchEvent.html.ini
testing/web-platform/meta/DOMEvents/throwing-in-listener-and-window-error-event.html.ini
testing/web-platform/meta/IndexedDB/interfaces.worker.js.ini
testing/web-platform/meta/XMLHttpRequest/setrequestheader-bogus-name.htm.ini
testing/web-platform/meta/content-security-policy/blink-contrib-2/stylehash-allowed.sub.html.ini
testing/web-platform/meta/content-security-policy/blink-contrib/shared-worker-connect-src-blocked.sub.html.ini
testing/web-platform/meta/content-security-policy/child-src/child-src-worker-blocked.sub.html.ini
testing/web-platform/meta/html/browsers/browsing-the-web/history-traversal/PopStateEvent.html.ini
testing/web-platform/meta/html/semantics/forms/constraints/form-validation-validate.html.ini
testing/web-platform/meta/html/semantics/selectors/pseudo-classes/dir.html.ini
testing/web-platform/meta/html/semantics/selectors/pseudo-classes/dir01.html.ini
testing/web-platform/meta/html/semantics/tabular-data/the-table-element/table-rows.html.ini
testing/web-platform/meta/shadow-dom/styles/shadow-cascade-order.html.ini
testing/web-platform/meta/web-animations/animatable/animate.html.ini
testing/web-platform/meta/web-animations/animation-model/animation-types/not-animatable.html.ini
testing/web-platform/meta/web-animations/animation-model/keyframes/effect-value-context.html.ini
testing/web-platform/meta/web-animations/animation-timeline/idlharness.html.ini
testing/web-platform/meta/web-animations/animation/constructor.html.ini
testing/web-platform/meta/web-animations/keyframe-effect/constructor.html.ini
testing/web-platform/meta/web-animations/keyframe-effect/setKeyframes.html.ini
testing/web-platform/meta/web-animations/timing-model/animations/set-the-animation-start-time.html.ini
testing/web-platform/tests/DOMEvents/ClickFakeEvent.nondocument.html
testing/web-platform/tests/DOMEvents/OWNERS
testing/web-platform/tests/DOMEvents/constructors.html
testing/web-platform/tests/DOMEvents/event-phases-order.html
testing/web-platform/tests/DOMEvents/init-event-while-dispatching.html
testing/web-platform/tests/DOMEvents/tests/Status.html
testing/web-platform/tests/DOMEvents/tests/approved/DOM.event.flow.html
testing/web-platform/tests/DOMEvents/tests/approved/EventListener.eventHandler.html
testing/web-platform/tests/DOMEvents/tests/approved/EventObject.after.dispatchEvent.html
testing/web-platform/tests/DOMEvents/tests/approved/EventObject.multiple.dispatchEvent.html
testing/web-platform/tests/DOMEvents/tests/approved/ProcessingInstruction.DOMCharacterDataModified.html
testing/web-platform/tests/DOMEvents/tests/approved/dispatchEvent.click.checkbox.html
testing/web-platform/tests/DOMEvents/tests/approved/domnodeinserted.html
testing/web-platform/tests/DOMEvents/tests/approved/stopImmediatePropagation.effect.html
testing/web-platform/tests/DOMEvents/tests/approved/stopPropagation.deferred.effect.html
testing/web-platform/tests/DOMEvents/tests/approved/support/ProcessingInstruction.DOMCharacterDataModified.xml
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/CompositionEvent.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.attrChange.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.attrName.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.newValue.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.prevValue.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/DOMAttrModified.relatedNode.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/DOMCharacterDataModified.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/DOMNodeInserted.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/DOMNodeRemoved.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/DOMSubtreeModified.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/Event.defaultPrevented.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/Event.eventPhase.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/Event.stopPropagation.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.key.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.location.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/KeyboardEvent.modifiers.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.button.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.image.map.area.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/MouseEvent.preventDefault.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.hasFeature.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.initMutationEvent.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/MutationEvent.relatedNode.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/ProcessingInstruction.DOMCharacterDataModified.fail.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/ProcessingInstruction.DOMCharacterDataModified.xml
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/TextEvent.hasFeature.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/TextEvent.initTextEvent.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.IME.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.drop.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.keyboard.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.paste.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/TextEvent.inputMode.script.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/UIEvent.load.stylesheet.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.Capture.Bubble.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.ctrlKey.zoom.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.deltaMode.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.hasFeature.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.initWheelEvent.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/WheelEvent.preventDefault.scroll.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/abort.img.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/abort.testresult.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/blur.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/compositionstart.data.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/compositionstart.keydown.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/compositionstart.preventDefault.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/converted/DOM.event.flow.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/converted/EventListener.dispatch.new.event.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/converted/EventListener.eventHandler.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/converted/EventObject.after.dispatchEvent.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/converted/EventObject.multiple.dispatchEvent.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/converted/ProcessingInstruction.DOMCharacterDataModified.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/converted/dispatchEvent.click.checkbox.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/converted/domnodeinserted.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/converted/stopImmediatePropagation.effect.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/converted/stopPropagation.deferred.effect.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/converted/support/ProcessingInstruction.DOMCharacterDataModified.xml
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/customevent.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/dispatchEvent.UNSPECIFIED_EVENT_TYPE_ERR.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/dispatchEvent.click.checkbox.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/error.image.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/focusin.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/focusin.relatedTarget.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/focusout.relatedTarget.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/hasFeature.Events.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/hasFeature.feature.string.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/load.image.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/mouseenter.ctrlKey.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/mouseenter.relatedTarget.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/mouseleave.relatedTarget.html
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/support/16kb.js
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/support/InvalidBitMap.png
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/support/iepreview.png
testing/web-platform/tests/DOMEvents/tests/submissions/Microsoft/support/style01.css
testing/web-platform/tests/DOMEvents/throwing-in-listener-and-window-error-event.html
testing/web-platform/tests/DOMEvents/throwing-in-listener-when-all-have-not-run-yet.html
testing/web-platform/tests/custom-elements/concepts/custom-elements-type-allowed-chars-first-char.html
testing/web-platform/tests/custom-elements/concepts/custom-elements-type-allowed-chars.html
testing/web-platform/tests/custom-elements/concepts/custom-elements-type-naming.html
testing/web-platform/tests/custom-elements/creating-and-passing-registries/new-registry-test.html
testing/web-platform/tests/custom-elements/creating-and-passing-registries/no-registry-test.html
testing/web-platform/tests/custom-elements/creating-and-passing-registries/share-registry-create-document.html
testing/web-platform/tests/custom-elements/creating-and-passing-registries/share-registry-import-document.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/enqueuing-and-invoking-callbacks/invoke-callbacks.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-move-element-test.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attached-callback-test.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-change-attribute-test.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-remove-attribute-test.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/types-of-callbacks/attribute-changed-callback-set-attribute-test.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-element-prototype-test.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-invocation-order-test.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/types-of-callbacks/created-callback-invocation-test.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-move-element-test.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-no-browsing-context-test.html
testing/web-platform/tests/custom-elements/custom-element-lifecycle/types-of-callbacks/detached-callback-with-browsing-context-test.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/changing-is-attribute.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/custom-element-constructor-is-attribute.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/custom-element-constructor-local-name.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/custom-element-constructor-namespace.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/custom-element-constructor-node-document.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/custom-element-constructor-prototype.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/custom-element-prototype.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/custom-element-type-is-attribute.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/custom-element-type-local-name-and-is-attribute.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/custom-element-type-local-name.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-local-name.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-interface-type-is-a-type-extension.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-is-attribute.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-namespace.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-extension-is-a-type.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-extension-unresolved.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/create-element-type-is-a-local-name.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/created-callback-create-element-ns.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/extensions-to-document-interface/created-callback-create-element.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/non-configurable-constructor-property.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/prototype-is-interface-prototype-object.html
testing/web-platform/tests/custom-elements/instantiating-custom-elements/unchanged-attribute.html
testing/web-platform/tests/custom-elements/registering-custom-elements/definition-construction-algorithm-default-namespace.html
testing/web-platform/tests/custom-elements/registering-custom-elements/definition-construction-algorithm-duplicate-definition.html
testing/web-platform/tests/custom-elements/registering-custom-elements/definition-construction-algorithm-invalid-type.html
testing/web-platform/tests/custom-elements/registering-custom-elements/definition-construction-algorithm-local-name-lowercased.html
testing/web-platform/tests/custom-elements/registering-custom-elements/definition-construction-algorithm-name-is-null.html
testing/web-platform/tests/custom-elements/registering-custom-elements/definition-construction-algorithm-no-interface-for-name.html
testing/web-platform/tests/custom-elements/registering-custom-elements/definition-construction-algorithm-svg-namespace-name-is-null.html
testing/web-platform/tests/custom-elements/registering-custom-elements/definition-construction-algorithm-svg-namespace.html
testing/web-platform/tests/custom-elements/registering-custom-elements/definition-construction-algorithm-type-name-lowercased.html
testing/web-platform/tests/custom-elements/registering-custom-elements/element-registration-algorithm-no-registry.html
testing/web-platform/tests/custom-elements/registering-custom-elements/extensions-to-document-interface/custom-element-name.html
testing/web-platform/tests/custom-elements/registering-custom-elements/extensions-to-document-interface/custom-element-prototype.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag-ref.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-custom-tag.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag-ref.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-custom-tag.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension-ref.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-registered-type-extension.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension-ref.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-css-test-type-extension.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-matching-query-selector-all.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-element-pseudoclass/unresolved-element-pseudoclass-matching-query-selector.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-elements-interface-html-element.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-elements-interface-html-unknown-element.html
testing/web-platform/tests/custom-elements/registering-custom-elements/unresolved-elements-interface-svg-element.html
testing/web-platform/tests/custom-elements/resources/blank.html
testing/web-platform/tests/custom-elements/resources/import-master-async.html
testing/web-platform/tests/custom-elements/resources/import-master.html
testing/web-platform/tests/custom-elements/resources/import.html
testing/web-platform/tests/custom-elements/resources/register-and-create-custom-element.html
testing/web-platform/tests/custom-elements/resources/x-element.html
testing/web-platform/tests/custom-elements/resources/x-mathml-element.html
testing/web-platform/tests/custom-elements/resources/x-svg-element.html
testing/web-platform/tests/custom-elements/testcommon.js
testing/web-platform/tests/html/dom/documents/dom-tree-accessors/document.body-getter.html
testing/web-platform/tests/html/dom/documents/dom-tree-accessors/document.body-setter-01.html
testing/web-platform/tests/html/dom/elements-microdata.js
testing/web-platform/tests/shadow-dom/styles/shadow-cascade-order.html
testing/web-platform/tests/uievents/keyboard/key-mtest-101en-us.html
testing/web-platform/tests/uievents/keyboard/key-mtest-102fr-fr.html
testing/web-platform/tests/uievents/keyboard/key-mtest.css
testing/web-platform/tests/uievents/keyboard/key-mtest.js
testing/web-platform/tests/web-animations/animatable/animate.html
testing/web-platform/tests/web-animations/animation-effect-timing/delay.html
testing/web-platform/tests/web-animations/animation-effect-timing/direction.html
testing/web-platform/tests/web-animations/animation-effect-timing/duration.html
testing/web-platform/tests/web-animations/animation-effect-timing/easing.html
testing/web-platform/tests/web-animations/animation-effect-timing/endDelay.html
testing/web-platform/tests/web-animations/animation-effect-timing/fill.html
testing/web-platform/tests/web-animations/animation-effect-timing/getAnimations.html
testing/web-platform/tests/web-animations/animation-effect-timing/getComputedStyle.html
testing/web-platform/tests/web-animations/animation-effect-timing/iterationStart.html
testing/web-platform/tests/web-animations/animation-effect-timing/iterations.html
testing/web-platform/tests/web-animations/animation-model/animation-types/not-animatable.html
testing/web-platform/tests/web-animations/animation-model/keyframes/effect-value-context.html
testing/web-platform/tests/web-animations/animation-timeline/document-timeline.html
testing/web-platform/tests/web-animations/animation-timeline/idlharness.html
testing/web-platform/tests/web-animations/animation/cancel.html
testing/web-platform/tests/web-animations/animation/constructor.html
testing/web-platform/tests/web-animations/animation/finish.html
testing/web-platform/tests/web-animations/animation/finished.html
testing/web-platform/tests/web-animations/animation/id.html
testing/web-platform/tests/web-animations/animation/oncancel.html
testing/web-platform/tests/web-animations/animation/onfinish.html
testing/web-platform/tests/web-animations/animation/pause.html
testing/web-platform/tests/web-animations/animation/play.html
testing/web-platform/tests/web-animations/animation/playState.html
testing/web-platform/tests/web-animations/animation/playbackRate.html
testing/web-platform/tests/web-animations/animation/ready.html
testing/web-platform/tests/web-animations/animation/reverse.html
testing/web-platform/tests/web-animations/animation/startTime.html
testing/web-platform/tests/web-animations/document/getAnimations.html
testing/web-platform/tests/web-animations/keyframe-effect/constructor.html
testing/web-platform/tests/web-animations/keyframe-effect/effect-easing.html
testing/web-platform/tests/web-animations/keyframe-effect/getComputedTiming.html
testing/web-platform/tests/web-animations/keyframe-effect/keyframe-handling.html
testing/web-platform/tests/web-animations/keyframe-effect/setKeyframes.html
testing/web-platform/tests/web-animations/keyframe-effect/setTarget.html
toolkit/components/telemetry/Histograms.json
toolkit/crashreporter/CrashSubmit.jsm
toolkit/crashreporter/breakpad-windows-libxul/staticruntime/moz.build
toolkit/crashreporter/nsExceptionHandler.cpp
toolkit/mozapps/update/nsUpdateService.js
toolkit/mozapps/update/tests/chrome/test_0071_notify_verifyFailPartial_noComplete.xul
toolkit/mozapps/update/tests/chrome/test_0072_notify_verifyFailComplete_noPartial.xul
toolkit/mozapps/update/tests/chrome/test_0073_notify_verifyFailPartialComplete.xul
toolkit/mozapps/update/tests/chrome/test_0074_notify_verifyFailPartial_successComplete.xul
toolkit/mozapps/update/tests/chrome/test_0081_error_patchApplyFailure_partial_only.xul
toolkit/mozapps/update/tests/chrome/test_0082_error_patchApplyFailure_complete_only.xul
toolkit/mozapps/update/tests/chrome/test_0083_error_patchApplyFailure_partial_complete.xul
toolkit/mozapps/update/tests/chrome/test_0084_error_patchApplyFailure_verify_failed.xul
toolkit/mozapps/update/tests/chrome/test_0091_installed.xul
toolkit/mozapps/update/tests/data/shared.js
toolkit/themes/osx/global/icons/find-arrows.svg
toolkit/xre/WindowsCrtPatch.h
toolkit/xre/moz.build
toolkit/xre/nsAppRunner.cpp
tools/update-packaging/app.mozbuild
tools/update-packaging/confvars.sh
--- a/.eslintignore
+++ b/.eslintignore
@@ -35,16 +35,18 @@ netwerk/**
 nsprpub/**
 other-licenses/**
 parser/**
 probes/**
 python/**
 rdf/**
 startupcache/**
 testing/**
+!testing/eslint-plugin-mozilla/
+testing/eslint-plugin-mozilla/node_modules/**
 tools/**
 uriloader/**
 view/**
 widget/**
 xpcom/**
 xpfe/**
 xulrunner/**
 
@@ -78,54 +80,49 @@ browser/extensions/loop/**
 # devtools/ exclusions
 devtools/client/canvasdebugger/**
 devtools/client/commandline/**
 devtools/client/debugger/**
 devtools/client/eyedropper/**
 devtools/client/framework/**
 # devtools/client/inspector/shared/*.js files are eslint-clean, so they aren't
 # included in the ignore list.
-devtools/client/inspector/computed/**
 devtools/client/inspector/fonts/**
-devtools/client/inspector/shared/test/**
 devtools/client/inspector/test/**
 devtools/client/inspector/*.js
 !devtools/client/inspector/breadcrumbs.js
 devtools/client/jsonview/lib/**
 devtools/client/memory/**
 devtools/client/netmonitor/test/**
 devtools/client/netmonitor/har/test/**
 devtools/client/performance/**
 devtools/client/projecteditor/**
 devtools/client/promisedebugger/**
 devtools/client/responsivedesign/**
 devtools/client/scratchpad/**
 devtools/client/shadereditor/**
-devtools/client/shared/*.js
 devtools/client/shared/*.jsm
-!devtools/client/shared/css-angle.js
-!devtools/client/shared/css-color.js
-!devtools/client/shared/css-color-db.js
-!devtools/client/shared/css-parsing-utils.js
-devtools/client/shared/components/**
-devtools/client/shared/redux/**
+devtools/client/shared/webgl-utils.js
+devtools/client/shared/developer-toolbar.js
+devtools/client/shared/components/test/**
+devtools/client/shared/redux/middleware/test/**
 devtools/client/shared/test/**
-devtools/client/shared/vendor/**
-devtools/client/shared/widgets/**
+devtools/client/shared/widgets/*.jsm
 devtools/client/sourceeditor/**
 devtools/client/webaudioeditor/**
 devtools/client/webconsole/**
 !devtools/client/webconsole/panel.js
 !devtools/client/webconsole/jsterm.js
 devtools/client/webide/**
 devtools/server/**
 !devtools/server/actors/webbrowser.js
 !devtools/server/actors/styles.js
 devtools/shared/*.js
 !devtools/shared/css-lexer.js
+!devtools/shared/task.js
 devtools/shared/*.jsm
 devtools/shared/apps/**
 devtools/shared/client/**
 devtools/shared/discovery/**
 devtools/shared/gcli/**
 !devtools/shared/gcli/templater.js
 devtools/shared/heapsnapshot/**
 devtools/shared/inspector/**
@@ -151,23 +148,34 @@ devtools/client/preferences/**
 # Ignore devtools third-party libs
 devtools/shared/jsbeautify/*
 devtools/shared/acorn/*
 devtools/client/sourceeditor/tern/*
 devtools/shared/pretty-fast/*
 devtools/shared/sourcemap/*
 devtools/shared/qrcode/decoder/*
 devtools/shared/qrcode/encoder/*
+devtools/client/shared/demangle.js
 devtools/client/shared/vendor/*
-devtools/client/shared/d3.js
-devtools/client/webaudioeditor/lib/dagre-d3.js
 devtools/client/sourceeditor/codemirror/*.js
 devtools/client/sourceeditor/codemirror/**/*.js
 devtools/client/sourceeditor/test/codemirror/*
 devtools/client/inspector/markup/test/lib_*
+devtools/client/jsonview/lib/require.js
+devtools/server/actors/utils/automation-timeline.js
+
+# Ignore devtools files testing sourcemaps / code style
+devtools/client/debugger/test/mochitest/code_binary_search.js
+devtools/client/debugger/test/mochitest/code_math.min.js
+devtools/client/debugger/test/mochitest/code_math_bogus_map.js
+devtools/client/debugger/test/mochitest/code_ugly*
+devtools/client/debugger/test/mochitest/code_worker-source-map.js
+devtools/client/framework/test/code_ugly*
+devtools/server/tests/unit/babel_and_browserify_script_with_source_map.js
+devtools/server/tests/unit/setBreakpoint*
 
 # mobile/android/ exclusions
 mobile/android/chrome/content
 mobile/android/tests/
 
 # Uses `#filter substitution`
 mobile/android/b2gdroid/app/b2gdroid.js
 mobile/android/app/mobile.js
new file mode 100644
--- /dev/null
+++ b/.flake8
@@ -0,0 +1,3 @@
+[flake8]
+max-line-length = 99
+filename = *.py, *.lint
--- a/.gitignore
+++ b/.gitignore
@@ -95,18 +95,18 @@ embedding/ios/GeckoEmbed/GeckoEmbed.xcod
 
 # Ignore mozharness execution files
 testing/mozharness/.tox/
 testing/mozharness/build/
 testing/mozharness/logs/
 testing/mozharness/.coverage
 testing/mozharness/nosetests.xml
 
-# Ignore node_modules from eslint-plugin-mozilla
-testing/eslint-plugin-mozilla/node_modules/
+# Ignore node_modules
+testing/eslint/node_modules/
 
 # Ignore talos virtualenv and tp5n files.
 # The tp5n set is supposed to be decompressed at
 # testing/talos/talos/page_load_test/tp5n in order to run tests like tps
 # locally. Similarly, running talos requires a Python package virtual
 # environment. Both the virtual environment and tp5n files end up littering
 # the status command, so we ignore them.
 testing/talos/.Python
--- a/.hgignore
+++ b/.hgignore
@@ -111,18 +111,18 @@ GPATH
 ^testing/mozharness/build/
 ^testing/mozharness/logs/
 ^testing/mozharness/.coverage
 ^testing/mozharness/nosetests.xml
 
 # Ignore tox generated dir
 .tox/
 
-# Ignore node_modules from eslint-plugin-mozilla
-^testing/eslint-plugin-mozilla/node_modules/
+# Ignore node_modules
+^testing/eslint/node_modules/
 
 # Ignore talos virtualenv and tp5n files.
 # The tp5n set is supposed to be decompressed at
 # testing/talos/talos/page_load_test/tp5n in order to run tests like tps
 # locally. Similarly, running talos requires a Python package virtual
 # environment. Both the virtual environment and tp5n files end up littering
 # the status command, so we ignore them.
 ^testing/talos/.Python
copy from testing/taskcluster/tasks/decision/try.yml
copy to .taskcluster.yml
--- a/testing/taskcluster/tasks/decision/try.yml
+++ b/.taskcluster.yml
@@ -1,116 +1,118 @@
 ---
+version: 0
 metadata:
-  name: 'Taskcluster decision task for {{project}}'
-  description: |
-    Try push for {{owner}}.
+  name: 'Taskcluster tasks for Gecko'
+  description: "The taskcluster task graph for Gecko trees"
   owner: mozilla-taskcluster-maintenance@mozilla.com
-  source: "{{{source}}}"
+  source: {{{source}}}
 
 scopes:
   # Note the below scopes are insecure however these get overriden on the server
   # side to whatever scopes are set by mozilla-taskcluster.
   - queue:*
   - docker-worker:*
   - scheduler:*
 
+# Available mustache parameters (see the mozilla-taskcluster source):
+#
+# - owner:          push user (email address)
+# - source:         URL of this YAML file
+# - url:            repository URL
+# - project:        alias for the destination repository (basename of
+#                   the repo url)
+# - level:          SCM level of the destination repository
+#                   (1 = try, 3 = core)
+# - revision:       (short) hg revision of the head of the push
+# - revision_hash:  (long) hg revision of the head of the push
+# - comment:        comment of the push
+# - pushlog_id:     id in the pushlog table of the repository
+#
+# and functions:
+# - as_slugid:      convert a label into a slugId
+# - from_now:       generate a timestamp at a fixed offset from now
+
 tasks:
   - taskId: '{{#as_slugid}}decision task{{/as_slugid}}'
-    reruns: 3
     task:
       created: '{{now}}'
       deadline: '{{#from_now}}1 day{{/from_now}}'
       expires: '{{#from_now}}14 day{{/from_now}}'
       metadata:
         owner: mozilla-taskcluster-maintenance@mozilla.com
         source: {{{source}}}
-        name: "[tc] Initial decision task for try"
+        name: "Gecko Decision Task"
         description: |
-          This is the single most important task as it decides how all other tasks
-          get built.
+            The task that creates all of the other tasks in the task graph
 
       workerType: "gecko-decision"
       provisionerId: "aws-provisioner-v1"
 
       tags:
         createdForUser: {{owner}}
 
       scopes:
-        - "docker-worker:cache:level-{{level}}-{{project}}-tc-vcs-public-sources"
-        - "docker-worker:cache:level-{{level}}-{{project}}-gecko-decision"
-        - "queue:route:tc-treeherder-stage.{{project}}.{{revision_hash}}"
-        - "queue:route:tc-treeherder.{{project}}.{{revision_hash}}"
-        - "scheduler:extend-task-graph:*"
+        # Bug 1269443: cache scopes, etc. must be listed explicitly
+        - "docker-worker:cache:level-{{level}}-*"
+        - "docker-worker:cache:tooltool-cache"
         - "secrets:get:project/taskcluster/gecko/hgfingerprint"
+        # mozilla-taskcluster will append the appropriate assume:repo:<repo>
+        # scope here.
 
       routes:
         - "index.gecko.v2.{{project}}.latest.firefox.decision"
         - "tc-treeherder.{{project}}.{{revision_hash}}"
         - "tc-treeherder-stage.{{project}}.{{revision_hash}}"
 
       payload:
         env:
+          # checkout-gecko uses these to check out the source; the inputs
+          # to `mach taskgraph decision` are all on the command line.
           GECKO_BASE_REPOSITORY: 'https://hg.mozilla.org/mozilla-central'
           GECKO_HEAD_REPOSITORY: '{{{url}}}'
           GECKO_HEAD_REF: '{{revision}}'
           GECKO_HEAD_REV: '{{revision}}'
 
         cache:
-          # The taskcluster-vcs tooling stores the large clone caches in this
-          # directory and will reuse them for new requests this saves about 20s~ and
-          # is the most generic cache possible.
           level-{{level}}-{{project}}-tc-vcs-public-sources: /home/worker/.tc-vcs/
           level-{{level}}-{{project}}-gecko-decision: /home/worker/workspace
 
         features:
           taskclusterProxy: true
 
         # Note: This task is built server side without the context or tooling that
         # exist in tree so we must hard code the version
         image: 'taskcluster/decision:0.1.0'
 
-        # Virtually no network or other potentially risky operations happen as part
-        # of the task timeout aside from the initial clone. We intentionally have
-        # set this to a lower value _all_ decision tasks should use a root
-        # repository which is cached.
         maxRunTime: 1800
 
         command:
           - /bin/bash
           - -cx
           - >
             mkdir -p /home/worker/artifacts &&
             checkout-gecko workspace &&
             cd workspace/gecko &&
-            ./mach taskcluster-graph
+            ln -s /home/worker/artifacts artifacts &&
+            ./mach taskgraph decision
             --pushlog-id='{{pushlog_id}}'
             --project='{{project}}'
             --message='{{comment}}'
             --owner='{{owner}}'
             --level='{{level}}'
+            --base-repository='https://hg.mozilla.org/mozilla-central'
+            --head-repository='{{{url}}}'
+            --head-ref='{{revision}}'
+            --head-rev='{{revision}}'
             --revision-hash='{{revision_hash}}'
-            --extend-graph > /home/worker/artifacts/graph.json &&
-            ./mach taskcluster-graph
-            --pushlog-id='{{pushlog_id}}'
-            --project='{{project}}'
-            --message='try: -b do -p all -u all'
-            --owner='{{owner}}'
-            --revision-hash='{{revision_hash}}'
-            --extend-graph > /home/worker/artifacts/all_tasks.json
-
-        graphs:
-          - /home/worker/artifacts/graph.json
 
         artifacts:
           'public':
             type: 'directory'
             path: '/home/worker/artifacts'
-            # Arbitrary value for keeping these artifacts around.  They are just the
-            # graph.json and context directories for now, so nothing that needs
-            # to stay around for long.
             expires: '{{#from_now}}7 days{{/from_now}}'
 
       extra:
         treeherder:
           symbol: D
           revision: '{{revision}}'
           revision_hash: '{{revision_hash}}'
--- 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 1265131 - Update Skia to m51 branch
+Bug 1271829 - Compile nss with SSE2 optimizations
--- a/accessible/atk/moz.build
+++ b/accessible/atk/moz.build
@@ -50,9 +50,12 @@ if 'gtk' in CONFIG['MOZ_WIDGET_TOOLKIT']
 if CONFIG['MOZ_ENABLE_DBUS']:
     CXXFLAGS += CONFIG['MOZ_DBUS_CFLAGS']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 if CONFIG['CLANG_CXX'] or CONFIG['GNU_CXX']:
     # Used in G_DEFINE_TYPE_EXTENDED macro, probably fixed in newer glib /
     # gobject headers. See bug 1243331 comment 3.
-    CXXFLAGS += ['-Wno-unused-local-typedefs']
+    CXXFLAGS += [
+        '-Wno-error=shadow',
+        '-Wno-unused-local-typedefs',
+    ]
--- a/accessible/base/AccEvent.cpp
+++ b/accessible/base/AccEvent.cpp
@@ -175,17 +175,17 @@ AccVCChangeEvent::
     mOldAccessible(aOldAccessible), mOldStart(aOldStart), mOldEnd(aOldEnd),
     mReason(aReason)
 {
 }
 
 already_AddRefed<nsIAccessibleEvent>
 a11y::MakeXPCEvent(AccEvent* aEvent)
 {
-  DocAccessible* doc = aEvent->GetDocAccessible();
+  DocAccessible* doc = aEvent->Document();
   Accessible* acc = aEvent->GetAccessible();
   nsINode* node = acc->GetNode();
   nsIDOMNode* domNode = node ? node->AsDOMNode() : nullptr;
   bool fromUser = aEvent->IsFromUserInput();
   uint32_t type = aEvent->GetEventType();
   uint32_t eventGroup = aEvent->GetEventGroups();
   nsCOMPtr<nsIAccessibleEvent> xpEvent;
 
--- a/accessible/base/AccEvent.h
+++ b/accessible/base/AccEvent.h
@@ -83,17 +83,17 @@ public:
   // AccEvent
   uint32_t GetEventType() const { return mEventType; }
   EEventRule GetEventRule() const { return mEventRule; }
   bool IsFromUserInput() const { return mIsFromUserInput; }
   EIsFromUserInput FromUserInput() const
     { return static_cast<EIsFromUserInput>(mIsFromUserInput); }
 
   Accessible* GetAccessible() const { return mAccessible; }
-  DocAccessible* GetDocAccessible() const { return mAccessible->Document(); }
+  DocAccessible* Document() const { return mAccessible->Document(); }
 
   /**
    * Down casting.
    */
   enum EventGroup {
     eGenericEvent,
     eStateChangeEvent,
     eTextChangeEvent,
--- a/accessible/base/EventQueue.cpp
+++ b/accessible/base/EventQueue.cpp
@@ -25,17 +25,17 @@ const unsigned int kSelChangeCountToPack
 ////////////////////////////////////////////////////////////////////////////////
 // EventQueue
 ////////////////////////////////////////////////////////////////////////////////
 
 bool
 EventQueue::PushEvent(AccEvent* aEvent)
 {
   NS_ASSERTION((aEvent->mAccessible && aEvent->mAccessible->IsApplication()) ||
-               aEvent->GetDocAccessible() == mDocument,
+               aEvent->Document() == mDocument,
                "Queued event belongs to another document!");
 
   if (!mEvents.AppendElement(aEvent))
     return false;
 
   // Filter events.
   CoalesceEvents();
 
--- a/accessible/base/EventTree.cpp
+++ b/accessible/base/EventTree.cpp
@@ -176,68 +176,82 @@ TreeMutation::Done()
 #endif
 }
 
 
 ////////////////////////////////////////////////////////////////////////////////
 // EventTree
 
 void
-EventTree::Process()
+EventTree::Process(const RefPtr<DocAccessible>& aDeathGrip)
 {
   while (mFirst) {
     // Skip a node and its subtree if its container is not in the document.
     if (mFirst->mContainer->IsInDocument()) {
-      mFirst->Process();
+      mFirst->Process(aDeathGrip);
+      if (aDeathGrip->IsDefunct()) {
+        return;
+      }
     }
     mFirst = mFirst->mNext.forget();
   }
 
   MOZ_ASSERT(mContainer || mDependentEvents.IsEmpty(),
              "No container, no events");
   MOZ_ASSERT(!mContainer || !mContainer->IsDefunct(),
              "Processing events for defunct container");
+  MOZ_ASSERT(!mFireReorder || mContainer, "No target for reorder event");
 
   // Fire mutation events.
   uint32_t eventsCount = mDependentEvents.Length();
   for (uint32_t jdx = 0; jdx < eventsCount; jdx++) {
     AccMutationEvent* mtEvent = mDependentEvents[jdx];
     MOZ_ASSERT(mtEvent->mEventRule != AccEvent::eDoNotEmit,
                "The event shouldn't be presented in the tree");
+    MOZ_ASSERT(mtEvent->Document(), "No document for event target");
 
     nsEventShell::FireEvent(mtEvent);
+    if (aDeathGrip->IsDefunct()) {
+      return;
+    }
+
     if (mtEvent->mTextChangeEvent) {
       nsEventShell::FireEvent(mtEvent->mTextChangeEvent);
+      if (aDeathGrip->IsDefunct()) {
+        return;
+      }
     }
 
     if (mtEvent->IsHide()) {
       // Fire menupopup end event before a hide event if a menu goes away.
 
       // XXX: We don't look into children of hidden subtree to find hiding
       // menupopup (as we did prior bug 570275) because we don't do that when
       // menu is showing (and that's impossible until bug 606924 is fixed).
       // Nevertheless we should do this at least because layout coalesces
       // the changes before our processing and we may miss some menupopup
       // events. Now we just want to be consistent in content insertion/removal
       // handling.
       if (mtEvent->mAccessible->ARIARole() == roles::MENUPOPUP) {
         nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_END,
                                 mtEvent->mAccessible);
+        if (aDeathGrip->IsDefunct()) {
+          return;
+        }
       }
 
       AccHideEvent* hideEvent = downcast_accEvent(mtEvent);
       if (hideEvent->NeedsShutdown()) {
-        mtEvent->GetDocAccessible()->ShutdownChildrenInSubtree(mtEvent->mAccessible);
+        aDeathGrip->ShutdownChildrenInSubtree(mtEvent->mAccessible);
       }
     }
   }
 
   // Fire reorder event at last.
   if (mFireReorder) {
-    MOZ_ASSERT(mContainer);
     nsEventShell::FireEvent(nsIAccessibleEvent::EVENT_REORDER, mContainer);
     mContainer->Document()->MaybeNotifyOfValueChange(mContainer);
   }
 
   mDependentEvents.Clear();
 }
 
 EventTree*
@@ -351,17 +365,17 @@ EventTree::Clear()
   mFirst = nullptr;
   mNext = nullptr;
   mContainer = nullptr;
 
   uint32_t eventsCount = mDependentEvents.Length();
   for (uint32_t jdx = 0; jdx < eventsCount; jdx++) {
     AccHideEvent* ev = downcast_accEvent(mDependentEvents[jdx]);
     if (ev && ev->NeedsShutdown()) {
-      ev->GetDocAccessible()->ShutdownChildrenInSubtree(ev->mAccessible);
+      ev->Document()->ShutdownChildrenInSubtree(ev->mAccessible);
     }
   }
   mDependentEvents.Clear();
 }
 
 const EventTree*
 EventTree::Find(const Accessible* aContainer) const
 {
--- a/accessible/base/EventTree.h
+++ b/accessible/base/EventTree.h
@@ -82,17 +82,17 @@ public:
 #ifdef A11Y_LOG
   void Log(uint32_t aLevel = UINT32_MAX) const;
 #endif
 
 private:
   /**
    * Processes the event queue and fires events.
    */
-  void Process();
+  void Process(const RefPtr<DocAccessible>& aDeathGrip);
 
   /**
    * Return an event subtree for the given accessible.
    */
   EventTree* FindOrInsert(Accessible* aContainer);
 
   void Mutated(AccMutationEvent* aEv);
   void Clear();
--- a/accessible/base/FocusManager.cpp
+++ b/accessible/base/FocusManager.cpp
@@ -274,17 +274,17 @@ FocusManager::ProcessFocusEvent(AccEvent
 
   // Emit focus event if event target is the active item. Otherwise then check
   // if it's still focused and then update active item and emit focus event.
   Accessible* target = aEvent->GetAccessible();
   if (target != mActiveItem) {
 
     // Check if still focused. Otherwise we can end up with storing the active
     // item for control that isn't focused anymore.
-    DocAccessible* document = aEvent->GetDocAccessible();
+    DocAccessible* document = aEvent->Document();
     nsINode* focusedNode = FocusedDOMNode();
     if (!focusedNode)
       return;
 
     Accessible* DOMFocus =
       document->GetAccessibleEvenIfNotInMapOrContainer(focusedNode);
     if (target != DOMFocus)
       return;
--- a/accessible/base/NotificationController.cpp
+++ b/accessible/base/NotificationController.cpp
@@ -396,17 +396,19 @@ NotificationController::WillRefresh(mozi
   }
   mRelocations.Clear();
 
   // If a generic notification occurs after this point then we may be allowed to
   // process it synchronously.  However we do not want to reenter if fireing
   // events causes script to run.
   mObservingState = eRefreshProcessing;
 
-  mEventTree.Process();
+  RefPtr<DocAccessible> deathGrip(mDocument);
+  mEventTree.Process(deathGrip);
+  deathGrip = nullptr;
 
   ProcessEventQueue();
 
   if (IPCAccessibilityActive()) {
     size_t newDocCount = newChildDocs.Length();
     for (size_t i = 0; i < newDocCount; i++) {
       DocAccessible* childDoc = newChildDocs[i];
       Accessible* parent = childDoc->Parent();
--- a/accessible/base/moz.build
+++ b/accessible/base/moz.build
@@ -92,8 +92,11 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
+
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wno-error=shadow']
--- a/accessible/generic/Accessible.cpp
+++ b/accessible/generic/Accessible.cpp
@@ -185,26 +185,17 @@ Accessible::Description(nsString& aDescr
   if (!HasOwnContent() || mContent->IsNodeOfType(nsINode::eTEXT))
     return;
 
   nsTextEquivUtils::
     GetTextEquivFromIDRefs(this, nsGkAtoms::aria_describedby,
                            aDescription);
 
   if (aDescription.IsEmpty()) {
-    bool isXUL = mContent->IsXULElement();
-    if (isXUL) {
-      // Try XUL <description control="[id]">description text</description>
-      XULDescriptionIterator iter(Document(), mContent);
-      Accessible* descr = nullptr;
-      while ((descr = iter.Next())) {
-        nsTextEquivUtils::AppendTextEquivFromContent(this, descr->GetContent(),
-                                                     &aDescription);
-      }
-    }
+    NativeDescription(aDescription);
 
     if (aDescription.IsEmpty()) {
       // Keep the Name() method logic.
       if (mContent->IsHTMLElement()) {
         mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::title, aDescription);
       } else if (mContent->IsXULElement()) {
         mContent->GetAttr(kNameSpaceID_None, nsGkAtoms::tooltiptext, aDescription);
       } else if (mContent->IsSVGElement()) {
@@ -1965,16 +1956,32 @@ Accessible::NativeName(nsString& aName)
     }
   }
 
   return eNameOK;
 }
 
 // Accessible protected
 void
+Accessible::NativeDescription(nsString& aDescription)
+{
+  bool isXUL = mContent->IsXULElement();
+  if (isXUL) {
+    // Try XUL <description control="[id]">description text</description>
+    XULDescriptionIterator iter(Document(), mContent);
+    Accessible* descr = nullptr;
+    while ((descr = iter.Next())) {
+      nsTextEquivUtils::AppendTextEquivFromContent(this, descr->GetContent(),
+                                                   &aDescription);
+    }
+  }
+}
+
+// Accessible protected
+void
 Accessible::BindToParent(Accessible* aParent, uint32_t aIndexInParent)
 {
   MOZ_ASSERT(aParent, "This method isn't used to set null parent");
   MOZ_ASSERT(!mParent, "The child was expected to be moved");
 
 #ifdef A11Y_LOG
   if (mParent) {
     logging::TreeInfo("BindToParent: stealing accessible", 0,
--- a/accessible/generic/Accessible.h
+++ b/accessible/generic/Accessible.h
@@ -951,16 +951,22 @@ protected:
 
   /**
    * Return the accessible name provided by native markup. It doesn't take
    * into account ARIA markup used to specify the name.
    */
   virtual mozilla::a11y::ENameValueFlag NativeName(nsString& aName);
 
   /**
+   * Return the accessible description provided by native markup. It doesn't take
+   * into account ARIA markup used to specify the description.
+   */
+  virtual void NativeDescription(nsString& aDescription);
+
+  /**
    * Return object attributes provided by native markup. It doesn't take into
    * account ARIA.
    */
   virtual already_AddRefed<nsIPersistentProperties> NativeAttributes();
 
   //////////////////////////////////////////////////////////////////////////////
   // Initializing, cache and tree traverse methods
 
--- a/accessible/generic/ApplicationAccessible.cpp
+++ b/accessible/generic/ApplicationAccessible.cpp
@@ -22,16 +22,17 @@
 
 using namespace mozilla::a11y;
 
 ApplicationAccessible::ApplicationAccessible() :
   AccessibleWrap(nullptr, nullptr)
 {
   mType = eApplicationType;
   mAppInfo = do_GetService("@mozilla.org/xre/app-info;1");
+  MOZ_ASSERT(mAppInfo, "no application info");
 }
 
 NS_IMPL_ISUPPORTS_INHERITED0(ApplicationAccessible, Accessible)
 
 ////////////////////////////////////////////////////////////////////////////////
 // nsIAccessible
 
 ENameValueFlag
--- a/accessible/generic/ApplicationAccessible.h
+++ b/accessible/generic/ApplicationAccessible.h
@@ -55,38 +55,50 @@ public:
   // ActionAccessible
   virtual KeyBinding AccessKey() const override;
 
   // ApplicationAccessible
   void Init();
 
   void AppName(nsAString& aName) const
   {
-    nsAutoCString cname;
-    mAppInfo->GetName(cname);
-    AppendUTF8toUTF16(cname, aName);
+    MOZ_ASSERT(mAppInfo, "no application info");
+
+    if (mAppInfo) {
+      nsAutoCString cname;
+      mAppInfo->GetName(cname);
+      AppendUTF8toUTF16(cname, aName);
+    }
   }
 
   void AppVersion(nsAString& aVersion) const
   {
-    nsAutoCString cversion;
-    mAppInfo->GetVersion(cversion);
-    AppendUTF8toUTF16(cversion, aVersion);
+    MOZ_ASSERT(mAppInfo, "no application info");
+
+    if (mAppInfo) {
+      nsAutoCString cversion;
+      mAppInfo->GetVersion(cversion);
+      AppendUTF8toUTF16(cversion, aVersion);
+    }
   }
 
   void PlatformName(nsAString& aName) const
   {
     aName.AssignLiteral("Gecko");
   }
 
   void PlatformVersion(nsAString& aVersion) const
   {
-    nsAutoCString cversion;
-    mAppInfo->GetPlatformVersion(cversion);
-    AppendUTF8toUTF16(cversion, aVersion);
+    MOZ_ASSERT(mAppInfo, "no application info");
+
+    if (mAppInfo) {
+      nsAutoCString cversion;
+      mAppInfo->GetPlatformVersion(cversion);
+      AppendUTF8toUTF16(cversion, aVersion);
+    }
   }
 
 protected:
   virtual ~ApplicationAccessible() {}
 
   // Accessible
   virtual Accessible* GetSiblingAtOffset(int32_t aOffset,
                                          nsresult *aError = nullptr) const override;
--- a/accessible/generic/DocAccessible-inl.h
+++ b/accessible/generic/DocAccessible-inl.h
@@ -165,16 +165,27 @@ DocAccessible::CreateSubtree(Accessible*
 {
   // If a focused node has been shown then it could mean its frame was recreated
   // while the node stays focused and we need to fire focus event on
   // the accessible we just created. If the queue contains a focus event for
   // this node already then it will be suppressed by this one.
   Accessible* focusedAcc = nullptr;
   CacheChildrenInSubtree(aChild, &focusedAcc);
 
+  // Fire events for ARIA elements.
+  if (aChild->HasARIARole()) {
+    roles::Role role = aChild->ARIARole();
+    if (role == roles::MENUPOPUP) {
+      FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aChild);
+    }
+    else if (role == roles::ALERT) {
+      FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aChild);
+    }
+  }
+
   // XXX: do we really want to send focus to focused DOM node not taking into
   // account active item?
   if (focusedAcc) {
     FocusMgr()->DispatchFocusEvent(this, focusedAcc);
     SelectionMgr()->
       SetControlSelectionListener(focusedAcc->GetNode()->AsElement());
   }
 }
--- a/accessible/generic/DocAccessible.cpp
+++ b/accessible/generic/DocAccessible.cpp
@@ -532,22 +532,22 @@ DocAccessible::RelativeBounds(nsIFrame**
 
   return bounds;
 }
 
 // DocAccessible protected member
 nsresult
 DocAccessible::AddEventListeners()
 {
-  nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem(mDocumentNode->GetDocShell());
+  nsCOMPtr<nsIDocShell> docShell(mDocumentNode->GetDocShell());
 
   // We want to add a command observer only if the document is content and has
   // an editor.
-  if (docShellTreeItem->ItemType() == nsIDocShellTreeItem::typeContent) {
-    nsCOMPtr<nsICommandManager> commandManager = do_GetInterface(docShellTreeItem);
+  if (docShell->ItemType() == nsIDocShellTreeItem::typeContent) {
+    nsCOMPtr<nsICommandManager> commandManager = docShell->GetCommandManager();
     if (commandManager)
       commandManager->AddCommandObserver(this, "obs_documentCreated");
   }
 
   SelectionMgr()->AddDocSelectionListener(mPresShell);
 
   // Add document observer.
   mDocumentNode->AddObserver(this);
@@ -562,22 +562,22 @@ DocAccessible::RemoveEventListeners()
   // Remove scroll position listener
   RemoveScrollListener();
 
   NS_ASSERTION(mDocumentNode, "No document during removal of listeners.");
 
   if (mDocumentNode) {
     mDocumentNode->RemoveObserver(this);
 
-    nsCOMPtr<nsIDocShellTreeItem> docShellTreeItem(mDocumentNode->GetDocShell());
-    NS_ASSERTION(docShellTreeItem, "doc should support nsIDocShellTreeItem.");
+    nsCOMPtr<nsIDocShell> docShell(mDocumentNode->GetDocShell());
+    NS_ASSERTION(docShell, "doc should support nsIDocShellTreeItem.");
 
-    if (docShellTreeItem) {
-      if (docShellTreeItem->ItemType() == nsIDocShellTreeItem::typeContent) {
-        nsCOMPtr<nsICommandManager> commandManager = do_GetInterface(docShellTreeItem);
+    if (docShell) {
+      if (docShell->ItemType() == nsIDocShellTreeItem::typeContent) {
+        nsCOMPtr<nsICommandManager> commandManager = docShell->GetCommandManager();
         if (commandManager) {
           commandManager->RemoveCommandObserver(this, "obs_documentCreated");
         }
       }
     }
   }
 
   if (mScrollWatchTimer) {
@@ -2176,29 +2176,19 @@ DocAccessible::CacheChildrenInSubtree(Ac
     mt.Done();
   }
 
   // Fire events for ARIA elements.
   if (!aRoot->HasARIARole()) {
     return;
   }
 
-  roles::Role role = aRoot->ARIARole();
-  if (role == roles::MENUPOPUP) {
-    FireDelayedEvent(nsIAccessibleEvent::EVENT_MENUPOPUP_START, aRoot);
-    return;
-  }
-
-  if (role == roles::ALERT) {
-    FireDelayedEvent(nsIAccessibleEvent::EVENT_ALERT, aRoot);
-    return;
-  }
-
   // XXX: we should delay document load complete event if the ARIA document
   // has aria-busy.
+  roles::Role role = aRoot->ARIARole();
   if (!aRoot->IsDoc() && (role == roles::DIALOG || role == roles::DOCUMENT)) {
     FireDelayedEvent(nsIAccessibleEvent::EVENT_DOCUMENT_LOAD_COMPLETE, aRoot);
   }
 }
 
 void
 DocAccessible::UncacheChildrenInSubtree(Accessible* aRoot)
 {
--- a/accessible/generic/moz.build
+++ b/accessible/generic/moz.build
@@ -52,8 +52,11 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
+
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wno-error=shadow']
--- a/accessible/html/moz.build
+++ b/accessible/html/moz.build
@@ -38,8 +38,11 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
         '/accessible/mac',
     ]
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
 FINAL_LIBRARY = 'xul'
+
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wno-error=shadow']
--- a/accessible/ipc/moz.build
+++ b/accessible/ipc/moz.build
@@ -43,8 +43,11 @@ if CONFIG['ACCESSIBILITY']:
     else:
         LOCAL_INCLUDES += [
             '/accessible/other',
         ]
 
     FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
+
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wno-error=shadow']
--- a/accessible/other/moz.build
+++ b/accessible/other/moz.build
@@ -17,8 +17,11 @@ SOURCES += [
 LOCAL_INCLUDES += [
     '/accessible/base',
     '/accessible/generic',
     '/accessible/html',
     '/accessible/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
+
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wno-error=shadow']
--- a/accessible/tests/mochitest/events/test_mutation.html
+++ b/accessible/tests/mochitest/events/test_mutation.html
@@ -372,16 +372,68 @@
       }
 
       this.getID = function showHiddenParentOfVisibleChild_getID()
       {
         return "show hidden parent of visible child";
       }
     }
 
+    function hideNDestroyDoc()
+    {
+      this.txt = null;
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, function() { return this.txt; }.bind(this))
+      ];
+
+      this.invoke = function hideNDestroyDoc_invoke()
+      {
+        this.txt = getAccessible('c5').firstChild.firstChild;
+        this.txt.DOMNode.parentNode.removeChild(this.txt.DOMNode);
+      }
+
+      this.check = function hideNDestroyDoc_check()
+      {
+        getNode('c5').parentNode.removeChild(getNode('c5'));
+      }
+
+      this.getID = function hideNDestroyDoc_getID()
+      {
+        return "remove text node and destroy a document on hide event";
+      }
+    }
+
+    function hideHideNDestroyDoc()
+    {
+      this.target = null;
+      this.eventSeq = [
+        new invokerChecker(EVENT_HIDE, function() { return this.target; }.bind(this))
+      ];
+
+      this.invoke = function hideHideNDestroyDoc_invoke()
+      {
+        var doc = getAccessible('c6').firstChild;
+        var l1 = doc.firstChild;
+        this.target = l1.firstChild;
+        var l2 = doc.lastChild;
+        l1.DOMNode.removeChild(l1.DOMNode.firstChild);
+        l2.DOMNode.removeChild(l2.DOMNode.firstChild);
+      }
+
+      this.check = function hideHideNDestroyDoc_check()
+      {
+        getNode('c6').parentNode.removeChild(getNode('c6'));
+      }
+
+      this.getID = function hideHideNDestroyDoc_getID()
+      {
+        return "remove text nodes (2 events in the queue) and destroy a document on first hide event";
+      }
+    }
+
     /**
      * Target getters.
      */
     function getFirstChild(aNode)
     {
       return [aNode.firstChild];
     }
     function getLastChild(aNode)
@@ -502,16 +554,18 @@
 
       gQueue.push(new test1("testContainer"));
       gQueue.push(new test2("testContainer", "testContainer2"));
       gQueue.push(new test2("testContainer", "testNestedContainer"));
       gQueue.push(new test3("testContainer"));
       gQueue.push(new insertReferredElm("testContainer3"));
       gQueue.push(new showHiddenParentOfVisibleChild());
 
+      gQueue.push(new hideNDestroyDoc());
+      gQueue.push(new hideHideNDestroyDoc());
       gQueue.invoke(); // Will call SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTests);
   </script>
 </head>
 
@@ -564,12 +618,15 @@
     <div id="container3" class="visibilityHidden"><a id="link8">Link #8</a></div>
     <div id="testNestedContainer"></div>
   </div>
   <div id="testContainer2"></div>
   <div id="testContainer3"></div>
 
   <div id="c4">
     <div style="visibility:hidden" id="c4_middle">
-     <div style="visibility:visible" id="c4_child"></div>
-   </div>
+    <div style="visibility:visible" id="c4_child"></div>
+  </div>
+
+  <iframe id="c5" src="data:text/html,hey"></iframe>
+  <iframe id="c6" src="data:text/html,<label>l</label><label>l</label>"></iframe>
 </body>
 </html>
--- a/accessible/tests/mochitest/name/test_general.xul
+++ b/accessible/tests/mochitest/name/test_general.xul
@@ -40,17 +40,17 @@
 
       // Multiple relations. The value of 'aria-labelledby' contains the IDs
       // of elements. Gets the name from text nodes of those elements.
       testName("btn_labelledby_texts", "text1 text2");
 
       // Trick cases. Self and recursive referencing.
       testName("rememberHistoryDays", "Remember 3 days");
       testName("historyDays", "Remember 3 days");
-      testName("rememberAfter", null); // XUL labels doesn't allow name from subtree
+      testName("rememberAfter", "days");
 
       // Anonymous content (see name.xbl#third)
       var anonBtn = getAccessible("labelledby_box_anon").lastChild;
       testName(anonBtn, "It's a cool button");
 
       //////////////////////////////////////////////////////////////////////////
       // Name from subtree (single relation labelled_by).
       
@@ -168,16 +168,21 @@
       // the visible children (bug 443081)
       testName("lb_opt1_children_hidden", "i am visible");
 
 
       //////////////////////////////////////////////////////////////////////////
       // Name from aria-labelledby: menuitem label+ listitem label
       testName("li_labelledby", "Show an Alert The moment the event starts");
 
+      //////////////////////////////////////////////////////////////////////////
+      // groupbox labeling from caption label or its sub tree
+      testName("groupbox", "Some caption");
+      testName("groupbox2", "Some caption");
+
       SimpleTest.finish();
     }
 
     SimpleTest.waitForExplicitFinish();
     addA11yLoadEvent(doTest);
   ]]>
   </script>
 
@@ -335,16 +340,26 @@
   <box id="box_children" role="button">14</box>
 
   <!-- name from children, hidden children -->
   <vbox role="listbox" tabindex="0">
     <hbox id="lb_opt1_children_hidden" role="option" tabindex="0">
       <description>i am visible</description>
       <description style="display:none">i am hidden</description>
     </hbox>
+
+    <!-- Name from label or sub tree -->
+    <groupbox id="groupbox">
+      <caption label="Some caption" />
+      <checkbox label="some checkbox label" />
+    </groupbox>
+    <groupbox id="groupbox2">
+      <caption><label>Some caption</label></caption>
+      <checkbox label="some checkbox label" />
+    </groupbox>
   </vbox>
 
   <!-- bug 441991; create name from other menuitem label listitem's own label -->
   <hbox>
     <listbox>
     <listitem id="li_labelledby"
               label="The moment the event starts"
               aria-labelledby="menuitem-DISPLAY li_labelledby"/>
--- a/accessible/windows/ia2/moz.build
+++ b/accessible/windows/ia2/moz.build
@@ -42,19 +42,16 @@ LOCAL_INCLUDES += [
     '/accessible/windows',
     '/accessible/windows/msaa',
     '/accessible/xpcom',
     '/accessible/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
 
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wshadow']
-
 # The Windows MIDL code generator creates things like:
 #
 #   #endif !_MIDL_USE_GUIDDEF_
 #
 # which clang-cl complains about.  MSVC doesn't, so turn this warning off.
 if CONFIG['CLANG_CL']:
     CXXFLAGS += ['-Wno-extra-tokens']
 
--- a/accessible/windows/msaa/moz.build
+++ b/accessible/windows/msaa/moz.build
@@ -65,11 +65,8 @@ LOCAL_INCLUDES += [
 #
 # which clang-cl complains about.  MSVC doesn't, so turn this warning off.
 if CONFIG['CLANG_CL']:
     CXXFLAGS += ['-Wno-extra-tokens']
 
 include('/ipc/chromium/chromium-config.mozbuild')
 
 FINAL_LIBRARY = 'xul'
-
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wshadow']
--- a/accessible/windows/sdn/moz.build
+++ b/accessible/windows/sdn/moz.build
@@ -15,11 +15,8 @@ LOCAL_INCLUDES += [
     '/accessible/generic',
     '/accessible/html',
     '/accessible/windows/msaa',
     '/accessible/xpcom',
     '/accessible/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wshadow']
--- a/accessible/windows/uia/moz.build
+++ b/accessible/windows/uia/moz.build
@@ -13,11 +13,8 @@ LOCAL_INCLUDES += [
     '/accessible/generic',
     '/accessible/html',
     '/accessible/windows/msaa',
     '/accessible/xpcom',
     '/accessible/xul',
 ]
 
 FINAL_LIBRARY = 'xul'
-
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wshadow']
--- a/accessible/xpcom/moz.build
+++ b/accessible/xpcom/moz.build
@@ -61,8 +61,11 @@ xpc_acc_events_h.inputs += ['AccEvents.c
 
 xpc_acc_events_cpp = GENERATED_FILES['xpcAccEvents.cpp']
 xpc_acc_events_cpp.script = 'AccEventGen.py:gen_cpp_file'
 xpc_acc_events_cpp.inputs += ['AccEvents.conf']
 
 FINAL_LIBRARY = 'xul'
 
 include('/ipc/chromium/chromium-config.mozbuild')
+
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wno-error=shadow']
--- a/accessible/xul/XULElementAccessibles.cpp
+++ b/accessible/xul/XULElementAccessibles.cpp
@@ -64,17 +64,17 @@ XULLabelAccessible::Shutdown()
 ENameValueFlag
 XULLabelAccessible::NativeName(nsString& aName)
 {
   // if the value attr doesn't exist, the screen reader must get the accessible text
   // from the accessible text interface or from the children
   if (mValueTextLeaf)
     return mValueTextLeaf->Name(aName);
 
-  return eNameOK;
+  return Accessible::NativeName(aName);
 }
 
 role
 XULLabelAccessible::NativeRole()
 {
   return roles::LABEL;
 }
 
--- a/accessible/xul/moz.build
+++ b/accessible/xul/moz.build
@@ -43,8 +43,11 @@ elif CONFIG['MOZ_WIDGET_TOOLKIT'] == 'co
         '/accessible/mac',
     ]
 else:
     LOCAL_INCLUDES += [
         '/accessible/other',
     ]
 
 FINAL_LIBRARY = 'xul'
+
+if CONFIG['GNU_CXX']:
+    CXXFLAGS += ['-Wno-error=shadow']
--- a/addon-sdk/source/python-lib/cuddlefish/prefs.py
+++ b/addon-sdk/source/python-lib/cuddlefish/prefs.py
@@ -32,19 +32,16 @@ DEFAULT_COMMON_PREFS = {
     # Disable intalling any distribution add-ons
     'extensions.installDistroAddons' : False,
     # Allow installing extensions dropped into the profile folder
     'extensions.autoDisableScopes' : 10,
 
     # shut up some warnings on `about:` page
     'app.releaseNotesURL': 'http://localhost/app-dummy/',
     'app.vendorURL': 'http://localhost/app-dummy/',
-
-    # Don't prompt about e10s
-    'browser.displayedE10SPrompt.1': 5
 }
 
 DEFAULT_NO_CONNECTIONS_PREFS = {
     'toolkit.telemetry.enabled': False,
     'toolkit.telemetry.server': 'https://localhost/telemetry-dummy/',
     'app.update.auto' : False,
     'app.update.url': 'http://localhost/app-dummy/update',
     # Make sure GMPInstallManager won't hit the network.
--- a/addon-sdk/source/test/preferences/e10s-off.json
+++ b/addon-sdk/source/test/preferences/e10s-off.json
@@ -1,6 +1,5 @@
 {
-  "browser.displayedE10SPrompt.1": 5,
   "browser.tabs.remote.autostart": false,
   "browser.tabs.remote.autostart.1": false,
   "browser.tabs.remote.autostart.2": false
 }
--- a/b2g/app/moz.build
+++ b/b2g/app/moz.build
@@ -66,18 +66,15 @@ if CONFIG['MOZ_WIDGET_TOOLKIT'] == 'gonk
 
 DISABLE_STL_WRAPPING = True
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     OS_LIBS += [
         'version',
     ]
 
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wshadow']
-
 JS_PREFERENCE_PP_FILES += [
     'b2g.js',
 ]
 
 FINAL_TARGET_PP_FILES += [
   'ua-update.json.in',
 ]
--- a/b2g/app/nsBrowserApp.cpp
+++ b/b2g/app/nsBrowserApp.cpp
@@ -20,17 +20,16 @@
 #include <string.h>
 
 #include "nsCOMPtr.h"
 #include "nsIFile.h"
 #include "nsStringGlue.h"
 
 #ifdef XP_WIN
 // we want a wmain entry point
-#define XRE_DONT_SUPPORT_XPSP2 // See https://bugzil.la/1023941#c32
 #include "nsWindowsWMain.cpp"
 #if defined(_MSC_VER) && (_MSC_VER < 1900)
 #define snprintf _snprintf
 #endif
 #define strcasecmp _stricmp
 #endif
 
 #ifdef MOZ_WIDGET_GONK
--- a/b2g/config/mozconfigs/linux32_gecko/debug
+++ b/b2g/config/mozconfigs/linux32_gecko/debug
@@ -1,16 +1,15 @@
 MOZ_AUTOMATION_L10N_CHECK=0
 MOZ_AUTOMATION_UPLOAD_SYMBOLS=0
 MOZ_AUTOMATION_UPDATE_PACKAGING=0
 . "$topsrcdir/b2g/config/mozconfigs/common"
 . "$topsrcdir/build/unix/mozconfig.linux32"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 ac_add_options --enable-debug
 
 # This will overwrite the default of stripping everything and keep the symbol table.
 # This is useful for profiling and debugging and only increases the package size
 # by 2 MBs.
 STRIP_FLAGS="--strip-debug"
 
--- a/b2g/config/mozconfigs/linux32_gecko/nightly
+++ b/b2g/config/mozconfigs/linux32_gecko/nightly
@@ -1,17 +1,16 @@
 MOZ_AUTOMATION_L10N_CHECK=0
 MOZ_AUTOMATION_UPLOAD_SYMBOLS=0
 MOZ_AUTOMATION_UPDATE_PACKAGING=0
 MOZ_AUTOMATION_SDK=0
 . "$topsrcdir/b2g/config/mozconfigs/common"
 . "$topsrcdir/build/unix/mozconfig.linux32"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # This will overwrite the default of stripping everything and keep the symbol table.
 # This is useful for profiling and debugging and only increases the package size
 # by 2 MBs.
 STRIP_FLAGS="--strip-debug"
 
 # Needed to enable breakpad in application.ini
--- a/b2g/config/mozconfigs/linux64_gecko/nightly
+++ b/b2g/config/mozconfigs/linux64_gecko/nightly
@@ -1,17 +1,16 @@
 MOZ_AUTOMATION_L10N_CHECK=0
 MOZ_AUTOMATION_UPLOAD_SYMBOLS=0
 MOZ_AUTOMATION_UPDATE_PACKAGING=0
 MOZ_AUTOMATION_SDK=0
 . "$topsrcdir/b2g/config/mozconfigs/common"
 . "$topsrcdir/build/unix/mozconfig.linux"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # This will overwrite the default of stripping everything and keep the symbol table.
 # This is useful for profiling and debugging and only increases the package size
 # by 2 MBs.
 STRIP_FLAGS="--strip-debug"
 
 # Needed to enable breakpad in application.ini
--- a/b2g/config/mozconfigs/macosx64_gecko/debug
+++ b/b2g/config/mozconfigs/macosx64_gecko/debug
@@ -3,17 +3,16 @@ MOZ_AUTOMATION_UPDATE_PACKAGING=0
 . "$topsrcdir/b2g/config/mozconfigs/common"
 
 # Use sccache
 no_sccache=
 
 . $topsrcdir/build/macosx/mozconfig.common
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 #ac_add_options --with-macbundlename-prefix=Firefox
--- a/b2g/config/mozconfigs/macosx64_gecko/nightly
+++ b/b2g/config/mozconfigs/macosx64_gecko/nightly
@@ -4,17 +4,16 @@ MOZ_AUTOMATION_SDK=0
 . "$topsrcdir/b2g/config/mozconfigs/common"
 
 # Use sccache
 no_sccache=
 
 . $topsrcdir/build/macosx/mozconfig.common
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
 #ac_add_options --with-macbundlename-prefix=Firefox
--- a/b2g/config/mozconfigs/win32_gecko/debug
+++ b/b2g/config/mozconfigs/win32_gecko/debug
@@ -1,15 +1,14 @@
 MOZ_AUTOMATION_L10N_CHECK=0
 MOZ_AUTOMATION_UPLOAD_SYMBOLS=0
 MOZ_AUTOMATION_UPDATE_PACKAGING=0
 . "$topsrcdir/b2g/config/mozconfigs/common"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
 ac_add_options --enable-signmar
 ac_add_options --enable-debug
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
--- a/b2g/config/mozconfigs/win32_gecko/nightly
+++ b/b2g/config/mozconfigs/win32_gecko/nightly
@@ -1,16 +1,15 @@
 MOZ_AUTOMATION_L10N_CHECK=0
 MOZ_AUTOMATION_UPLOAD_SYMBOLS=0
 MOZ_AUTOMATION_UPDATE_PACKAGING=0
 MOZ_AUTOMATION_SDK=0
 . "$topsrcdir/b2g/config/mozconfigs/common"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
 ac_add_options --enable-signmar
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
 export MOZ_TELEMETRY_REPORTING=1
 
--- a/b2g/dev/moz.configure
+++ b/b2g/dev/moz.configure
@@ -1,7 +1,9 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
+imply_option('MOZ_SERVICES_SYNC', True)
+
 include('../common.configure')
--- a/b2g/graphene/config/horizon-mozconfigs/linux32/nightly
+++ b/b2g/graphene/config/horizon-mozconfigs/linux32/nightly
@@ -1,13 +1,12 @@
 . "$topsrcdir/b2g/graphene/config/horizon-mozconfigs/common"
 . "$topsrcdir/build/unix/mozconfig.linux32"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 #ac_add_options --enable-js-diagnostics
 
 # This will overwrite the default of stripping everything and keep the symbol table.
 # This is useful for profiling and debugging and only increases the package size
 # by 2 MBs.
--- a/b2g/graphene/config/horizon-mozconfigs/linux64/nightly
+++ b/b2g/graphene/config/horizon-mozconfigs/linux64/nightly
@@ -1,13 +1,12 @@
 . "$topsrcdir/b2g/graphene/config/horizon-mozconfigs/common"
 . "$topsrcdir/build/unix/mozconfig.linux"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 #ac_add_options --enable-js-diagnostics
 
 # This will overwrite the default of stripping everything and keep the symbol table.
 # This is useful for profiling and debugging and only increases the package size
 # by 2 MBs.
--- a/b2g/graphene/config/horizon-mozconfigs/macosx64/nightly
+++ b/b2g/graphene/config/horizon-mozconfigs/macosx64/nightly
@@ -1,17 +1,16 @@
 . "$topsrcdir/b2g/graphene/config/horizon-mozconfigs/common"
 
 # Use sccache
 no_sccache=
 
 . $topsrcdir/build/macosx/mozconfig.common
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
--- a/b2g/graphene/config/horizon-mozconfigs/win32/nightly
+++ b/b2g/graphene/config/horizon-mozconfigs/win32/nightly
@@ -1,12 +1,11 @@
 . "$topsrcdir/b2g/graphene/config/horizon-mozconfigs/common"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
--- a/b2g/graphene/config/horizon-mozconfigs/win64/nightly
+++ b/b2g/graphene/config/horizon-mozconfigs/win64/nightly
@@ -6,17 +6,16 @@ fi
 . "$topsrcdir/b2g/graphene/config/horizon-mozconfigs/common"
 
 ac_add_options --target=x86_64-pc-mingw32
 ac_add_options --host=x86_64-pc-mingw32
 
 . $topsrcdir/build/win64/mozconfig.vs-latest
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
--- a/b2g/graphene/config/mozconfigs/linux32/nightly
+++ b/b2g/graphene/config/mozconfigs/linux32/nightly
@@ -1,13 +1,12 @@
 . "$topsrcdir/b2g/graphene/config/mozconfigs/common"
 . "$topsrcdir/build/unix/mozconfig.linux32"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 #ac_add_options --enable-js-diagnostics
 
 # This will overwrite the default of stripping everything and keep the symbol table.
 # This is useful for profiling and debugging and only increases the package size
 # by 2 MBs.
--- a/b2g/graphene/config/mozconfigs/linux64/nightly
+++ b/b2g/graphene/config/mozconfigs/linux64/nightly
@@ -1,13 +1,12 @@
 . "$topsrcdir/b2g/graphene/config/mozconfigs/common"
 . "$topsrcdir/build/unix/mozconfig.linux"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 #ac_add_options --enable-js-diagnostics
 
 # This will overwrite the default of stripping everything and keep the symbol table.
 # This is useful for profiling and debugging and only increases the package size
 # by 2 MBs.
--- a/b2g/graphene/config/mozconfigs/macosx64/nightly
+++ b/b2g/graphene/config/mozconfigs/macosx64/nightly
@@ -1,17 +1,16 @@
 . "$topsrcdir/b2g/graphene/config/mozconfigs/common"
 
 # Use sccache
 no_sccache=
 
 . $topsrcdir/build/macosx/mozconfig.common
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
 
--- a/b2g/graphene/config/mozconfigs/win32/nightly
+++ b/b2g/graphene/config/mozconfigs/win32/nightly
@@ -1,12 +1,11 @@
 . "$topsrcdir/b2g/graphene/config/mozconfigs/common"
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
--- a/b2g/graphene/config/mozconfigs/win64/nightly
+++ b/b2g/graphene/config/mozconfigs/win64/nightly
@@ -6,17 +6,16 @@ fi
 . "$topsrcdir/b2g/graphene/config/mozconfigs/common"
 
 ac_add_options --target=x86_64-pc-mingw32
 ac_add_options --host=x86_64-pc-mingw32
 
 . $topsrcdir/build/win64/mozconfig.vs-latest
 
 ac_add_options --enable-update-channel=${MOZ_UPDATE_CHANNEL}
-ac_add_options --enable-update-packaging
 ac_add_options --enable-jemalloc
 ac_add_options --enable-signmar
 
 # Nightlies only since this has a cost in performance
 ac_add_options --enable-js-diagnostics
 
 # Needed to enable breakpad in application.ini
 export MOZILLA_OFFICIAL=1
--- a/b2g/installer/package-manifest.in
+++ b/b2g/installer/package-manifest.in
@@ -409,17 +409,17 @@
 @RESPATH@/components/nsSidebar.js
 @RESPATH@/components/nsAsyncShutdown.manifest
 @RESPATH@/components/nsAsyncShutdown.js
 @RESPATH@/components/htmlMenuBuilder.js
 @RESPATH@/components/htmlMenuBuilder.manifest
 @RESPATH@/components/PresentationDeviceInfoManager.manifest
 @RESPATH@/components/PresentationDeviceInfoManager.js
 @RESPATH@/components/BuiltinProviders.manifest
-@RESPATH@/components/TCPPresentationServer.js
+@RESPATH@/components/PresentationControlService.js
 @RESPATH@/components/PresentationDataChannelSessionTransport.js
 @RESPATH@/components/PresentationDataChannelSessionTransport.manifest
 
 #ifdef MOZ_SECUREELEMENT
 @RESPATH@/components/ACEService.js
 @RESPATH@/components/ACEService.manifest
 @RESPATH@/components/GPAccessRulesManager.js
 @RESPATH@/components/GPAccessRulesManager.manifest
--- a/b2g/locales/en-US/chrome/overrides/appstrings.properties
+++ b/b2g/locales/en-US/chrome/overrides/appstrings.properties
@@ -29,12 +29,12 @@ externalProtocolPrompt=An external appli
 externalProtocolUnknown=<Unknown>
 externalProtocolChkMsg=Remember my choice for all links of this type.
 externalProtocolLaunchBtn=Launch application
 malwareBlocked=The site at %S has been reported as an attack site and has been blocked based on your security preferences.
 unwantedBlocked=The site at %S has been reported as serving unwanted software and has been blocked based on your security preferences.
 deceptiveBlocked=This web page at %S has been reported as a deceptive site and has been blocked based on your security preferences.
 forbiddenBlocked=The site at %S has been blocked by your browser configuration.
 cspBlocked=This page has a content security policy that prevents it from being loaded in this way.
-corruptedContentError=The page you are trying to view cannot be shown because an error in the data transmission was detected.
+corruptedContentError=The site at %S has experienced a network protocol violation that cannot be repaired.
 remoteXUL=This page uses an unsupported technology that is no longer available by default in Firefox.
 sslv3Used=Firefox cannot guarantee the safety of your data on %S because it uses SSLv3, a broken security protocol.
 weakCryptoUsed=The owner of %S has configured their website improperly. To protect your information from being stolen, Firefox has not connected to this website.
--- a/browser/app/blocklist.xml
+++ b/browser/app/blocklist.xml
@@ -1,10 +1,10 @@
 <?xml version="1.0"?>
-<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1462472009000">
+<blocklist xmlns="http://www.mozilla.org/2006/addons-blocklist" lastupdate="1463504139000">
   <emItems>
       <emItem  blockID="i58" id="webmaster@buzzzzvideos.info">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i71" id="youtube@2youtube.com">
@@ -1904,16 +1904,22 @@
               </prefs>
     </emItem>
       <emItem  blockID="i60" id="youtb3@youtb3.com">
                         <versionRange  minVersion="0" maxVersion="*">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
+      <emItem  blockID="i1214" id="firefoxdav@icloud.com">
+                        <versionRange  minVersion="0" maxVersion="1.4.22" severity="1">
+                    </versionRange>
+                    <prefs>
+              </prefs>
+    </emItem>
       <emItem  blockID="i434" id="afurladvisor@anchorfree.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i90" id="videoplugin@player.com">
                         <versionRange  minVersion="0" maxVersion="*">
@@ -2519,16 +2525,22 @@
               </prefs>
     </emItem>
       <emItem  blockID="i970" id="hha8771ui3-Fo9j9h7aH98jsdfa8sda@jetpack">
                         <versionRange  minVersion="0" maxVersion="*" severity="3">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
+      <emItem  blockID="i1213" id="unblocker20__web@unblocker.yt">
+                        <versionRange  minVersion="0" maxVersion="*" severity="3">
+                    </versionRange>
+                    <prefs>
+              </prefs>
+    </emItem>
       <emItem  blockID="i342" id="lbmsrvfvxcblvpane@lpaezhjez.org">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
                     </versionRange>
                     <prefs>
               </prefs>
     </emItem>
       <emItem  blockID="i336" id="CortonExt@ext.com">
                         <versionRange  minVersion="0" maxVersion="*" severity="1">
@@ -3607,17 +3619,16 @@
     <gfxBlacklistEntry  blockID="g1124">      <os>All</os>      <vendor>0x8086</vendor>              <devices>
                       <device>0x2a42</device>
                       <device>0x2e22</device>
                       <device>0x2e12</device>
                       <device>0x2e32</device>
                       <device>0x0046</device>
                   </devices>
             <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus>      <driverVersion>8.15.10.2086</driverVersion>      <driverVersionComparator>EQUAL</driverVersionComparator>    </gfxBlacklistEntry>
-    <gfxBlacklistEntry  blockID="g1208">      <os>All</os>      <vendor>0x8086</vendor>            <feature>HARDWARE_VIDEO_DECODING</feature>      <featureStatus>BLOCKED_DRIVER_VERSION</featureStatus>      <driverVersion>10.18.10.3947</driverVersion>      <driverVersionComparator>EQUAL</driverVersionComparator>    </gfxBlacklistEntry>
     </gfxItems>
 
   <certItems>
         <certItem issuerName="MIGQMQswCQYDVQQGEwJHQjEbMBkGA1UECBMSR3JlYXRlciBNYW5jaGVzdGVyMRAwDgYDVQQHEwdTYWxmb3JkMRowGAYDVQQKExFDT01PRE8gQ0EgTGltaXRlZDE2MDQGA1UEAxMtQ09NT0RPIFJTQSBEb21haW4gVmFsaWRhdGlvbiBTZWN1cmUgU2VydmVyIENB">
       <serialNumber>D9UltDPl4XVfSSqQOvdiwQ==</serialNumber>
     </certItem>
         <certItem issuerName="MDIxCzAJBgNVBAYTAkNOMQ4wDAYDVQQKEwVDTk5JQzETMBEGA1UEAxMKQ05OSUMgUk9PVA==">
       <serialNumber>STMAjg==</serialNumber>
--- a/browser/app/macbuild/Contents/Info.plist.in
+++ b/browser/app/macbuild/Contents/Info.plist.in
@@ -201,17 +201,17 @@
 	</array>
 	<key>CFBundleVersion</key>
 	<string>%MAC_BUNDLE_VERSION%</string>
 	<key>NSAppleScriptEnabled</key>
 	<true/>
 	<key>LSApplicationCategoryType</key>
 	<string>public.app-category.productivity</string>
 	<key>LSMinimumSystemVersion</key>
-	<string>10.6</string>
+	<string>10.9.0</string>
   <key>NSSupportsAutomaticGraphicsSwitching</key>
   <true/>
   <key>NSPrincipalClass</key>
   <string>GeckoNSApplication</string>
 	<key>SMPrivilegedExecutables</key>
 	<dict>
 		<key>org.mozilla.updater</key>
 		<string>identifier "org.mozilla.updater" and ((anchor apple generic and certificate leaf[field.1.2.840.113635.100.6.1.9]) or (anchor apple generic and certificate 1[field.1.2.840.113635.100.6.2.6] and certificate leaf[field.1.2.840.113635.100.6.1.13] and certificate leaf[subject.OU] = "43AQ936H96"))</string>
--- a/browser/app/moz.build
+++ b/browser/app/moz.build
@@ -1,20 +1,17 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 DIRS += ['profile/extensions']
 
-if CONFIG['OS_ARCH'] == 'WINNT' and CONFIG['MOZ_ASAN']:
-    GeckoProgram(CONFIG['MOZ_APP_NAME'])
-else:
-    GeckoProgram(CONFIG['MOZ_APP_NAME'], msvcrt='static')
+GeckoProgram(CONFIG['MOZ_APP_NAME'])
 
 JS_PREFERENCE_PP_FILES += [
     'profile/firefox.js',
 ]
 
 SOURCES += [
     'nsBrowserApp.cpp',
 ]
@@ -27,36 +24,43 @@ DEFINES['APP_VERSION'] = CONFIG['MOZ_APP
 
 LOCAL_INCLUDES += [
     '!/build',
     '/toolkit/xre',
     '/xpcom/base',
     '/xpcom/build',
 ]
 
-DELAYLOAD_DLLS += [
-    'mozglue.dll',
-]
-
 USE_LIBS += [
     'mozglue',
 ]
 
 if CONFIG['_MSC_VER']:
     # Always enter a Windows program through wmain, whether or not we're
     # a console application.
     WIN32_EXE_LDFLAGS += ['-ENTRY:wmainCRTStartup']
 
 if CONFIG['OS_ARCH'] == 'WINNT':
     RCINCLUDE = 'splash.rc'
     DEFINES['MOZ_PHOENIX'] = True
 
 for cdm in CONFIG['MOZ_EME_MODULES']:
     DEFINES['MOZ_%s_EME' % cdm.upper()] = True
 
+if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
+    # For sandbox includes and the include dependencies those have
+    LOCAL_INCLUDES += [
+        '/security/sandbox/chromium',
+        '/security/sandbox/chromium-shim',
+    ]
+
+    USE_LIBS += [
+        'sandbox_s',
+    ]
+
 # Control the default heap size.
 # This is the heap returned by GetProcessHeap().
 # As we use the CRT heap, the default size is too large and wastes VM.
 #
 # The default heap size is 1MB on Win32.
 # The heap will grow if need be.
 #
 # Set it to 256k.  See bug 127069.
@@ -66,14 +70,11 @@ if CONFIG['OS_ARCH'] == 'WINNT' and not 
 DISABLE_STL_WRAPPING = True
 
 if CONFIG['MOZ_LINKER']:
     OS_LIBS += CONFIG['MOZ_ZLIB_LIBS']
 
 if CONFIG['HAVE_CLOCK_MONOTONIC']:
     OS_LIBS += CONFIG['REALTIME_LIBS']
 
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wshadow']
-
 for icon in ('firefox', 'document', 'newwindow', 'newtab', 'pbmode'):
     DEFINES[icon.upper() + '_ICO'] = '"%s/dist/branding/%s.ico"' % (
         TOPOBJDIR, icon)
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -37,16 +37,19 @@
 #define XRE_DONT_SUPPORT_XPSP2
 #endif
 #define XRE_WANT_ENVIRON
 #include "nsWindowsWMain.cpp"
 #if defined(_MSC_VER) && (_MSC_VER < 1900)
 #define snprintf _snprintf
 #endif
 #define strcasecmp _stricmp
+#ifdef MOZ_SANDBOX
+#include "mozilla/sandboxing/SandboxInitialization.h"
+#endif
 #endif
 #include "BinaryPath.h"
 
 #include "nsXPCOMPrivate.h" // for MAXPATHLEN and XPCOM_DLL
 
 #include "mozilla/Telemetry.h"
 #include "mozilla/WindowsDllBlocklist.h"
 
@@ -174,17 +177,24 @@ static int do_main(int argc, char* argv[
     }
     argv[2] = argv[0];
     argv += 2;
     argc -= 2;
   } else if (argc > 1 && IsArg(argv[1], "xpcshell")) {
     for (int i = 1; i < argc; i++) {
       argv[i] = argv[i + 1];
     }
-    return XRE_XPCShellMain(--argc, argv, envp);
+
+    XREShellData shellData;
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+    shellData.sandboxBrokerServices =
+      sandboxing::GetInitializedBrokerServices();
+#endif
+
+    return XRE_XPCShellMain(--argc, argv, envp, &shellData);
   }
 
   if (appini) {
     nsXREAppData *appData;
     rv = XRE_CreateAppData(appini, &appData);
     if (NS_FAILED(rv)) {
       Output("Couldn't read application.ini");
       return 255;
@@ -212,16 +222,28 @@ static int do_main(int argc, char* argv[
   nsCOMPtr<nsIFile> appSubdir;
   greDir->Clone(getter_AddRefs(appSubdir));
   appSubdir->Append(NS_LITERAL_STRING(kDesktopFolder));
 
   SetStrongPtr(appData.directory, static_cast<nsIFile*>(appSubdir.get()));
   // xreDirectory already has a refcount from NS_NewLocalFile
   appData.xreDirectory = xreDirectory;
 
+#if defined(XP_WIN) && defined(MOZ_SANDBOX)
+  sandbox::BrokerServices* brokerServices =
+    sandboxing::GetInitializedBrokerServices();
+#if defined(MOZ_CONTENT_SANDBOX)
+  if (!brokerServices) {
+    Output("Couldn't initialize the broker services.\n");
+    return 255;
+  }
+#endif
+  appData.sandboxBrokerServices = brokerServices;
+#endif
+
   return XRE_main(argc, argv, &appData, mainFlags);
 }
 
 static bool
 FileExists(const char *path)
 {
 #ifdef XP_WIN
   wchar_t wideDir[MAX_PATH];
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1307,17 +1307,17 @@ pref("ui.key.menuAccessKeyFocuses", true
 #endif
 
 // Encrypted media extensions.
 pref("media.eme.enabled", true);
 pref("media.eme.apiVisible", true);
 
 // Decode using Gecko Media Plugins in <video>, if a system decoder is not
 // availble and the preferred GMP is available.
-pref("media.gmp.decoder.enabled", true);
+pref("media.gmp.decoder.enabled", false);
 
 // If decoding-via-GMP is turned on for <video>, use Adobe's GMP for decoding,
 // if it's available. Note: We won't fallback to another GMP if Adobe's is not
 // installed.
 pref("media.gmp.decoder.aac", 2);
 pref("media.gmp.decoder.h264", 2);
 
 // Whether we should run a test-pattern through EME GMPs before assuming they'll
@@ -1381,16 +1381,17 @@ pref("browser.tabs.remote.autostart.2", 
 pref("browser.tabs.crashReporting.sendReport", true);
 pref("browser.tabs.crashReporting.includeURL", false);
 pref("browser.tabs.crashReporting.emailMe", false);
 pref("browser.tabs.crashReporting.email", "");
 
 #ifndef MOZ_MULET
 pref("layers.async-pan-zoom.enabled", true);
 #endif
+pref("apz.velocity_bias", "0.0");
 
 // Enable e10s add-on interposition by default.
 pref("extensions.interposition.enabled", true);
 pref("extensions.interposition.prefetching", true);
 
 // Enable blocking of e10s for add-on users on beta/release.
 #ifdef RELEASE_BUILD
 pref("extensions.e10sBlocksEnabling", true);
--- a/browser/base/content/browser-context.inc
+++ b/browser/base/content/browser-context.inc
@@ -59,30 +59,18 @@
                 accesskey="&openLinkCmdInTab.accesskey;"
                 usercontextid="0"
                 oncommand="gContextMenu.openLinkInTab(event);"/>
 
       <menu id="context-openlinkinusercontext-menu"
             label="&openLinkCmdInContainerTab.label;"
             accesskey="&openLinkCmdInContainerTab.accesskey;"
             hidden="true">
-        <menupopup oncommand="gContextMenu.openLinkInTab(event);">
-          <menuitem label="&userContextPersonal.label;"
-                    usercontextid="1"
-                    accesskey="&userContextPersonal.accesskey;"/>
-          <menuitem label="&userContextWork.label;"
-                    usercontextid="2"
-                    accesskey="&userContextWork.accesskey;"/>
-          <menuitem label="&userContextBanking.label;"
-                    usercontextid="3"
-                    accesskey="&userContextBanking.accesskey;"/>
-          <menuitem label="&userContextShopping.label;"
-                    usercontextid="4"
-                    accesskey="&userContextShopping.accesskey;"/>
-        </menupopup>
+        <menupopup oncommand="gContextMenu.openLinkInTab(event);"
+                   onpopupshowing="return createUserContextMenu(event, false);" />
       </menu>
 
       <menuitem id="context-openlink"
                 label="&openLinkCmd.label;"
                 accesskey="&openLinkCmd.accesskey;"
                 oncommand="gContextMenu.openLink();"/>
       <menuitem id="context-openlinkprivate"
                 label="&openLinkInPrivateWindowCmd.label;"
@@ -173,24 +161,16 @@
       <menuitem id="context-media-showcontrols"
                 label="&mediaShowControls.label;"
                 accesskey="&mediaShowControls.accesskey;"
                 oncommand="gContextMenu.mediaCommand('showcontrols');"/>
       <menuitem id="context-media-hidecontrols"
                 label="&mediaHideControls.label;"
                 accesskey="&mediaHideControls.accesskey;"
                 oncommand="gContextMenu.mediaCommand('hidecontrols');"/>
-      <menuitem id="context-video-showstats"
-                accesskey="&videoShowStats.accesskey;"
-                label="&videoShowStats.label;"
-                oncommand="gContextMenu.mediaCommand('showstats');"/>
-      <menuitem id="context-video-hidestats"
-                accesskey="&videoHideStats.accesskey;"
-                label="&videoHideStats.label;"
-                oncommand="gContextMenu.mediaCommand('hidestats');"/>
       <menuitem id="context-video-fullscreen"
                 accesskey="&videoFullScreen.accesskey;"
                 label="&videoFullScreen.label;"
                 oncommand="gContextMenu.mediaCommand('fullscreen');"/>
       <menuitem id="context-leave-dom-fullscreen"
                 accesskey="&leaveDOMFullScreen.accesskey;"
                 label="&leaveDOMFullScreen.label;"
                 oncommand="gContextMenu.leaveDOMFullScreen();"/>
--- a/browser/base/content/browser-fullScreen.js
+++ b/browser/base/content/browser-fullScreen.js
@@ -126,20 +126,22 @@ var FullScreen = {
         // to get its corresponding browser here.
         let browser;
         if (event.target == gBrowser) {
           browser = event.originalTarget;
         } else {
           let topWin = event.target.ownerDocument.defaultView.top;
           browser = gBrowser.getBrowserForContentWindow(topWin);
         }
+        TelemetryStopwatch.start("FULLSCREEN_CHANGE_MS");
         this.enterDomFullscreen(browser);
         break;
       }
       case "MozDOMFullscreen:Exited":
+        TelemetryStopwatch.start("FULLSCREEN_CHANGE_MS");
         this.cleanupDomFullscreen();
         break;
     }
   },
 
   receiveMessage: function(aMessage) {
     let browser = aMessage.target;
     switch (aMessage.name) {
@@ -152,16 +154,17 @@ var FullScreen = {
         break;
       }
       case "DOMFullscreen:Exit": {
         this._windowUtils.remoteFrameFullscreenReverted();
         break;
       }
       case "DOMFullscreen:Painted": {
         Services.obs.notifyObservers(window, "fullscreen-painted", "");
+        TelemetryStopwatch.finish("FULLSCREEN_CHANGE_MS");
         break;
       }
     }
   },
 
   enterDomFullscreen : function(aBrowser) {
     if (!document.fullscreenElement) {
       return;
--- a/browser/base/content/browser-menubar.inc
+++ b/browser/base/content/browser-menubar.inc
@@ -17,42 +17,17 @@
                           label="&tabCmd.label;"
                           command="cmd_newNavigatorTab"
                           key="key_newNavigatorTab"
                           accesskey="&tabCmd.accesskey;"/>
                 <menu id="menu_newUserContext"
                       label="&newUserContext.label;"
                       accesskey="&newUserContext.accesskey;"
                       hidden="true">
-                  <menupopup>
-                    <menuitem id="menu_newUserContextTabPersonal"
-                              usercontextid="1"
-                              class="menuitem-iconic"
-                              label="&userContextPersonal.label;"
-                              command="Browser:NewUserContextTab"
-                              accesskey="&userContextPersonal.accesskey;"/>
-                    <menuitem id="menu_newUserContextTabWork"
-                              usercontextid="2"
-                              class="menuitem-iconic"
-                              label="&userContextWork.label;"
-                              command="Browser:NewUserContextTab"
-                              accesskey="&userContextWork.accesskey;"/>
-                    <menuitem id="menu_newUserContextTabBanking"
-                              usercontextid="3"
-                              class="menuitem-iconic"
-                              label="&userContextBanking.label;"
-                              command="Browser:NewUserContextTab"
-                              accesskey="&userContextBanking.accesskey;"/>
-                    <menuitem id="menu_newUserContextTabShopping"
-                              usercontextid="4"
-                              class="menuitem-iconic"
-                              label="&userContextShopping.label;"
-                              command="Browser:NewUserContextTab"
-                              accesskey="&userContextShopping.accesskey;"/>
-                  </menupopup>
+                  <menupopup onpopupshowing="return createUserContextMenu(event);" />
                 </menu>
                 <menuitem id="menu_newNavigator"
                           label="&newNavigatorCmd.label;"
                           accesskey="&newNavigatorCmd.accesskey;"
                           key="key_newNavigator"
                           command="cmd_newNavigator"/>
                 <menuitem id="menu_newPrivateWindow"
                           label="&newPrivateWindow.label;"
--- a/browser/base/content/browser-places.js
+++ b/browser/base/content/browser-places.js
@@ -1467,28 +1467,28 @@ var BookmarkingUI = {
       let title = node.title;
       let icon = node.icon;
 
       let item =
         document.createElementNS("http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul",
                                  "menuitem");
       item.setAttribute("label", title || uri);
       item.setAttribute("targetURI", uri);
-      item.setAttribute("context", "hideRecentlyBookmarked");
+      item.setAttribute("simulated-places-node", true);
       item.setAttribute("class", "menuitem-iconic menuitem-with-favicon bookmark-item " +
                                  aExtraCSSClass);
       item.addEventListener("command", onItemCommand);
       if (icon) {
         item.setAttribute("image", icon);
       }
+      item._placesNode = node;
       fragment.appendChild(item);
     }
     root.containerOpen = false;
     aHeaderItem.parentNode.insertBefore(fragment, aHeaderItem.nextSibling);
-    aHeaderItem.setAttribute("context", "hideRecentlyBookmarked");
   },
 
   showRecentlyBookmarked() {
     Services.prefs.setBoolPref(this.RECENTLY_BOOKMARKED_PREF, true);
   },
 
   hideRecentlyBookmarked() {
     Services.prefs.setBoolPref(this.RECENTLY_BOOKMARKED_PREF, false);
--- a/browser/base/content/browser-sets.inc
+++ b/browser/base/content/browser-sets.inc
@@ -352,17 +352,17 @@
     <key id="key_showAllTabs" command="Browser:ShowAllTabs" keycode="VK_TAB" modifiers="control,shift"/>
 
     <key id="key_switchTextDirection" key="&bidiSwitchTextDirectionItem.commandkey;" command="cmd_switchTextDirection" modifiers="accel,shift" />
 
     <key id="key_privatebrowsing" command="Tools:PrivateBrowsing" key="&privateBrowsingCmd.commandkey;" modifiers="accel,shift"/>
     <key id="key_sanitize" command="Tools:Sanitize" keycode="VK_DELETE" modifiers="accel,shift"/>
 #ifdef XP_MACOSX
     <key id="key_sanitize_mac" command="Tools:Sanitize" keycode="VK_BACK" modifiers="accel,shift"/>
-    <key id="key_quitApplication" key="&quitApplicationCmdUnix.key;" modifiers="accel"/>
+    <key id="key_quitApplication" key="&quitApplicationCmdUnix.key;" modifiers="accel" reserved="true"/>
 #elifdef XP_UNIX
     <key id="key_quitApplication" key="&quitApplicationCmdUnix.key;" command="cmd_quitApplication" modifiers="accel"/>
 #endif
 
 #ifdef FULL_BROWSER_WINDOW
     <key id="key_undoCloseTab" command="History:UndoCloseTab" key="&tabCmd.commandkey;" modifiers="accel,shift"/>
 #endif
     <key id="key_undoCloseWindow" command="History:UndoCloseWindow" key="&newNavigatorCmd.key;" modifiers="accel,shift"/>
--- a/browser/base/content/browser-sidebar.js
+++ b/browser/base/content/browser-sidebar.js
@@ -190,16 +190,20 @@ var SidebarUI = {
   show(commandID) {
     return new Promise((resolve, reject) => {
       let sidebarBroadcaster = document.getElementById(commandID);
       if (!sidebarBroadcaster || sidebarBroadcaster.localName != "broadcaster") {
         reject(new Error("Invalid sidebar broadcaster specified: " + commandID));
         return;
       }
 
+      if (this.isOpen && commandID != this.currentID) {
+        BrowserUITelemetry.countSidebarEvent(this.currentID, "hide");
+      }
+
       let broadcasters = document.getElementsByAttribute("group", "sidebar");
       for (let broadcaster of broadcasters) {
         // skip elements that observe sidebar broadcasters and random
         // other elements
         if (broadcaster.localName != "broadcaster") {
           continue;
         }
 
@@ -252,16 +256,17 @@ var SidebarUI = {
         this._fireFocusedEvent();
         resolve();
       }
 
       let selBrowser = gBrowser.selectedBrowser;
       selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange",
         {commandID: commandID, isOpen: true}
       );
+      BrowserUITelemetry.countSidebarEvent(commandID, "show");
     });
   },
 
   /**
    * Hide the sidebar.
    */
   hide() {
     if (!this.isOpen) {
@@ -289,16 +294,17 @@ var SidebarUI = {
     this._box.hidden = true;
     this._splitter.hidden = true;
 
     let selBrowser = gBrowser.selectedBrowser;
     selBrowser.focus();
     selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange",
       {commandID: commandID, isOpen: false}
     );
+    BrowserUITelemetry.countSidebarEvent(commandID, "hide");
   },
 };
 
 /**
  * This exists for backards compatibility - it will be called once a sidebar is
  * ready, following any request to show it.
  *
  * @deprecated
--- a/browser/base/content/browser-syncui.js
+++ b/browser/base/content/browser-syncui.js
@@ -398,20 +398,17 @@ var gSyncUI = {
       tooltiptext = this._stringBundle.GetStringFromName("signInToSync.description");
     } else if (loginFailed) {
       // "need to reconnect/re-enter your password"
       tooltiptext = gFxAccounts.strings.formatStringFromName("reconnectDescription", [email], 1);
     } else {
       // Sync appears configured - format the "last synced at" time.
       try {
         let lastSync = new Date(Services.prefs.getCharPref("services.sync.lastSync"));
-        // Show the day-of-week and time (HH:MM) of last sync
-        let lastSyncDateString = lastSync.toLocaleDateString(undefined,
-          {weekday: 'long', hour: 'numeric', minute: 'numeric'});
-        tooltiptext = this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDateString], 1);
+        tooltiptext = this.formatLastSyncDate(lastSync);
       }
       catch (e) {
         // pref doesn't exist (which will be the case until we've seen the
         // first successful sync) or is invalid (which should be impossible!)
         // Just leave tooltiptext as the empty string in these cases, which
         // will cause the tooltip to be removed below.
       }
     }
@@ -426,16 +423,34 @@ var gSyncUI = {
       if (tooltiptext) {
         broadcaster.setAttribute("tooltiptext", tooltiptext);
       } else {
         broadcaster.removeAttribute("tooltiptext");
       }
     }
   }),
 
+  formatLastSyncDate: function(date) {
+    let dateFormat;
+    let sixDaysAgo = (() => {
+      let date = new Date();
+      date.setDate(date.getDate() - 6);
+      date.setHours(0, 0, 0, 0);
+      return date;
+    })();
+    // It may be confusing for the user to see "Last Sync: Monday" when the last sync was a indeed a Monday but 3 weeks ago
+    if (date < sixDaysAgo) {
+      dateFormat = {month: 'long', day: 'numeric'};
+    } else {
+      dateFormat = {weekday: 'long', hour: 'numeric', minute: 'numeric'};
+    }
+    let lastSyncDateString = date.toLocaleDateString(undefined, dateFormat);
+    return this._stringBundle.formatStringFromName("lastSync2.label", [lastSyncDateString], 1);
+  },
+
   onSyncFinish: function SUI_onSyncFinish() {
     let title = this._stringBundle.GetStringFromName("error.sync.title");
   },
 
   onClientsSynced: function() {
     let broadcaster = document.getElementById("sync-syncnow-state");
     if (broadcaster) {
       if (Weave.Service.clientsEngine.stats.numClients > 1) {
--- a/browser/base/content/browser-tabsintitlebar.js
+++ b/browser/base/content/browser-tabsintitlebar.js
@@ -3,16 +3,19 @@
  * 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/. */
 
 // Note: the file browser-tabsintitlebar-stub.js is used instead of
 // this one on platforms which don't have CAN_DRAW_IN_TITLEBAR defined.
 
 var TabsInTitlebar = {
   init: function () {
+    if (this._initialized) {
+      return;
+    }
     this._readPref();
     Services.prefs.addObserver(this._prefName, this, false);
 
     // We need to update the appearance of the titlebar when the menu changes
     // from the active to the inactive state. We can't, however, rely on
     // DOMMenuBarInactive, because the menu fires this event and then removes
     // the inactive attribute after an event-loop spin.
     //
@@ -33,16 +36,22 @@ var TabsInTitlebar = {
       if (aArea == CustomizableUI.AREA_TABSTRIP || aArea == CustomizableUI.AREA_MENUBAR)
         this._update(true);
     };
     CustomizableUI.addListener(this);
 
     addEventListener("resolutionchange", this, false);
 
     this._initialized = true;
+    if (this._updateOnInit) {
+      // We don't need to call this with 'true', even if original calls
+      // (before init()) did, because this will be the first call and so
+      // we will update anyway.
+      this._update();
+    }
   },
 
   allowedBy: function (condition, allow) {
     if (allow) {
       if (condition in this._disallowed) {
         delete this._disallowed[condition];
         this._update(true);
       }
@@ -79,33 +88,41 @@ var TabsInTitlebar = {
           mutation.attributeName == "autohide") {
         TabsInTitlebar._update(true);
         return;
       }
     }
   },
 
   _initialized: false,
+  _updateOnInit: false,
   _disallowed: {},
   _prefName: "browser.tabs.drawInTitlebar",
   _lastSizeMode: null,
 
   _readPref: function () {
     this.allowedBy("pref",
                    Services.prefs.getBoolPref(this._prefName));
   },
 
   _update: function (aForce=false) {
     let $ = id => document.getElementById(id);
     let rect = ele => ele.getBoundingClientRect();
     let verticalMargins = cstyle => parseFloat(cstyle.marginBottom) + parseFloat(cstyle.marginTop);
 
-    if (!this._initialized || window.fullScreen)
+    if (window.fullScreen)
       return;
 
+    // In some edgecases it is possible for this to fire before we've initialized.
+    // Don't run now, but don't forget to run it when we do initialize.
+    if (!this._initialized) {
+      this._updateOnInit = true;
+      return;
+    }
+
     let allowed = true;
 
     if (!aForce) {
       // _update is called on resize events, because the window is not ready
       // after sizemode events. However, we only care about the event when the
       // sizemode is different from the last time we updated the appearance of
       // the tabs in the titlebar.
       let sizemode = document.documentElement.getAttribute("sizemode");
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -5,17 +5,16 @@
 
 var Ci = Components.interfaces;
 var Cu = Components.utils;
 var Cc = Components.classes;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/NotificationDB.jsm");
 Cu.import("resource:///modules/RecentWindow.jsm");
-Cu.import("resource:///modules/UserContextUI.jsm");
 
 
 XPCOMUtils.defineLazyModuleGetter(this, "Preferences",
                                   "resource://gre/modules/Preferences.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "Deprecated",
                                   "resource://gre/modules/Deprecated.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
                                   "resource:///modules/BrowserUITelemetry.jsm");
@@ -50,16 +49,18 @@ XPCOMUtils.defineLazyServiceGetter(this,
                                    "mozIAsyncFavicons");
 XPCOMUtils.defineLazyServiceGetter(this, "gDNSService",
                                    "@mozilla.org/network/dns-service;1",
                                    "nsIDNSService");
 XPCOMUtils.defineLazyServiceGetter(this, "WindowsUIUtils",
                                    "@mozilla.org/windows-ui-utils;1", "nsIWindowsUIUtils");
 XPCOMUtils.defineLazyModuleGetter(this, "LightweightThemeManager",
                                   "resource://gre/modules/LightweightThemeManager.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
+                                  "resource:///modules/ContextualIdentityService.jsm");
 XPCOMUtils.defineLazyServiceGetter(this, "gAboutNewTabService",
                                    "@mozilla.org/browser/aboutnewtab-service;1",
                                    "nsIAboutNewTabService");
 XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() {
   return Services.strings.createBundle('chrome://browser/locale/browser.properties');
 });
 XPCOMUtils.defineLazyModuleGetter(this, "AddonWatcher",
                                   "resource://gre/modules/AddonWatcher.jsm");
@@ -984,17 +985,16 @@ var gBrowserInit = {
       gURLBar.setAttribute("enablehistory", "false");
       goSetCommandEnabled("cmd_newNavigatorTab", false);
     }
 
     // Misc. inits.
     TabletModeUpdater.init();
     CombinedStopReload.init();
     gPrivateBrowsingUI.init();
-    TabsInTitlebar.init();
 
     if (window.matchMedia("(-moz-os-version: windows-win8)").matches &&
         window.matchMedia("(-moz-windows-default-theme)").matches) {
       let windowFrameColor = Cu.import("resource:///modules/Windows8WindowFrameColor.jsm", {})
                                .Windows8WindowFrameColor.get();
 
       // Formula from W3C's WCAG 2.0 spec's color ratio and relative luminance,
       // section 1.3.4, http://www.w3.org/TR/WCAG20/ .
@@ -1102,16 +1102,22 @@ var gBrowserInit = {
         // remote.
         try {
           if (tabToOpen.linkedBrowser.isRemoteBrowser) {
             if (!gMultiProcessBrowser) {
               throw new Error("Cannot drag a remote browser into a window " +
                               "without the remote tabs load context.");
             }
 
+            // We must set usercontextid before updateBrowserRemoteness()
+            // so that the newly created remote tab child has correct usercontextid
+            if (tabToOpen.hasAttribute("usercontextid")) {
+              let usercontextid = tabToOpen.getAttribute("usercontextid");
+              gBrowser.selectedBrowser.setAttribute("usercontextid", usercontextid);
+            }
             gBrowser.updateBrowserRemoteness(gBrowser.selectedBrowser, true);
           }
           gBrowser.swapBrowsersAndCloseOther(gBrowser.selectedTab, tabToOpen);
         } catch(e) {
           Cu.reportError(e);
         }
       }
       // window.arguments[2]: referrer (nsIURI | string)
@@ -1290,16 +1296,18 @@ var gBrowserInit = {
       gDataNotificationInfoBar.init();
 
     gBrowserThumbnails.init();
 
     gMenuButtonBadgeManager.init();
 
     gMenuButtonUpdateBadge.init();
 
+    UserContextStyleManager.init();
+
     window.addEventListener("mousemove", MousePosTracker, false);
     window.addEventListener("dragover", MousePosTracker, false);
 
     gNavToolbox.addEventListener("customizationstarting", CustomizationHandler);
     gNavToolbox.addEventListener("customizationchange", CustomizationHandler);
     gNavToolbox.addEventListener("customizationending", CustomizationHandler);
 
     // End startup crash tracking after a delay to catch crashes while restoring
@@ -3668,28 +3676,27 @@ const BrowserSearch = {
 
   loadAddEngines: function BrowserSearch_loadAddEngines() {
     var newWindowPref = gPrefService.getIntPref("browser.link.open_newwindow");
     var where = newWindowPref == 3 ? "tab" : "window";
     var searchEnginesURL = formatURL("browser.search.searchEnginesURL", true);
     openUILinkIn(searchEnginesURL, where);
   },
 
+  get _isExtendedTelemetryEnabled() {
+    return Services.prefs.getBoolPref("toolkit.telemetry.enabled");
+  },
+
   _getSearchEngineId: function (engine) {
-    if (!engine) {
+    if (engine && engine.identifier) {
+      return engine.identifier;
+    }
+
+    if (!engine || (engine.name === undefined) || !this._isExtendedTelemetryEnabled)
       return "other";
-    }
-
-    if (engine.identifier) {
-      return engine.identifier;
-    }
-
-    if (!("name" in engine) || engine.name === undefined) {
-      return "other";
-    }
 
     return "other-" + engine.name;
   },
 
   /**
    * Helper to record a search with Telemetry.
    *
    * Telemetry records only search counts and nothing pertaining to the search itself.
@@ -4043,36 +4050,50 @@ function openNewUserContextTab(event)
 }
 
 /**
  * Updates File Menu User Context UI visibility depending on
  * privacy.userContext.enabled pref state.
  */
 function updateUserContextUIVisibility()
 {
-  let userContextEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled");
-  document.getElementById("menu_newUserContext").hidden = !userContextEnabled;
+  let menu = document.getElementById("menu_newUserContext");
+  menu.hidden = !Services.prefs.getBoolPref("privacy.userContext.enabled");
+  if (PrivateBrowsingUtils.isWindowPrivate(window)) {
+    menu.setAttribute("disabled", "true");
+  }
 }
 
 /**
  * Updates the User Context UI indicators if the browser is in a non-default context
  */
 function updateUserContextUIIndicator(browser)
 {
   let hbox = document.getElementById("userContext-icons");
 
-  if (!browser.hasAttribute("usercontextid")) {
-    hbox.removeAttribute("usercontextid");
+  let userContextId = browser.getAttribute("usercontextid");
+  if (!userContextId) {
+    hbox.hidden = true;
+    return;
+  }
+
+  let identity = ContextualIdentityService.getIdentityFromId(userContextId);
+  if (!identity) {
+    hbox.hidden = true;
     return;
   }
 
   let label = document.getElementById("userContext-label");
-  let userContextId = browser.getAttribute("usercontextid");
-  hbox.setAttribute("usercontextid", userContextId);
-  label.value = UserContextUI.getUserContextLabel(userContextId);
+  label.value = ContextualIdentityService.getUserContextLabel(userContextId);
+  label.style.color = identity.color;
+
+  let indicator = document.getElementById("userContext-indicator");
+  indicator.style.listStyleImage = "url(" + identity.icon + ")";
+
+  hbox.hidden = false;
 }
 
 /**
  * Makes the Character Encoding menu enabled or disabled as appropriate.
  * To be called when the View menu or the app menu is opened.
  */
 function updateCharacterEncodingMenuState()
 {
@@ -5100,22 +5121,25 @@ var TabletModeUpdater = {
     }
   },
 
   observe(subject, topic, data) {
     this.update(data == "tablet-mode");
   },
 
   update(isInTabletMode) {
+    let wasInTabletMode = document.documentElement.hasAttribute("tabletmode");
     if (isInTabletMode) {
       document.documentElement.setAttribute("tabletmode", "true");
     } else {
       document.documentElement.removeAttribute("tabletmode");
     }
-    TabsInTitlebar.updateAppearance(true);
+    if (wasInTabletMode != isInTabletMode) {
+      TabsInTitlebar.updateAppearance(true);
+    }
   },
 };
 
 var gTabletModePageCounter = {
   enabled: false,
   inc() {
     this.enabled = AppConstants.isPlatformAndVersionAtLeast("win", "10.0");
     if (!this.enabled) {
@@ -7895,8 +7919,37 @@ TabModalPromptBox.prototype = {
   get browser() {
     let browser = this._weakBrowserRef.get();
     if (!browser) {
       throw "Stale promptbox! The associated browser is gone.";
     }
     return browser;
   },
 };
+
+let UserContextStyleManager = {
+  init() {
+    for (let styleId in document.styleSheets) {
+      let styleSheet = document.styleSheets[styleId];
+      if (styleSheet.href != "chrome://browser/content/usercontext/usercontext.css") {
+        continue;
+      }
+
+      if (ContextualIdentityService.needsCssRule()) {
+        for (let ruleId in styleSheet.cssRules) {
+          let cssRule = styleSheet.cssRules[ruleId];
+          if (cssRule.selectorText != ":root") {
+            continue;
+          }
+
+          ContextualIdentityService.storeCssRule(cssRule.cssText);
+          break;
+        }
+      }
+
+      ContextualIdentityService.cssRules().forEach(rule => {
+        styleSheet.insertRule(rule, styleSheet.cssRules.length);
+      });
+
+      break;
+    }
+  },
+};
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -3,16 +3,17 @@
 # -*- Mode: HTML -*-
 #
 # 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/.
 
 <?xml-stylesheet href="chrome://browser/content/browser.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/content/places/places.css" type="text/css"?>
+<?xml-stylesheet href="chrome://browser/content/usercontext/usercontext.css" type="text/css"?>
 <?xml-stylesheet href="chrome://devtools/skin/devtools-browser.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/controlcenter/panel.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/customizableui/panelUIOverlay.css" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/" type="text/css"?>
 <?xml-stylesheet href="chrome://browser/skin/browser-lightweightTheme.css" type="text/css"?>
 
 <?xul-overlay href="chrome://global/content/editMenuOverlay.xul"?>
 <?xul-overlay href="chrome://browser/content/baseMenuOverlay.xul"?>
@@ -401,23 +402,16 @@
                 accesskey="&showRecentlyBookmarked.accesskey;"
                 oncommand="BookmarkingUI.showRecentlyBookmarked();"
                 closemenu="single"
                 ignoreitem="true"
                 ordinal="2"
                 hidden="true"/>
     </menupopup>
 
-    <menupopup id="hideRecentlyBookmarked">
-      <menuitem label="&hideRecentlyBookmarked.label;"
-                accesskey="&hideRecentlyBookmarked.accesskey;"
-                oncommand="BookmarkingUI.hideRecentlyBookmarked();"
-                closemenu="single"/>
-    </menupopup>
-
     <panel id="ctrlTab-panel" class="KUI-panel" hidden="true" norestorefocus="true" level="top">
       <hbox>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
         <button class="ctrlTab-preview" flex="1"/>
@@ -652,17 +646,22 @@
                      removable="false">
         <menupopup id="alltabs-popup"
                    position="after_end">
           <menuitem id="alltabs_undoCloseTab"
                     class="menuitem-iconic"
                     key="key_undoCloseTab"
                     label="&undoCloseTab.label;"
                     observes="History:UndoCloseTab"/>
-          <menuseparator id="alltabs-popup-separator"/>
+          <menuseparator id="alltabs-popup-separator-1"/>
+          <menu id="alltabs_containersTab"
+                label="&newUserContext.label;">
+            <menupopup id="alltabs_containersMenuTab" />
+          </menu>
+          <menuseparator id="alltabs-popup-separator-2"/>
         </menupopup>
       </toolbarbutton>
 
 #if !defined(MOZ_WIDGET_GTK) && !defined(MOZ_WIDGET_QT)
       <hbox class="private-browsing-indicator" skipintoolbarset="true"/>
 #endif
 #ifdef CAN_DRAW_IN_TITLEBAR
       <hbox class="titlebar-placeholder" type="caption-buttons"
--- a/browser/base/content/content.js
+++ b/browser/base/content/content.js
@@ -750,23 +750,16 @@ addMessageListener("ContextMenu:MediaCom
       media.playbackRate = message.data.data;
       break;
     case "hidecontrols":
       media.removeAttribute("controls");
       break;
     case "showcontrols":
       media.setAttribute("controls", "true");
       break;
-    case "hidestats":
-    case "showstats":
-      let event = media.ownerDocument.createEvent("CustomEvent");
-      event.initCustomEvent("media-showStatistics", false, true,
-                            message.data.command == "showstats");
-      media.dispatchEvent(event);
-      break;
     case "fullscreen":
       if (content.document.fullscreenEnabled)
         media.requestFullscreen();
       break;
   }
 });
 
 addMessageListener("ContextMenu:Canvas:ToDataURL", (message) => {
--- a/browser/base/content/nsContextMenu.js
+++ b/browser/base/content/nsContextMenu.js
@@ -144,17 +144,17 @@ nsContextMenu.prototype = {
     }
 
     var shouldShow = this.onSaveableLink || isMailtoInternal || this.onPlainTextLink;
     var isWindowPrivate = PrivateBrowsingUtils.isWindowPrivate(window);
     var showContainers = Services.prefs.getBoolPref("privacy.userContext.enabled");
     this.showItem("context-openlink", shouldShow && !isWindowPrivate);
     this.showItem("context-openlinkprivate", shouldShow);
     this.showItem("context-openlinkintab", shouldShow);
-    this.showItem("context-openlinkinusercontext-menu", shouldShow && showContainers);
+    this.showItem("context-openlinkinusercontext-menu", shouldShow && !isWindowPrivate && showContainers);
     this.showItem("context-openlinkincurrent", this.onPlainTextLink);
     this.showItem("context-sep-open", shouldShow);
   },
 
   initNavigationItems: function CM_initNavigationItems() {
     var shouldShow = !(this.isContentSelected || this.onLink || this.onImage ||
                        this.onCanvas || this.onVideo || this.onAudio ||
                        this.onTextInput || this.onSocial);
@@ -469,19 +469,16 @@ nsContextMenu.prototype = {
     this.showItem("context-media-pause", onMedia && !this.target.paused && !this.target.ended);
     this.showItem("context-media-mute",   onMedia && !this.target.muted);
     this.showItem("context-media-unmute", onMedia && this.target.muted);
     this.showItem("context-media-playbackrate", onMedia);
     this.showItem("context-media-loop", onMedia);
     this.showItem("context-media-showcontrols", onMedia && !this.target.controls);
     this.showItem("context-media-hidecontrols", this.target.controls && (this.onVideo || (this.onAudio && !this.inSyntheticDoc)));
     this.showItem("context-video-fullscreen", this.onVideo && this.target.ownerDocument.fullscreenElement == null);
-    var statsShowing = this.onVideo && this.target.mozMediaStatisticsShowing;
-    this.showItem("context-video-showstats", this.onVideo && this.target.controls && !statsShowing);
-    this.showItem("context-video-hidestats", this.onVideo && this.target.controls && statsShowing);
     this.showItem("context-media-eme-learnmore", this.onDRMMedia);
     this.showItem("context-media-eme-separator", this.onDRMMedia);
 
     // Disable them when there isn't a valid media source loaded.
     if (onMedia) {
       this.setItemAttr("context-media-playbackrate-050x", "checked", this.target.playbackRate == 0.5);
       this.setItemAttr("context-media-playbackrate-100x", "checked", this.target.playbackRate == 1.0);
       this.setItemAttr("context-media-playbackrate-125x", "checked", this.target.playbackRate == 1.25);
@@ -501,18 +498,16 @@ nsContextMenu.prototype = {
       this.setItemAttr("context-media-playbackrate-150x", "disabled", hasError);
       this.setItemAttr("context-media-playbackrate-200x", "disabled", hasError);
       this.setItemAttr("context-media-showcontrols", "disabled", hasError);
       this.setItemAttr("context-media-hidecontrols", "disabled", hasError);
       if (this.onVideo) {
         let canSaveSnapshot = !this.onDRMMedia && this.target.readyState >= this.target.HAVE_CURRENT_DATA;
         this.setItemAttr("context-video-saveimage",  "disabled", !canSaveSnapshot);
         this.setItemAttr("context-video-fullscreen", "disabled", hasError);
-        this.setItemAttr("context-video-showstats", "disabled", hasError);
-        this.setItemAttr("context-video-hidestats", "disabled", hasError);
       }
     }
     this.showItem("context-media-sep-commands",  onMedia);
   },
 
   initClickToPlayItems: function() {
     this.showItem("context-ctp-play", this.onCTPPlugin);
     this.showItem("context-ctp-hide", this.onCTPPlugin);
--- a/browser/base/content/pageinfo/security.js
+++ b/browser/base/content/pageinfo/security.js
@@ -85,16 +85,19 @@ var security = {
           retval.version = "TLS 1.0";
           break;
         case nsISSLStatus.TLS_VERSION_1_1:
           retval.version = "TLS 1.1";
           break;
         case nsISSLStatus.TLS_VERSION_1_2:
           retval.version = "TLS 1.2"
           break;
+        case nsISSLStatus.TLS_VERSION_1_3:
+          retval.version = "TLS 1.3"
+          break;
       }
 
       return retval;
     } else {
       return {
         hostName : hostName,
         cAName : "",
         encryptionAlgorithm : "",
--- a/browser/base/content/popup-notifications.inc
+++ b/browser/base/content/popup-notifications.inc
@@ -71,22 +71,16 @@
         <textbox id="login-fill-username" readonly="true"/>
         <textbox id="login-fill-password" type="password" disabled="true"/>
         <hbox>
           <button id="login-fill-use" label="Use in form"/>
         </hbox>
       </vbox>
     </stack>
 
-#ifdef E10S_TESTING_ONLY
-    <popupnotification id="enable-e10s-notification" hidden="true">
-      <popupnotificationcontent orient="vertical"/>
-    </popupnotification>
-#endif
-
     <popupnotification id="addon-progress-notification" hidden="true">
       <popupnotificationcontent orient="vertical">
         <progressmeter id="addon-progress-notification-progressmeter"/>
         <label id="addon-progress-notification-progresstext" crop="end"/>
       </popupnotificationcontent>
       <button id="addon-progress-cancel"
               oncommand="this.parentNode.cancel();"/>
       <button id="addon-progress-accept" disabled="true"/>
--- a/browser/base/content/sync/setup.xul
+++ b/browser/base/content/sync/setup.xul
@@ -354,17 +354,17 @@
 
   <wizardpage id="syncOptionsPage"
               label="&setup.optionsPage.title;"
               onpageshow="gSyncSetup.onPageShow()">
     <groupbox id="syncOptions">
     <grid>
       <columns>
         <column/>
-        <column flex="1" style="-moz-margin-end: 2px"/>
+        <column flex="1" style="margin-inline-end: 2px"/>
       </columns>
       <rows>
         <row align="center">
           <label value="&syncDeviceName.label;"
                  accesskey="&syncDeviceName.accesskey;"
                  control="syncComputerName"/>
           <textbox id="syncComputerName" flex="1"
                    onchange="gSyncUtils.changeName(this)"/>
--- a/browser/base/content/tab-content.js
+++ b/browser/base/content/tab-content.js
@@ -241,16 +241,18 @@ var AboutPrivateBrowsingListener = {
   },
 };
 AboutPrivateBrowsingListener.init(this);
 
 var AboutReaderListener = {
 
   _articlePromise: null,
 
+  _isLeavingReaderMode: false,
+
   init: function() {
     addEventListener("AboutReaderContentLoaded", this, false, true);
     addEventListener("DOMContentLoaded", this, false);
     addEventListener("pageshow", this, false);
     addEventListener("pagehide", this, false);
     addMessageListener("Reader:ToggleReaderMode", this);
     addMessageListener("Reader:PushState", this);
   },
@@ -258,16 +260,17 @@ var AboutReaderListener = {
   receiveMessage: function(message) {
     switch (message.name) {
       case "Reader:ToggleReaderMode":
         let url = content.document.location.href;
         if (!this.isAboutReader) {
           this._articlePromise = ReaderMode.parseDocument(content.document).catch(Cu.reportError);
           ReaderMode.enterReaderMode(docShell, content);
         } else {
+          this._isLeavingReaderMode = true;
           ReaderMode.leaveReaderMode(docShell, content);
         }
         break;
 
       case "Reader:PushState":
         this.updateReaderButton(!!(message.data && message.data.isArticle));
         break;
     }
@@ -296,17 +299,23 @@ var AboutReaderListener = {
           sendAsyncMessage("Reader:UpdateReaderButton");
           new AboutReader(global, content, this._articlePromise);
           this._articlePromise = null;
         }
         break;
 
       case "pagehide":
         this.cancelPotentialPendingReadabilityCheck();
-        sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: false });
+        // this._isLeavingReaderMode is used here to keep the Reader Mode icon
+        // visible in the location bar when transitioning from reader-mode page
+        // back to the source page.
+        sendAsyncMessage("Reader:UpdateReaderButton", { isArticle: this._isLeavingReaderMode });
+        if (this._isLeavingReaderMode) {
+          this._isLeavingReaderMode = false;
+        }
         break;
 
       case "pageshow":
         // If a page is loaded from the bfcache, we won't get a "DOMContentLoaded"
         // event, so we need to rely on "pageshow" in this case.
         if (aEvent.persisted) {
           this.updateReaderButton();
         }
@@ -860,31 +869,31 @@ var RefreshBlocker = {
                                          Ci.nsISupportsWeakReference,
                                          Ci.nsISupports]),
 };
 
 RefreshBlocker.init();
 
 var UserContextIdNotifier = {
   init() {
-    addEventListener("DOMContentLoaded", this);
+    addEventListener("DOMWindowCreated", this);
   },
 
   uninit() {
-    removeEventListener("DOMContentLoaded", this);
+    removeEventListener("DOMWindowCreated", this);
   },
 
   handleEvent(aEvent) {
-    // When the first content is loaded, we want to inform the tabbrowser about
+    // When the window is created, we want to inform the tabbrowser about
     // the userContextId in use in order to update the UI correctly.
     // Just because we cannot change the userContextId from an active docShell,
     // we don't need to check DOMContentLoaded again.
     this.uninit();
     let userContextId = content.document.nodePrincipal.originAttributes.userContextId;
-    sendAsyncMessage("Browser:FirstContentLoaded", { userContextId });
+    sendAsyncMessage("Browser:WindowCreated", { userContextId });
   }
 };
 
 UserContextIdNotifier.init();
 
 ExtensionContent.init(this);
 addEventListener("unload", () => {
   ExtensionContent.uninit(this);
--- a/browser/base/content/tabbrowser.xml
+++ b/browser/base/content/tabbrowser.xml
@@ -58,27 +58,20 @@
       <field name="closingTabsEnum" readonly="true">({ ALL: 0, OTHER: 1, TO_END: 2 });</field>
 
       <field name="_visibleTabs">null</field>
 
       <field name="mURIFixup" readonly="true">
         Components.classes["@mozilla.org/docshell/urifixup;1"]
                   .getService(Components.interfaces.nsIURIFixup);
       </field>
-      <field name="mFaviconService" readonly="true">
-        Components.classes["@mozilla.org/browser/favicon-service;1"]
-                  .getService(Components.interfaces.nsIFaviconService);
-      </field>
       <field name="_unifiedComplete" readonly="true">
          Components.classes["@mozilla.org/autocomplete/search;1?name=unifiedcomplete"]
                    .getService(Components.interfaces.mozIPlacesAutoComplete);
       </field>
-      <field name="PlacesUtils" readonly="true">
-        (Components.utils.import("resource://gre/modules/PlacesUtils.jsm", {})).PlacesUtils;
-      </field>
       <field name="AppConstants" readonly="true">
         (Components.utils.import("resource://gre/modules/AppConstants.jsm", {})).AppConstants;
       </field>
       <field name="mTabBox" readonly="true">
         document.getAnonymousElementByAttribute(this, "anonid", "tabbox");
       </field>
       <field name="mPanelContainer" readonly="true">
         document.getAnonymousElementByAttribute(this, "anonid", "panelcontainer");
@@ -298,17 +291,17 @@
       <method name="unpinTab">
         <parameter name="aTab"/>
         <body><![CDATA[
           if (!aTab.pinned)
             return;
 
           this.moveTabTo(aTab, this._numPinnedTabs - 1);
           aTab.removeAttribute("pinned");
-          aTab.style.MozMarginStart = "";
+          aTab.style.marginInlineStart = "";
           this.tabContainer._unlockTabSizing();
           this.tabContainer._positionPinnedTabs();
           this.tabContainer.adjustTabstrip();
 
           this.getBrowserForTab(aTab).messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: false })
 
           if (aTab.selected)
             this._setCloseKeyState(true);
@@ -857,32 +850,27 @@
         <parameter name="aTab"/>
         <parameter name="aURI"/>
         <parameter name="aLoadingPrincipal"/>
         <body>
           <![CDATA[
             let browser = this.getBrowserForTab(aTab);
             browser.mIconURL = aURI instanceof Ci.nsIURI ? aURI.spec : aURI;
 
-            if (aURI && this.mFaviconService) {
+            if (aURI) {
               if (!(aURI instanceof Ci.nsIURI)) {
                 aURI = makeURI(aURI);
               }
               // We do not serialize the principal from within SessionStore.jsm,
               // hence if aLoadingPrincipal is null we default to the
               // systemPrincipal which will allow the favicon to load.
               let loadingPrincipal = aLoadingPrincipal
                 ? aLoadingPrincipal
                 : Services.scriptSecurityManager.getSystemPrincipal();
-              let loadType = PrivateBrowsingUtils.isWindowPrivate(window)
-                ? this.mFaviconService.FAVICON_LOAD_PRIVATE
-                : this.mFaviconService.FAVICON_LOAD_NON_PRIVATE;
-
-              this.mFaviconService.setAndFetchFaviconForPage(
-                browser.currentURI, aURI, false, loadType, null, loadingPrincipal);
+              PlacesUIUtils.loadFavicon(browser, loadingPrincipal, aURI);
             }
 
             let sizedIconUrl = browser.mIconURL || "";
             if (sizedIconUrl != aTab.getAttribute("image")) {
               if (sizedIconUrl)
                 aTab.setAttribute("image", sizedIconUrl);
               else
                 aTab.removeAttribute("image");
@@ -945,22 +933,19 @@
           ]]>
         </body>
       </method>
 
       <method name="isFailedIcon">
         <parameter name="aURI"/>
         <body>
           <![CDATA[
-            if (this.mFaviconService) {
-              if (!(aURI instanceof Ci.nsIURI))
-                aURI = makeURI(aURI);
-              return this.mFaviconService.isFailedFavicon(aURI);
-            }
-            return null;
+            if (!(aURI instanceof Ci.nsIURI))
+              aURI = makeURI(aURI);
+            return PlacesUtils.favicons.isFailedFavicon(aURI);
           ]]>
         </body>
       </method>
 
       <method name="getWindowTitleForBrowser">
         <parameter name="aBrowser"/>
         <body>
           <![CDATA[
@@ -3068,17 +3053,22 @@
         <parameter name="aTab"/>
         <parameter name="aIndex"/>
         <parameter name="aSelectTab"/>
         <body>
         <![CDATA[
           // Swap the dropped tab with a new one we create and then close
           // it in the other window (making it seem to have moved between
           // windows).
-          let newTab = this.addTab("about:blank", { eventDetail: { adoptedTab: aTab } });
+          let params = { eventDetail: { adoptedTab: aTab } };
+          if (aTab.hasAttribute("usercontextid")) {
+            // new tab must have the same usercontextid as the old one
+            params.userContextId = aTab.getAttribute("usercontextid");
+          }
+          let newTab = this.addTab("about:blank", params);
           let newBrowser = this.getBrowserForTab(newTab);
           let newURL = aTab.linkedBrowser.currentURI.spec;
 
           // If we're an e10s browser window, an exception will be thrown
           // if we attempt to drag a non-remote browser in, so we need to
           // ensure that the remoteness of the newly created browser is
           // appropriate for the URL of the tab being dragged in.
           this.updateBrowserRemotenessByURL(newBrowser, newURL);
@@ -4327,22 +4317,23 @@
               let tab = this.getTabForBrowser(browser);
               if (!tab)
                 return undefined;
 
               this._outerWindowIDBrowserMap.set(browser.outerWindowID, browser);
               browser.messageManager.sendAsyncMessage("Browser:AppTab", { isAppTab: tab.pinned })
               break;
             }
-            case "Browser:FirstContentLoaded": {
+            case "Browser:WindowCreated": {
               let tab = this.getTabForBrowser(browser);
               if (tab && data.userContextId) {
                 tab.setUserContextId(data.userContextId);
               }
 
+              updateUserContextUIIndicator(browser);
               break;
             }
             case "Findbar:Keypress": {
               let tab = this.getTabForBrowser(browser);
               // If the find bar for this tab is not yet alive, only initialize
               // it if there's a possibility FindAsYouType will be used.
               // There's no point in doing it for most random keypresses.
               if (!this.isFindBarInitialized(tab) &&
@@ -4481,17 +4472,17 @@
             this.mPanelContainer.classList.add("tabbrowser-tabpanels");
           } else {
             this._outerWindowIDBrowserMap.set(this.mCurrentBrowser.outerWindowID,
                                               this.mCurrentBrowser);
           }
           messageManager.addMessageListener("DOMWebNotificationClicked", this);
           messageManager.addMessageListener("DOMServiceWorkerFocusClient", this);
           messageManager.addMessageListener("RefreshBlocker:Blocked", this);
-          messageManager.addMessageListener("Browser:FirstContentLoaded", this);
+          messageManager.addMessageListener("Browser:WindowCreated", this);
 
           // To correctly handle keypresses for potential FindAsYouType, while
           // the tab's find bar is not yet initialized.
           this._findAsYouType = Services.prefs.getBoolPref("accessibility.typeaheadfind");
           Services.prefs.addObserver("accessibility.typeaheadfind", this, false);
           messageManager.addMessageListener("Findbar:Keypress", this);
         ]]>
       </constructor>
@@ -5216,30 +5207,30 @@
 
             let scrollButtonWidth = this.mTabstrip._scrollButtonDown.getBoundingClientRect().width;
             let paddingStart = this.mTabstrip.scrollboxPaddingStart;
             let width = 0;
 
             for (let i = numPinned - 1; i >= 0; i--) {
               let tab = this.childNodes[i];
               width += tab.getBoundingClientRect().width;
-              tab.style.MozMarginStart = - (width + scrollButtonWidth + paddingStart) + "px";
+              tab.style.marginInlineStart = - (width + scrollButtonWidth + paddingStart) + "px";
             }
 
-            this.style.MozPaddingStart = width + paddingStart + "px";
+            this.style.paddingInlineStart = width + paddingStart + "px";
 
           } else {
             this.removeAttribute("positionpinnedtabs");
 
             for (let i = 0; i < numPinned; i++) {
               let tab = this.childNodes[i];
-              tab.style.MozMarginStart = "";
+              tab.style.marginInlineStart = "";
             }
 
-            this.style.MozPaddingStart = "";
+            this.style.paddingInlineStart = "";
           }
 
           if (this._lastNumPinned != numPinned) {
             this._lastNumPinned = numPinned;
             this._handleTabSelect(false);
           }
         ]]></body>
       </method>
@@ -5359,16 +5350,17 @@
       </method>
 
       <method name="handleEvent">
         <parameter name="aEvent"/>
         <body><![CDATA[
           switch (aEvent.type) {
             case "load":
               this.updateVisibility();
+              TabsInTitlebar.init();
               break;
             case "resize":
               if (aEvent.target != window)
                 break;
 
               TabsInTitlebar.updateAppearance();
 
               var width = this.mTabstrip.boxObject.width;
@@ -5982,17 +5974,17 @@
 
         ind.collapsed = false;
 
         newMargin += ind.clientWidth / 2;
         if (!ltr)
           newMargin *= -1;
 
         ind.style.transform = "translate(" + Math.round(newMargin) + "px)";
-        ind.style.MozMarginStart = (-ind.clientWidth) + "px";
+        ind.style.marginInlineStart = (-ind.clientWidth) + "px";
       ]]></handler>
 
       <handler event="drop"><![CDATA[
         var dt = event.dataTransfer;
         var dropEffect = dt.dropEffect;
         var draggedTab;
         if (dt.mozTypesAt(0)[0] == TAB_DROP_TYPE) { // tab copy or move
           draggedTab = dt.mozGetDataAt(TAB_DROP_TYPE, 0);
@@ -6591,16 +6583,30 @@
             addEndImage().setAttribute("soundplaying", "true");
         ]]></body>
       </method>
     </implementation>
 
     <handlers>
       <handler event="popupshowing">
       <![CDATA[
+        if (event.target.getAttribute('id') == "alltabs_containersMenuTab") {
+          createUserContextMenu(event);
+          return;
+        }
+
+        let containersEnabled = Services.prefs.getBoolPref("privacy.userContext.enabled");
+        document.getElementById("alltabs-popup-separator-1").hidden = !containersEnabled;
+        let containersTab = document.getElementById("alltabs_containersTab");
+
+        containersTab.hidden = !containersEnabled;
+        if (PrivateBrowsingUtils.isWindowPrivate(window)) {
+          containersTab.setAttribute("disabled", "true");
+        }
+
         document.getElementById("alltabs_undoCloseTab").disabled =
           SessionStore.getClosedTabCount(window) == 0;
 
         var tabcontainer = gBrowser.tabContainer;
 
         // Listen for changes in the tab bar.
         tabcontainer.addEventListener("TabAttrModified", this, false);
         tabcontainer.addEventListener("TabClose", this, false);
@@ -6611,16 +6617,20 @@
           if (!tabs[i].pinned)
             this._createTabMenuItem(tabs[i]);
         }
         this._updateTabsVisibilityStatus();
       ]]></handler>
 
       <handler event="popuphidden">
       <![CDATA[
+        if (event.target.getAttribute('id') == "alltabs_containersMenuTab") {
+          return;
+        }
+
         // clear out the menu popup and remove the listeners
         for (let i = this.childNodes.length - 1; i > 0; i--) {
           let menuItem = this.childNodes[i];
           if (menuItem.tab) {
             menuItem.tab.mCorrespondingMenuitem = null;
             this.removeChild(menuItem);
           }
         }
--- a/browser/base/content/test/general/browser.ini
+++ b/browser/base/content/test/general/browser.ini
@@ -263,17 +263,17 @@ tags = mcb
 [browser_bug832435.js]
 [browser_bug839103.js]
 [browser_bug880101.js]
 [browser_bug882977.js]
 [browser_bug902156.js]
 tags = mcb
 [browser_bug906190.js]
 tags = mcb
-skip-if = buildapp == "mulet" || e10s # Bug 1093642 - test manipulates content and relies on content focus
+skip-if = buildapp == "mulet" # Bug 1093642 - test manipulates content and relies on content focus
 [browser_mixedContentFromOnunload.js]
 tags = mcb
 [browser_mixedContentFramesOnHttp.js]
 tags = mcb
 [browser_bug970746.js]
 [browser_bug1015721.js]
 skip-if = os == 'win'
 [browser_bug1064280_changeUrlInPinnedTab.js]
@@ -500,16 +500,17 @@ tags = psm
 [browser_mcb_redirect.js]
 tags = mcb
 [browser_windowactivation.js]
 [browser_contextmenu_childprocess.js]
 [browser_bug963945.js]
 [browser_readerMode.js]
 support-files =
   readerModeArticle.html
+  readerModeArticleHiddenNodes.html
 [browser_readerMode_hidden_nodes.js]
 support-files =
   readerModeArticleHiddenNodes.html
 [browser_bug1124271_readerModePinnedTab.js]
 support-files =
   readerModeArticle.html
 [browser_domFullscreen_fullscreenMode.js]
 tags = fullscreen
--- a/browser/base/content/test/general/browser_bug906190.js
+++ b/browser/base/content/test/general/browser_bug906190.js
@@ -187,45 +187,54 @@ add_task(function* test_same_origin_meta
   }, true);
 });
 
 /**
  * 5. - Load a html page which has mixed content
  *    - Doorhanger to disable protection appears - we disable it
  *    - Load a new page from the same origin in a new tab simulating a click
  *    - Redirect to another page from the same origin using 302 redirect
- *    - Doorhanger >> APPEARS << , but should >> NOT << appear again!
- *    - FOLLOW UP BUG 914860!
  */
 add_task(function* test_same_origin_302redirect_same_origin() {
   // the sjs files returns a 302 redirect- note, same origins
   yield doTest(gHttpTestRoot1 + "file_bug906190_1.html",
                gHttpTestRoot1 + "file_bug906190.sjs", function* () {
     // The doorhanger should appear but activeBlocked should be >> NOT << true.
     // Currently it is >> TRUE << - see follow up bug 914860
-    todo(!gIdentityHandler._identityBox.classList.contains("mixedActiveBlocked"),
-         "OK: Mixed Content is NOT being blocked");
+    ok(!gIdentityHandler._identityBox.classList.contains("mixedActiveBlocked"),
+       "OK: Mixed Content is NOT being blocked");
 
-    todo_is(content.document.getElementById('mctestdiv').innerHTML,
-            "Mixed Content Blocker disabled", "OK: Executed mixed script");
+    is(content.document.getElementById('mctestdiv').innerHTML,
+       "Mixed Content Blocker disabled", "OK: Executed mixed script");
   });
 });
 
 /**
  * 6. - Load a html page which has mixed content
  *    - Doorhanger to disable protection appears - we disable it
  *    - Load a new page from the same origin in a new tab simulating a click
  *    - Redirect to another page from a different origin using 302 redirect
- *    - Doorhanger >> SHOULD << appear again!
  */
 add_task(function* test_same_origin_302redirect_different_origin() {
   // the sjs files returns a 302 redirect - note, different origins
   yield doTest(gHttpTestRoot2 + "file_bug906190_1.html",
                gHttpTestRoot2 + "file_bug906190.sjs", function* () {
     // The doorhanger should appear and activeBlocked should be >> TRUE <<.
     yield assertMixedContentBlockingState(gBrowser, {
       activeLoaded: false, activeBlocked: true, passiveLoaded: false,
     });
 
     is(content.document.getElementById('mctestdiv').innerHTML,
        "Mixed Content Blocker enabled", "OK: Blocked mixed script");
   });
 });
+
+/**
+ * 7. - Test memory leak issue on redirection error. See Bug 1269426.
+ */
+add_task(function* test_bad_redirection() {
+  // the sjs files returns a 302 redirect - note, different origins
+  yield doTest(gHttpTestRoot2 + "file_bug906190_1.html",
+               gHttpTestRoot2 + "file_bug906190.sjs?bad-redirection=1", function* () {
+    // Nothing to do. Just see if memory leak is reported in the end.
+    ok(true, "Nothing to do");
+  });
+});
--- a/browser/base/content/test/general/browser_contextmenu.js
+++ b/browser/base/content/test/general/browser_contextmenu.js
@@ -112,17 +112,16 @@ add_task(function* test_video_ok() {
      "context-media-playbackrate", null,
          ["context-media-playbackrate-050x", true,
           "context-media-playbackrate-100x", true,
           "context-media-playbackrate-125x", true,
           "context-media-playbackrate-150x", true,
           "context-media-playbackrate-200x", true], null,
      "context-media-loop",         true,
      "context-media-hidecontrols", true,
-     "context-video-showstats",    true,
      "context-video-fullscreen",   true,
      "---",                        null,
      "context-viewvideo",          true,
      "context-copyvideourl",       true,
      "---",                        null,
      "context-savevideo",          true,
      "context-video-saveimage",    true,
      "context-sendvideo",          true,
@@ -160,17 +159,16 @@ add_task(function* test_video_bad() {
      "context-media-playbackrate", null,
          ["context-media-playbackrate-050x", false,
           "context-media-playbackrate-100x", false,
           "context-media-playbackrate-125x", false,
           "context-media-playbackrate-150x", false,
           "context-media-playbackrate-200x", false], null,
      "context-media-loop",         true,
      "context-media-hidecontrols", false,
-     "context-video-showstats",    false,
      "context-video-fullscreen",   false,
      "---",                        null,
      "context-viewvideo",          true,
      "context-copyvideourl",       true,
      "---",                        null,
      "context-savevideo",          true,
      "context-video-saveimage",    false,
      "context-sendvideo",          true,
@@ -187,17 +185,16 @@ add_task(function* test_video_bad2() {
      "context-media-playbackrate", null,
          ["context-media-playbackrate-050x", false,
           "context-media-playbackrate-100x", false,
           "context-media-playbackrate-125x", false,
           "context-media-playbackrate-150x", false,
           "context-media-playbackrate-200x", false], null,
      "context-media-loop",         true,
      "context-media-hidecontrols", false,
-     "context-video-showstats",    false,
      "context-video-fullscreen",   false,
      "---",                        null,
      "context-viewvideo",          false,
      "context-copyvideourl",       false,
      "---",                        null,
      "context-savevideo",          false,
      "context-video-saveimage",    false,
      "context-sendvideo",          false,
@@ -248,17 +245,16 @@ add_task(function* test_video_in_iframe(
      "context-media-playbackrate", null,
          ["context-media-playbackrate-050x", true,
           "context-media-playbackrate-100x", true,
           "context-media-playbackrate-125x", true,
           "context-media-playbackrate-150x", true,
           "context-media-playbackrate-200x", true], null,
      "context-media-loop",         true,
      "context-media-hidecontrols", true,
-     "context-video-showstats",    true,
      "context-video-fullscreen",   true,
      "---",                        null,
      "context-viewvideo",          true,
      "context-copyvideourl",       true,
      "---",                        null,
      "context-savevideo",          true,
      "context-video-saveimage",    true,
      "context-sendvideo",          true,
--- a/browser/base/content/test/general/browser_devices_get_user_media.js
+++ b/browser/base/content/test/general/browser_devices_get_user_media.js
@@ -5,27 +5,22 @@
 requestLongerTimeout(2);
 
 const CONTENT_SCRIPT_HELPER = getRootDirectory(gTestPath) + "get_user_media_content_script.js";
 Cc["@mozilla.org/moz/jssubscript-loader;1"]
   .getService(Ci.mozIJSSubScriptLoader)
   .loadSubScript(getRootDirectory(gTestPath) + "get_user_media_helpers.js",
                  this);
 
-function enableDevice(aType, aEnabled) {
-  let menulist = document.getElementById("webRTC-select" + aType + "-menulist");
-  let menupopup = document.getElementById("webRTC-select" + aType + "-menupopup");
-  menulist.value = aEnabled ? menupopup.firstChild.getAttribute("value") : "-1";
-}
-
 registerCleanupFunction(function() {
   gBrowser.removeCurrentTab();
 });
 
-const permissionError = "error: SecurityError: The operation is insecure.";
+const permissionError = "error: NotAllowedError: The request is not allowed " +
+    "by the user agent or the platform in the current context.";
 
 var gTests = [
 
 {
   desc: "getUserMedia audio+video",
   run: function checkAudioVideo() {
     let promise = promisePopupNotificationShown("webRTC-shareDevices");
     yield promiseRequestDevice(true, true);
@@ -62,18 +57,16 @@ var gTests = [
     yield expectObserverCalled("getUserMedia:request");
 
     is(PopupNotifications.getNotification("webRTC-shareDevices").anchorID,
        "webRTC-shareMicrophone-notification-icon", "anchored to mic icon");
     checkDeviceSelectors(true);
     is(PopupNotifications.panel.firstChild.getAttribute("popupid"),
        "webRTC-shareMicrophone", "panel using microphone icon");
 
-    enableDevice("Microphone", true);
-
     let indicator = promiseIndicatorWindow();
     yield promiseMessage("ok", () => {
       PopupNotifications.panel.firstChild.button.click();
     });
     yield expectObserverCalled("getUserMedia:response:allow");
     yield expectObserverCalled("recording-device-events");
     is((yield getMediaCaptureState()), "Microphone",
        "expected microphone to be shared");
@@ -108,107 +101,16 @@ var gTests = [
 
     yield indicator;
     yield checkSharingUI({video: true});
     yield closeStream();
   }
 },
 
 {
-  desc: "getUserMedia audio+video, user disables video",
-  run: function checkDisableVideo() {
-    let promise = promisePopupNotificationShown("webRTC-shareDevices");
-    yield promiseRequestDevice(true, true);
-    yield promise;
-    yield expectObserverCalled("getUserMedia:request");
-    checkDeviceSelectors(true, true);
-
-    // disable the camera
-    enableDevice("Microphone", true);
-    enableDevice("Camera", false);
-
-    let indicator = promiseIndicatorWindow();
-    yield promiseMessage("ok", () => {
-      PopupNotifications.panel.firstChild.button.click();
-    });
-
-    // reset the menuitem to have no impact on the following tests.
-    enableDevice("Camera", true);
-
-    yield expectObserverCalled("getUserMedia:response:allow");
-    yield expectObserverCalled("recording-device-events");
-    is((yield getMediaCaptureState()), "Microphone",
-       "expected microphone to be shared");
-
-    yield indicator;
-    yield checkSharingUI({audio: true});
-    yield closeStream();
-  }
-},
-
-{
-  desc: "getUserMedia audio+video, user disables audio",
-  run: function checkDisableAudio() {
-    let promise = promisePopupNotificationShown("webRTC-shareDevices");
-    yield promiseRequestDevice(true, true);
-    yield promise;
-    yield expectObserverCalled("getUserMedia:request");
-    checkDeviceSelectors(true, true);
-
-    // disable the microphone
-    enableDevice("Microphone", false);
-    enableDevice("Camera", true);
-
-    let indicator = promiseIndicatorWindow();
-    yield promiseMessage("ok", () => {
-      PopupNotifications.panel.firstChild.button.click();
-    });
-
-    // reset the menuitem to have no impact on the following tests.
-    enableDevice("Microphone", true);
-
-    yield expectObserverCalled("getUserMedia:response:allow");
-    yield expectObserverCalled("recording-device-events");
-    is((yield getMediaCaptureState()), "Camera",
-       "expected microphone to be shared");
-
-    yield indicator;
-    yield checkSharingUI({video: true});
-    yield closeStream();
-  }
-},
-
-{
-  desc: "getUserMedia audio+video, user disables both audio and video",
-  run: function checkDisableAudioVideo() {
-    let promise = promisePopupNotificationShown("webRTC-shareDevices");
-    yield promiseRequestDevice(true, true);
-    yield promise;
-    yield expectObserverCalled("getUserMedia:request");
-    checkDeviceSelectors(true, true);
-
-    // disable the camera and microphone
-    enableDevice("Camera", false);
-    enableDevice("Microphone", false);
-
-    yield promiseMessage(permissionError, () => {
-      PopupNotifications.panel.firstChild.button.click();
-    });
-
-    // reset the menuitems to have no impact on the following tests.
-    enableDevice("Camera", true);
-    enableDevice("Microphone", true);
-
-    yield expectObserverCalled("getUserMedia:response:deny");
-    yield expectObserverCalled("recording-window-ended");
-    yield checkNotSharing();
-  }
-},
-
-{
   desc: "getUserMedia audio+video, user clicks \"Don't Share\"",
   run: function checkDontShare() {
     let promise = promisePopupNotificationShown("webRTC-shareDevices");
     yield promiseRequestDevice(true, true);
     yield promise;
     yield expectObserverCalled("getUserMedia:request");
     checkDeviceSelectors(true, true);
 
@@ -303,47 +205,40 @@ var gTests = [
   }
 },
 
 {
   desc: "getUserMedia prompt: Always/Never Share",
   run: function checkRememberCheckbox() {
     let elt = id => document.getElementById(id);
 
-    function checkPerm(aRequestAudio, aRequestVideo, aAllowAudio, aAllowVideo,
+    function checkPerm(aRequestAudio, aRequestVideo,
                        aExpectedAudioPerm, aExpectedVideoPerm, aNever) {
       let promise = promisePopupNotificationShown("webRTC-shareDevices");
       yield promiseRequestDevice(aRequestAudio, aRequestVideo);
       yield promise;
       yield expectObserverCalled("getUserMedia:request");
 
-      let noAudio = aAllowAudio === undefined;
-      is(elt("webRTC-selectMicrophone").hidden, noAudio,
-         "microphone selector expected to be " + (noAudio ? "hidden" : "visible"));
-      if (!noAudio)
-        enableDevice("Microphone", aAllowAudio || aNever);
+      is(elt("webRTC-selectMicrophone").hidden, !aRequestAudio,
+         "microphone selector expected to be " + (aRequestAudio ? "visible" : "hidden"));
 
-      let noVideo = aAllowVideo === undefined;
-      is(elt("webRTC-selectCamera").hidden, noVideo,
-         "camera selector expected to be " + (noVideo ? "hidden" : "visible"));
-      if (!noVideo)
-        enableDevice("Camera", aAllowVideo || aNever);
+      is(elt("webRTC-selectCamera").hidden, !aRequestVideo,
+         "camera selector expected to be " + (aRequestVideo ? "visible" : "hidden"));
 
-      let expectedMessage =
-        (aAllowVideo || aAllowAudio) ? "ok" : permissionError;
+      let expectedMessage = aNever ? permissionError : "ok";
       yield promiseMessage(expectedMessage, () => {
         activateSecondaryAction(aNever ? kActionNever : kActionAlways);
       });
       let expected = [];
       if (expectedMessage == "ok") {
         yield expectObserverCalled("getUserMedia:response:allow");
         yield expectObserverCalled("recording-device-events");
-        if (aAllowVideo)
+        if (aRequestVideo)
           expected.push("Camera");
-        if (aAllowAudio)
+        if (aRequestAudio)
           expected.push("Microphone");
         expected = expected.join("And");
       }
       else {
         yield expectObserverCalled("getUserMedia:response:deny");
         yield expectObserverCalled("recording-window-ended");
         expected = "none";
       }
@@ -366,49 +261,29 @@ var gTests = [
       checkDevicePermissions("camera", aExpectedVideoPerm);
 
       if (expectedMessage == "ok")
         yield closeStream();
     }
 
     // 3 cases where the user accepts the device prompt.
     info("audio+video, user grants, expect both perms set to allow");
-    yield checkPerm(true, true, true, true, true, true);
+    yield checkPerm(true, true, true, true);
     info("audio only, user grants, check audio perm set to allow, video perm not set");
-    yield checkPerm(true, false, true, undefined, true, undefined);
+    yield checkPerm(true, false, true, undefined);
     info("video only, user grants, check video perm set to allow, audio perm not set");
-    yield checkPerm(false, true, undefined, true, undefined, true);
+    yield checkPerm(false, true, undefined, true);
 
-    // 3 cases where the user rejects the device request.
-    // First test these cases by setting the device to 'No Audio'/'No Video'
-    info("audio+video, user denies, expect both perms set to deny");
-    yield checkPerm(true, true, false, false, false, false);
+    // 3 cases where the user rejects the device request by using 'Never Share'.
     info("audio only, user denies, expect audio perm set to deny, video not set");
-    yield checkPerm(true, false, false, undefined, false, undefined);
+    yield checkPerm(true, false, false, undefined, true);
     info("video only, user denies, expect video perm set to deny, audio perm not set");
-    yield checkPerm(false, true, undefined, false, undefined, false);
-    // Now test these 3 cases again by using the 'Never Share' action.
+    yield checkPerm(false, true, undefined, false, true);
     info("audio+video, user denies, expect both perms set to deny");
-    yield checkPerm(true, true, false, false, false, false, true);
-    info("audio only, user denies, expect audio perm set to deny, video not set");
-    yield checkPerm(true, false, false, undefined, false, undefined, true);
-    info("video only, user denies, expect video perm set to deny, audio perm not set");
-    yield checkPerm(false, true, undefined, false, undefined, false, true);
-
-    // 2 cases where the user allows half of what's requested.
-    info("audio+video, user denies video, grants audio, " +
-         "expect video perm set to deny, audio perm set to allow.");
-    yield checkPerm(true, true, true, false, true, false);
-    info("audio+video, user denies audio, grants video, " +
-         "expect video perm set to allow, audio perm set to deny.");
-    yield checkPerm(true, true, false, true, false, true);
-
-    // reset the menuitems to have no impact on the following tests.
-    enableDevice("Microphone", true);
-    enableDevice("Camera", true);
+    yield checkPerm(true, true, false, false, true);
   }
 },
 
 {
   desc: "getUserMedia without prompt: use persistent permissions",
   run: function checkUsePersistentPermissions() {
     function usePerm(aAllowAudio, aAllowVideo, aRequestAudio, aRequestVideo,
                      aExpectStream) {
@@ -473,58 +348,58 @@ var gTests = [
 
     // Set both permissions identically
     info("allow audio+video, request audio+video, expect ok (audio+video)");
     yield usePerm(true, true, true, true, true);
     info("deny audio+video, request audio+video, expect denied");
     yield usePerm(false, false, true, true, false);
 
     // Allow audio, deny video.
-    info("allow audio, deny video, request audio+video, expect ok (audio)");
-    yield usePerm(true, false, true, true, true);
+    info("allow audio, deny video, request audio+video, expect denied");
+    yield usePerm(true, false, true, true, false);
     info("allow audio, deny video, request audio, expect ok (audio)");
     yield usePerm(true, false, true, false, true);
     info("allow audio, deny video, request video, expect denied");
     yield usePerm(true, false, false, true, false);
 
     // Deny audio, allow video.
-    info("deny audio, allow video, request audio+video, expect ok (video)");
-    yield usePerm(false, true, true, true, true);
+    info("deny audio, allow video, request audio+video, expect denied");
+    yield usePerm(false, true, true, true, false);
     info("deny audio, allow video, request audio, expect denied");
     yield usePerm(false, true, true, false, false);
     info("deny audio, allow video, request video, expect ok (video)");
     yield usePerm(false, true, false, true, true);
 
     // Allow audio, video not set.
     info("allow audio, request audio+video, expect prompt");
     yield usePerm(true, undefined, true, true, undefined);
     info("allow audio, request audio, expect ok (audio)");
     yield usePerm(true, undefined, true, false, true);
     info("allow audio, request video, expect prompt");
     yield usePerm(true, undefined, false, true, undefined);
 
     // Deny audio, video not set.
-    info("deny audio, request audio+video, expect prompt");
-    yield usePerm(false, undefined, true, true, undefined);
+    info("deny audio, request audio+video, expect denied");
+    yield usePerm(false, undefined, true, true, false);
     info("deny audio, request audio, expect denied");
     yield usePerm(false, undefined, true, false, false);
     info("deny audio, request video, expect prompt");
     yield usePerm(false, undefined, false, true, undefined);
 
-    // Allow video, video not set.
+    // Allow video, audio not set.
     info("allow video, request audio+video, expect prompt");
     yield usePerm(undefined, true, true, true, undefined);
     info("allow video, request audio, expect prompt");
     yield usePerm(undefined, true, true, false, undefined);
     info("allow video, request video, expect ok (video)");
     yield usePerm(undefined, true, false, true, true);
 
-    // Deny video, video not set.
-    info("deny video, request audio+video, expect prompt");
-    yield usePerm(undefined, false, true, true, undefined);
+    // Deny video, audio not set.
+    info("deny video, request audio+video, expect denied");
+    yield usePerm(undefined, false, true, true, false);
     info("deny video, request audio, expect prompt");
     yield usePerm(undefined, false, true, false, undefined);
     info("deny video, request video, expect denied");
     yield usePerm(undefined, false, false, true, false);
   }
 },
 
 {
--- a/browser/base/content/test/general/browser_devices_get_user_media_about_urls.js
+++ b/browser/base/content/test/general/browser_devices_get_user_media_about_urls.js
@@ -57,17 +57,18 @@ function loadPage(aUrl) {
   content.location = aUrl;
   return deferred.promise;
 }
 
 registerCleanupFunction(function() {
   gBrowser.removeCurrentTab();
 });
 
-const permissionError = "error: SecurityError: The operation is insecure.";
+const permissionError = "error: NotAllowedError: The request is not allowed " +
+    "by the user agent or the platform in the current context.";
 
 var gTests = [
 
 {
   desc: "getUserMedia about:loopconversation shouldn't prompt",
   run: function checkAudioVideoLoop() {
     yield new Promise(resolve => SpecialPowers.pushPrefEnv({
       "set": [[PREF_LOOP_CSP, "default-src 'unsafe-inline'"]],
--- a/browser/base/content/test/general/browser_readerMode.js
+++ b/browser/base/content/test/general/browser_readerMode.js
@@ -96,8 +96,120 @@ add_task(function* test_getOriginalUrl()
   is(ReaderMode.getOriginalUrl("about:reader?url=" + encodeURIComponent(url)), url, "Found original URL from encoded URL");
   is(ReaderMode.getOriginalUrl("about:reader?foobar"), null, "Did not find original URL from malformed reader URL");
   is(ReaderMode.getOriginalUrl(url), null, "Did not find original URL from non-reader URL");
 
   let badUrl = "http://foo.com/?;$%^^";
   is(ReaderMode.getOriginalUrl("about:reader?url=" + encodeURIComponent(badUrl)), badUrl, "Found original URL from encoded malformed URL");
   is(ReaderMode.getOriginalUrl("about:reader?url=" + badUrl), badUrl, "Found original URL from non-encoded malformed URL");
 });
+
+add_task(function* test_reader_view_element_attribute_transform() {
+  registerCleanupFunction(function() {
+    while (gBrowser.tabs.length > 1) {
+      gBrowser.removeCurrentTab();
+    }
+  });
+
+  function observeAttribute(element, attribute, triggerFn, checkFn) {
+    let initValue = element.getAttribute(attribute);
+    return new Promise(resolve => {
+      let observer = new MutationObserver((mutations) => {
+        mutations.forEach( mu => {
+          let muValue = element.getAttribute(attribute);
+          if(element.getAttribute(attribute) !== mu.oldValue) {
+            checkFn();
+            resolve();
+            observer.disconnect();
+          }
+        });
+      });
+
+      observer.observe(element, {
+        attributes: true,
+        attributeOldValue: true,
+        attributeFilter: [attribute]
+      });
+
+      triggerFn();
+    });
+  };
+
+  let command = document.getElementById("View:ReaderView");
+  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser);
+  is(command.hidden, true, "Command element should have the hidden attribute");
+
+  info("Navigate a reader-able page");
+  let waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+  yield observeAttribute(command, "hidden",
+    () => {
+      let url = TEST_PATH + "readerModeArticle.html";
+      tab.linkedBrowser.loadURI(url);
+    },
+    () => {
+      is(command.hidden, false, "Command's hidden attribute should be false on a reader-able page");
+    }
+  );
+  yield waitForPageshow;
+
+  info("Navigate a non-reader-able page");
+  waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+  yield observeAttribute(command, "hidden",
+    () => {
+      let url = TEST_PATH + "readerModeArticleHiddenNodes.html";
+      tab.linkedBrowser.loadURI(url);
+    },
+    () => {
+      is(command.hidden, true, "Command's hidden attribute should be true on a non-reader-able page");
+    }
+  );
+  yield waitForPageshow;
+
+  info("Navigate a reader-able page");
+  waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+  yield observeAttribute(command, "hidden",
+    () => {
+      let url = TEST_PATH + "readerModeArticle.html";
+      tab.linkedBrowser.loadURI(url);
+    },
+    () => {
+      is(command.hidden, false, "Command's hidden attribute should be false on a reader-able page");
+    }
+  );
+  yield waitForPageshow;
+
+  info("Enter Reader Mode");
+  waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+  yield observeAttribute(readerButton, "readeractive",
+    () => {
+      readerButton.click();
+    },
+    () => {
+      is(readerButton.getAttribute("readeractive"), "true", "readerButton's readeractive attribute should be true when entering reader mode");
+    }
+  );
+  yield waitForPageshow;
+
+  info("Exit Reader Mode");
+  waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+  yield observeAttribute(readerButton, "readeractive",
+    () => {
+      readerButton.click();
+    },
+    () => {
+      is(readerButton.getAttribute("readeractive"), "", "readerButton's readeractive attribute should be empty when reader mode is exited");
+    }
+  );
+  yield waitForPageshow;
+
+  info("Navigate a non-reader-able page");
+  waitForPageshow = BrowserTestUtils.waitForContentEvent(tab.linkedBrowser, "pageshow");
+  yield observeAttribute(command, "hidden",
+    () => {
+      let url = TEST_PATH + "readerModeArticleHiddenNodes.html";
+      tab.linkedBrowser.loadURI(url);
+    },
+    () => {
+      is(command.hidden, true, "Command's hidden attribute should be true on a non-reader-able page");
+    }
+  );
+  yield waitForPageshow;
+});
--- a/browser/base/content/test/general/browser_selectpopup.js
+++ b/browser/base/content/test/general/browser_selectpopup.js
@@ -270,8 +270,75 @@ add_task(function*() {
     is(rect.left, expectedX, "step " + (stepIndex + 1) + " x");
     is(rect.top, expectedY, "step " + (stepIndex + 1) + " y");
 
     yield hideSelectPopup(selectPopup);
   }
 
   yield BrowserTestUtils.removeTab(tab);
 });
+
+// Test that we get the right events when a select popup is changed.
+add_task(function* test_event_order() {
+  const URL = "data:text/html," + escape(PAGECONTENT_SMALL);
+  yield BrowserTestUtils.withNewTab({
+    gBrowser,
+    url: URL,
+  }, function*(browser) {
+    let menulist = document.getElementById("ContentSelectDropdown");
+    let selectPopup = menulist.menupopup;
+
+    yield openSelectPopup(selectPopup, true, "#one");
+
+    let eventsPromise = ContentTask.spawn(browser, null, function*() {
+      // According to https://html.spec.whatwg.org/#the-select-element,
+      // we want to fire input, change, and then click events on the
+      // <select> (in that order) when it has changed.
+      let expected = [
+        {
+          type: "input",
+          cancelable: false,
+        },
+        {
+          type: "change",
+          cancelable: false,
+        },
+        {
+          type: "mousedown",
+          cancelable: true,
+        },
+        {
+          type: "mouseup",
+          cancelable: true,
+        },
+        {
+          type: "click",
+          cancelable: true,
+        },
+      ];
+
+      return new Promise((resolve) => {
+        function onEvent(event) {
+          select.removeEventListener(event.type, onEvent);
+          let expectation = expected.shift();
+          Assert.equal(event.type, expectation.type,
+                       "Expected the right event order");
+          Assert.ok(event.bubbles, "All of these events should bubble");
+          Assert.equal(event.cancelable, expectation.cancelable,
+                       "Cancellation property should match");
+          if (!expected.length) {
+            resolve();
+          }
+        }
+
+        let select = content.document.getElementById("one");
+        for (let expectation of expected) {
+          select.addEventListener(expectation.type, onEvent);
+        }
+      });
+    });
+
+    EventUtils.synthesizeKey("KEY_ArrowDown", { code: "ArrowDown" });
+    yield hideSelectPopup(selectPopup, false);
+    yield eventsPromise;
+  });
+});
+
--- a/browser/base/content/test/general/browser_syncui.js
+++ b/browser/base/content/test/general/browser_syncui.js
@@ -174,16 +174,29 @@ function *doTestButtonActivities() {
 }
 
 add_task(function* testButtonActivitiesInNavBar() {
   // check the button's functionality while the button is in the NavBar - which
   // it already is.
   yield doTestButtonActivities();
 });
 
+add_task(function* testFormatLastSyncDateNow() {
+  let now = new Date();
+  let nowString = gSyncUI.formatLastSyncDate(now);
+  Assert.equal(nowString, "Last sync: " + now.toLocaleDateString(undefined, {weekday: 'long', hour: 'numeric', minute: 'numeric'}));
+});
+
+add_task(function* testFormatLastSyncDateMonthAgo() {
+  let monthAgo = new Date();
+  monthAgo.setMonth(monthAgo.getMonth() - 1);
+  let monthAgoString = gSyncUI.formatLastSyncDate(monthAgo);
+  Assert.equal(monthAgoString, "Last sync: " + monthAgo.toLocaleDateString(undefined, {month: 'long', day: 'numeric'}));
+});
+
 add_task(function* testButtonActivitiesInPanel() {
   // check the button's functionality while the button is in the panel - it's
   // currently in the NavBar - move it to the panel and open it.
   CustomizableUI.addWidgetToArea("sync-button", CustomizableUI.AREA_PANEL);
   yield PanelUI.show();
   try {
     yield doTestButtonActivities();
   } finally {
--- a/browser/base/content/test/general/file_bug906190.sjs
+++ b/browser/base/content/test/general/file_bug906190.sjs
@@ -1,11 +1,17 @@
 function handleRequest(request, response) {
   var page = "<!DOCTYPE html><html><body>bug 906190</body></html>";
   var path = "https://test1.example.com/browser/browser/base/content/test/general/";
-  var url = path + "file_bug906190_redirected.html";
+  var url;
+
+  if (request.queryString.includes('bad-redirection=1')) {
+    url = path + "this_page_does_not_exist.html";
+  } else {
+    url = path + "file_bug906190_redirected.html";
+  }
 
   response.setHeader("Cache-Control", "no-cache", false);
   response.setHeader("Content-Type", "text/html", false);
   response.setStatusLine(request.httpVersion, "302", "Found");
   response.setHeader("Location", url, false);
   response.write(page);
 }
--- a/browser/base/content/test/referrer/browser_referrer_open_link_in_container_tab.js
+++ b/browser/base/content/test/referrer/browser_referrer_open_link_in_container_tab.js
@@ -18,19 +18,19 @@ function startNewTabTestCase(aTestNumber
     someTabLoaded(gTestWindow).then(function(aNewTab) {
       gTestWindow.gBrowser.selectedTab = aNewTab;
 
       checkReferrerAndStartNextTest(aTestNumber, null, aNewTab,
                                     startNewTabTestCase);
     });
 
     let menu = gTestWindow.document.getElementById("context-openlinkinusercontext-menu");
-    ok(menu && menu.firstChild, "The menu exists and it has a first child node.");
+    let menupopup = menu.menupopup;
+    menupopup.showPopup();
 
-    let menupopup = menu.firstChild;
     is(menupopup.nodeType, Node.ELEMENT_NODE, "We have a menupopup.");
     ok(menupopup.firstChild, "We have a first container entry.");
 
     let firstContext = menupopup.firstChild;
     is(firstContext.nodeType, Node.ELEMENT_NODE, "We have a first container entry.");
     ok(firstContext.hasAttribute('usercontextid'), "We have a usercontextid value.");
 
     firstContext.doCommand();
--- a/browser/base/content/utilityOverlay.js
+++ b/browser/base/content/utilityOverlay.js
@@ -8,16 +8,19 @@ Components.utils.import("resource://gre/
 Components.utils.import("resource://gre/modules/Services.jsm");
 Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
 Components.utils.import("resource://gre/modules/PrivateBrowsingUtils.jsm");
 Components.utils.import("resource:///modules/RecentWindow.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ShellService",
                                   "resource:///modules/ShellService.jsm");
 
+XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
+                                  "resource:///modules/ContextualIdentityService.jsm");
+
 XPCOMUtils.defineLazyServiceGetter(this, "aboutNewTabService",
                                    "@mozilla.org/browser/aboutnewtab-service;1",
                                    "nsIAboutNewTabService");
 
 this.__defineGetter__("BROWSER_NEW_TAB_URL", () => {
   if (PrivateBrowsingUtils.isWindowPrivate(window) &&
       !PrivateBrowsingUtils.permanentPrivateBrowsing &&
       !aboutNewTabService.overridden) {
@@ -398,16 +401,46 @@ function checkForMiddleClick(node, event
     fn.call(target, event);
 
     // If the middle-click was on part of a menu, close the menu.
     // (Menus close automatically with left-click but not with middle-click.)
     closeMenus(event.target);
   }
 }
 
+// Populate a menu with user-context menu items. This method should be called
+// by onpopupshowing passing the event as first argument. addCommandAttribute
+// param is used to set the 'command' attribute in the new menuitem elements.
+function createUserContextMenu(event, addCommandAttribute = true) {
+  while (event.target.hasChildNodes()) {
+    event.target.removeChild(event.target.firstChild);
+  }
+
+  let bundle = document.getElementById("bundle_browser");
+  let docfrag = document.createDocumentFragment();
+
+  ContextualIdentityService.getIdentities().forEach(identity => {
+    let menuitem = document.createElement("menuitem");
+    menuitem.setAttribute("usercontextid", identity.userContextId);
+    menuitem.setAttribute("label", bundle.getString(identity.label));
+    menuitem.setAttribute("accesskey", bundle.getString(identity.accessKey));
+
+    if (addCommandAttribute) {
+      menuitem.setAttribute("command", "Browser:NewUserContextTab");
+    }
+
+    menuitem.style.listStyleImage = "url(" + identity.icon + ")";
+
+    docfrag.appendChild(menuitem);
+  });
+
+  event.target.appendChild(docfrag);
+  return true;
+}
+
 // Closes all popups that are ancestors of the node.
 function closeMenus(node)
 {
   if ("tagName" in node) {
     if (node.namespaceURI == "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
     && (node.tagName == "menupopup" || node.tagName == "popup"))
       node.hidePopup();
 
--- a/browser/components/about/moz.build
+++ b/browser/components/about/moz.build
@@ -12,11 +12,8 @@ SOURCES += [
     'AboutRedirector.cpp',
 ]
 
 FINAL_LIBRARY = 'browsercomps'
 
 LOCAL_INCLUDES += [
     '../build',
 ]
-
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wshadow']
--- a/browser/components/build/moz.build
+++ b/browser/components/build/moz.build
@@ -33,11 +33,8 @@ if CONFIG['OS_ARCH'] == 'WINNT':
     DELAYLOAD_DLLS += [
         'esent.dll',
     ]
 
 # Mac: Need to link with CoreFoundation for Mac Migrators (PList reading code)
 # GTK2: Need to link with glib for GNOME shell service
 if CONFIG['MOZ_WIDGET_TOOLKIT'] in ('cocoa', 'gtk2', 'gtk3'):
     OS_LIBS += CONFIG['TK_LIBS']
-
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wshadow']
rename from browser/modules/UserContextUI.jsm
rename to browser/components/contextualidentity/ContextualIdentityService.jsm
--- a/browser/modules/UserContextUI.jsm
+++ b/browser/components/contextualidentity/ContextualIdentityService.jsm
@@ -1,32 +1,84 @@
 /* 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.EXPORTED_SYMBOLS = ["UserContextUI"];
+this.EXPORTED_SYMBOLS = ["ContextualIdentityService"];
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm")
 
 XPCOMUtils.defineLazyGetter(this, "gBrowserBundle", function() {
   return Services.strings.createBundle("chrome://browser/locale/browser.properties");
 });
 
-this.UserContextUI = {
-  getUserContextLabel(userContextId) {
-    switch (parseInt(userContextId)) {
-      // No UserContext:
-      case 0: return "";
+this.ContextualIdentityService = {
+  _identities: [
+    { userContextId: 1,
+      icon: "chrome://browser/skin/usercontext/personal.svg",
+      color: "#00a7e0",
+      label: "userContextPersonal.label",
+      accessKey: "userContextPersonal.accesskey" },
+    { userContextId: 2,
+      icon: "chrome://browser/skin/usercontext/work.svg",
+      color: "#f89c24",
+      label: "userContextWork.label",
+      accessKey: "userContextWork.accesskey" },
+    { userContextId: 3,
+      icon: "chrome://browser/skin/usercontext/banking.svg",
+      color: "#7dc14c",
+      label: "userContextBanking.label",
+      accessKey: "userContextBanking.accesskey" },
+    { userContextId: 4,
+      icon: "chrome://browser/skin/usercontext/shopping.svg",
+      color: "#ee5195",
+      label: "userContextShopping.label",
+      accessKey: "userContextShopping.accesskey" },
+  ],
+
+  _cssRule: false,
+
+  getIdentities() {
+    return this._identities;
+  },
+
+  getIdentityFromId(userContextId) {
+    return this._identities.find(info => info.userContextId == userContextId);
+  },
 
-      case 1: return gBrowserBundle.GetStringFromName("usercontext.personal.label");
-      case 2: return gBrowserBundle.GetStringFromName("usercontext.work.label");
-      case 3: return gBrowserBundle.GetStringFromName("usercontext.banking.label");
-      case 4: return gBrowserBundle.GetStringFromName("usercontext.shopping.label");
+  getUserContextLabel(userContextId) {
+    let identity = this.getIdentityFromId(userContextId);
+    return gBrowserBundle.GetStringFromName(identity.label);
+  },
+
+  needsCssRule() {
+    return !this._cssRule;
+  },
+
+  storeCssRule(cssRule) {
+    this._cssRule = cssRule;
+  },
+
+  cssRules() {
+    let rules = [];
 
-      // Display the context IDs for values outside the pre-defined range.
-      // Used for debugging, no localization necessary.
-      default: return "Context " + userContextId;
+    if (this.needsCssRule()) {
+      return rules;
     }
-  }
+
+    /* The CSS Rules for the ContextualIdentity tabs are set up like this:
+     * 1. :root { --usercontext-color-<id>: #color }
+     * 2. the template, replacing 'id' with the userContextId.
+     * 3. tabbrowser-tab[usercontextid="<id>"] { background-image: var(--usercontext-tab-<id>) }
+     */
+    for (let identity of this._identities) {
+      rules.push(":root { --usercontext-color-" + identity.userContextId + ": " + identity.color + " }");
+
+      rules.push(this._cssRule.replace(/id/g, identity.userContextId));
+      rules.push(".tabbrowser-tab[usercontextid=\"" + identity.userContextId + "\"] { background-image: var(--usercontext-tab-" + identity.userContextId + ") }");
+    }
+
+    return rules;
+  },
 }
rename from browser/themes/shared/usercontext/usercontext.inc.css
rename to browser/components/contextualidentity/content/usercontext.css
--- a/browser/themes/shared/usercontext/usercontext.inc.css
+++ b/browser/components/contextualidentity/content/usercontext.css
@@ -1,69 +1,27 @@
-/* User Context UI browser styles */
-
-#menu_newUserContextTabPersonal {
-  list-style-image: url("chrome://browser/skin/usercontext/personal.svg");
-}
-
-#menu_newUserContextTabWork {
-  list-style-image: url("chrome://browser/skin/usercontext/work.svg");
+:root {
+  /* This is used as a template for ContextualIdentityService. 'id' will be
+   * replaced with the userContextId */
+  --usercontext-tab-id: linear-gradient(to right, transparent 20%, var(--usercontext-color-id) 30%, var(--usercontext-color-id) 70%, transparent 80%);
 }
 
-#menu_newUserContextTabBanking {
-  list-style-image: url("chrome://browser/skin/usercontext/banking.svg");
-}
-
-#menu_newUserContextTabShopping {
-  list-style-image: url("chrome://browser/skin/usercontext/shopping.svg");
-}
-
-/* URL Bar Decoration */
-
 #userContext-indicator {
   height: 16px;
   width: 16px;
 }
 
 #userContext-label {
   margin-inline-end: 3px;
   color: #909090;
 }
 
-#userContext-icons:not([usercontextid]) {
-  display: none;
-}
-
 #userContext-icons {
   -moz-box-align: center;
 }
 
-/* Personal User Context */
-#userContext-icons[usercontextid="1"] > #userContext-label {
-  color: #00a7e0;
-}
-#userContext-icons[usercontextid="1"] > #userContext-indicator {
-  list-style-image: url("chrome://browser/skin/usercontext/personal.svg");
-}
-
-/* Work User Context */
-#userContext-icons[usercontextid="2"] > #userContext-label {
-  color: #f89c24;
-}
-#userContext-icons[usercontextid="2"] > #userContext-indicator {
-  list-style-image: url("chrome://browser/skin/usercontext/work.svg");
+/* User Context UI - change tab decoration depending on userContextId.
+   Defaults to gray for unknown usercontextids. */
+.tabbrowser-tab[usercontextid] {
+  background-image: linear-gradient(to right, transparent 20%, #909090 30%, #909090 70%, transparent 80%);
+  background-size: auto 2px;
+  background-repeat: no-repeat;
 }
-
-/* Banking User Context */
-#userContext-icons[usercontextid="3"] > #userContext-label {
-  color: #7dc14c;
-}
-#userContext-icons[usercontextid="3"] > #userContext-indicator {
-  list-style-image: url("chrome://browser/skin/usercontext/banking.svg");
-}
-
-/* Shopping User Context */
-#userContext-icons[usercontextid="4"] > #userContext-label {
-  color: #ee5195;
-}
-#userContext-icons[usercontextid="4"] > #userContext-indicator {
-  list-style-image: url("chrome://browser/skin/usercontext/shopping.svg");
-}
new file mode 100644
--- /dev/null
+++ b/browser/components/contextualidentity/jar.mn
@@ -0,0 +1,6 @@
+# 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/.
+
+browser.jar:
+    content/browser/usercontext/usercontext.css (content/usercontext.css)
--- a/browser/components/contextualidentity/moz.build
+++ b/browser/components/contextualidentity/moz.build
@@ -3,10 +3,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/.
 
 BROWSER_CHROME_MANIFESTS += [
     'test/browser/browser.ini',
 ]
 
+EXTRA_JS_MODULES += [
+    'ContextualIdentityService.jsm',
+]
+
+JAR_MANIFESTS += ['jar.mn']
+
 with Files('**'):
     BUG_COMPONENT = ('Firefox', 'Contextual Identity')
--- a/browser/components/contextualidentity/test/browser/browser_aboutURLs.js
+++ b/browser/components/contextualidentity/test/browser/browser_aboutURLs.js
@@ -1,8 +1,14 @@
+"use strict";
+
+// For some about: URLs, they will take more time to load and cause timeout.
+// See Bug 1270998.
+requestLongerTimeout(2);
+
 add_task(function* () {
   let aboutURLs = [];
 
   // List of about: URLs that will initiate network requests.
   let networkURLs = [
     "credits",
     "telemetry" // about:telemetry will fetch Telemetry asynchrounously and takes
                 // longer, we skip this for now.
--- a/browser/components/customizableui/CustomizableWidgets.jsm
+++ b/browser/components/customizableui/CustomizableWidgets.jsm
@@ -22,16 +22,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "ShortcutUtils",
   "resource://gre/modules/ShortcutUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "CharsetMenu",
   "resource://gre/modules/CharsetMenu.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "SyncedTabs",
   "resource://services-sync/SyncedTabs.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
+  "resource:///modules/ContextualIdentityService.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "CharsetBundle", function() {
   const kCharsetBundle = "chrome://global/locale/charsetMenu.properties";
   return Services.strings.createBundle(kCharsetBundle);
 });
 XPCOMUtils.defineLazyGetter(this, "BrandBundle", function() {
   const kBrandBundle = "chrome://branding/locale/brand.properties";
   return Services.strings.createBundle(kBrandBundle);
@@ -482,16 +484,17 @@ const CustomizableWidgets = [
       item.setAttribute("label", tabInfo.title != "" ? tabInfo.title : tabInfo.url);
       item.setAttribute("image", tabInfo.icon);
       item.setAttribute("tooltiptext", tooltipText);
       // We need to use "click" instead of "command" here so openUILink
       // respects different buttons (eg, to open in a new tab).
       item.addEventListener("click", e => {
         doc.defaultView.openUILink(tabInfo.url, e);
         CustomizableUI.hidePanelForNode(item);
+        BrowserUITelemetry.countSyncedTabEvent("open", "toolbarbutton-subview");
       });
       return item;
     },
   }, {
     id: "privatebrowsing-button",
     shortcutId: "key_privatebrowsing",
     defaultArea: CustomizableUI.AREA_PANEL,
     onCommand: function(e) {
@@ -1092,16 +1095,65 @@ const CustomizableWidgets = [
     id: "email-link-button",
     tooltiptext: "email-link-button.tooltiptext3",
     onCommand: function(aEvent) {
       let win = aEvent.view;
       win.MailIntegration.sendLinkForBrowser(win.gBrowser.selectedBrowser)
     }
   }];
 
+if (Services.prefs.getBoolPref("privacy.userContext.enabled")) {
+  CustomizableWidgets.push({
+    id: "containers-panelmenu",
+    type: "view",
+    viewId: "PanelUI-containers",
+    onCreated: function(aNode) {
+      let doc = aNode.ownerDocument;
+      let win = doc.defaultView;
+      let items = doc.getElementById("PanelUI-containersItems");
+
+      let onItemCommand = function (aEvent) {
+        let item = aEvent.target;
+        let userContextId = parseInt(item.getAttribute("usercontextid"));
+        win.openUILinkIn(win.BROWSER_NEW_TAB_URL, "tab", {userContextId});
+      };
+      items.addEventListener("command", onItemCommand);
+
+      if (PrivateBrowsingUtils.isWindowPrivate(win)) {
+        aNode.setAttribute("disabled", "true");
+      }
+    },
+    onViewShowing: function(aEvent) {
+      let doc = aEvent.detail.ownerDocument;
+
+      let items = doc.getElementById("PanelUI-containersItems");
+
+      while (items.firstChild) {
+        items.firstChild.remove();
+      }
+
+      let fragment = doc.createDocumentFragment();
+
+      ContextualIdentityService.getIdentities().forEach(identity => {
+        let bundle = doc.getElementById("bundle_browser");
+        let label = bundle.getString(identity.label);
+
+        let item = doc.createElementNS(kNSXUL, "toolbarbutton");
+        item.setAttribute("label", label);
+        item.setAttribute("usercontextid", identity.userContextId);
+        item.setAttribute("class", "subviewbutton");
+
+        fragment.appendChild(item);
+      });
+
+      items.appendChild(fragment);
+    }
+  });
+}
+
 let preferencesButton = {
   id: "preferences-button",
   defaultArea: CustomizableUI.AREA_PANEL,
   onCommand: function(aEvent) {
     let win = aEvent.target &&
               aEvent.target.ownerDocument &&
               aEvent.target.ownerDocument.defaultView;
     if (win && typeof win.openPreferences == "function") {
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -1431,27 +1431,16 @@ CustomizeMode.prototype = {
           lwthemePrefs.setComplexValue("recommendedThemes",
                                        Ci.nsISupportsString, string);
           this.parentNode.hidePopup();
         });
         panel.insertBefore(tbb, footer);
       }
       let hideRecommendedLabel = (footer.previousSibling == recommendedLabel);
       recommendedLabel.hidden = hideRecommendedLabel;
-
-      let hideMyThemesSection = themesInMyThemesSection < 2 && hideRecommendedLabel;
-      let headerLabel = doc.getElementById("customization-lwtheme-menu-header");
-      if (hideMyThemesSection) {
-        let element = recommendedLabel.previousSibling;
-        while (element && element != headerLabel) {
-          element.hidden = true;
-          element = element.previousSibling;
-        }
-      }
-      headerLabel.hidden = hideMyThemesSection;
     }.bind(this));
   },
 
   resetLWThemesMenu: function(target) {
     let doc = target.ownerDocument;
     let footer = doc.getElementById("customization-lwtheme-menu-footer");
     let recommendedLabel = doc.getElementById("customization-lwtheme-menu-recommended");
     this.swatchForTheme(doc);
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -243,16 +243,21 @@
     <panelview id="PanelUI-socialapi" flex="1"/>
 
     <panelview id="PanelUI-loopapi" flex="1"/>
 
     <panelview id="PanelUI-feeds" flex="1" oncommand="FeedHandler.subscribeToFeed(null, event);">
       <label value="&feedsMenu2.label;" class="panel-subview-header"/>
     </panelview>
 
+    <panelview id="PanelUI-containers" flex="1">
+      <label value="&containersMenu.label;" class="panel-subview-header"/>
+      <vbox id="PanelUI-containersItems"/>
+    </panelview>
+
     <panelview id="PanelUI-helpView" flex="1" class="PanelUI-subView">
       <label value="&helpMenu.label;" class="panel-subview-header"/>
       <vbox id="PanelUI-helpItems" class="panel-subview-body"/>
     </panelview>
 
     <panelview id="PanelUI-developer" flex="1">
       <label value="&webDeveloperMenu.label;" class="panel-subview-header"/>
       <vbox id="PanelUI-developerItems" class="panel-subview-body"/>
--- a/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
+++ b/browser/components/customizableui/test/browser_1007336_lwthemes_in_customize_mode.js
@@ -57,16 +57,36 @@ add_task(function* () {
      "The second theme in the 'My Themes' section should be the newly installed theme: " +
      "Installed theme id: " + installedThemeId + "; First theme ID: " + firstLWThemeId);
   is(header.nextSibling.nextSibling.nextSibling, recommendedHeader,
      "There should be two themes in the 'My Themes' section");
 
   let defaultTheme = header.nextSibling;
   defaultTheme.doCommand();
   is(Services.prefs.getCharPref("lightweightThemes.selectedThemeID"), "", "No lwtheme should be selected");
+
+  yield endCustomizing();
+  Services.prefs.setCharPref("lightweightThemes.usedThemes", "[]");
+  Services.prefs.setCharPref("lightweightThemes.recommendedThemes", "[]");
+  info("Removed all recommended themes");
+  yield startCustomizing();
+  popupShownPromise = popupShown(popup);
+  EventUtils.synthesizeMouseAtCenter(themesButton, {});
+  info("Clicked on themes button a second time");
+  yield popupShownPromise;
+  header = document.getElementById("customization-lwtheme-menu-header");
+  is(header.hidden, false, "Header should never be hidden");
+  is(header.nextSibling.theme.id, DEFAULT_THEME_ID, "The first theme should be the Default theme");
+  is(header.nextSibling.hidden, false, "The default theme should never be hidden");
+  recommendedHeader = document.getElementById("customization-lwtheme-menu-recommended");
+  is(header.nextSibling.nextSibling, recommendedHeader,
+     "There should only be one theme (default) in the 'My Themes' section by default");
+  let footer = document.getElementById("customization-lwtheme-menu-footer");
+  is(recommendedHeader.nextSibling.id, footer.id, "There should be no recommended themes in the menu");
+  is(recommendedHeader.hidden, true, "The recommendedHeader should be hidden since there are no recommended themes");
 });
 
 add_task(function* asyncCleanup() {
   yield endCustomizing();
 
   Services.prefs.clearUserPref("lightweightThemes.usedThemes");
   Services.prefs.clearUserPref("lightweightThemes.recommendedThemes");
 });
--- a/browser/components/dirprovider/moz.build
+++ b/browser/components/dirprovider/moz.build
@@ -12,11 +12,8 @@ SOURCES += [
     'DirectoryProvider.cpp',
 ]
 
 FINAL_LIBRARY = 'browsercomps'
 
 LOCAL_INCLUDES += [
     '../build'
 ]
-
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wshadow']
--- a/browser/components/extensions/ext-history.js
+++ b/browser/components/extensions/ext-history.js
@@ -4,16 +4,52 @@
 
 const {classes: Cc, interfaces: Ci, utils: Cu} = Components;
 
 XPCOMUtils.defineLazyGetter(this, "History", () => {
   Cu.import("resource://gre/modules/PlacesUtils.jsm");
   return PlacesUtils.history;
 });
 
+Cu.import("resource://gre/modules/ExtensionUtils.jsm");
+const {
+  normalizeTime,
+} = ExtensionUtils;
+
+/*
+ * Converts a nsINavHistoryResultNode into a plain object
+ *
+ * https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsINavHistoryResultNode
+ */
+function convertNavHistoryResultNode(node) {
+  return {
+    id: node.pageGuid,
+    url: node.uri,
+    title: node.title,
+    lastVisitTime: PlacesUtils.toTime(node.time),
+    visitCount: node.accessCount,
+  };
+}
+
+/*
+ * Converts a nsINavHistoryContainerResultNode into an array of objects
+ *
+ * https://developer.mozilla.org/en-US/docs/XPCOM_Interface_Reference/nsINavHistoryContainerResultNode
+ */
+function convertNavHistoryContainerResultNode(container) {
+  let results = [];
+  container.containerOpen = true;
+  for (let i = 0; i < container.childCount; i++) {
+    let node = container.getChild(i);
+    results.push(convertNavHistoryResultNode(node));
+  }
+  container.containerOpen = false;
+  return results;
+}
+
 extensions.registerSchemaAPI("history", "history", (extension, context) => {
   return {
     history: {
       deleteAll: function() {
         return History.clear();
       },
       deleteRange: function(filter) {
         let newFilter = {
@@ -23,11 +59,34 @@ extensions.registerSchemaAPI("history", 
         // History.removeVisitsByFilter returns a boolean, but our API should return nothing
         return History.removeVisitsByFilter(newFilter).then(() => undefined);
       },
       deleteUrl: function(details) {
         let url = details.url;
         // History.remove returns a boolean, but our API should return nothing
         return History.remove(url).then(() => undefined);
       },
+      search: function(query) {
+        let beginTime = (query.startTime == null) ?
+                          PlacesUtils.toPRTime(Date.now() - 24 * 60 * 60 * 1000) :
+                          PlacesUtils.toPRTime(normalizeTime(query.startTime));
+        let endTime = (query.endTime == null) ?
+                        Number.MAX_VALUE :
+                        PlacesUtils.toPRTime(normalizeTime(query.endTime));
+        if (beginTime > endTime) {
+          return Promise.reject({message: "The startTime cannot be after the endTime"});
+        }
+
+        let options = History.getNewQueryOptions();
+        options.sortingMode = options.SORT_BY_DATE_DESCENDING;
+        options.maxResults = query.maxResults || 100;
+
+        let historyQuery = History.getNewQuery();
+        historyQuery.searchTerms = query.text;
+        historyQuery.beginTime = beginTime;
+        historyQuery.endTime = endTime;
+        let queryResult = History.executeQuery(historyQuery, options).root;
+        let results = convertNavHistoryContainerResultNode(queryResult);
+        return Promise.resolve(results);
+      },
     },
   };
 });
--- a/browser/components/extensions/schemas/history.json
+++ b/browser/components/extensions/schemas/history.json
@@ -85,48 +85,60 @@
             "type": "string",
             "description": "The visit ID of the referrer."
           },
           "transition": {
             "$ref": "TransitionType",
             "description": "The $(topic:transition-types)[transition type] for this visit from its referrer."
           }
         }
+      },
+      {
+        "id": "HistoryTime",
+        "description": "A time specified as a Date object, a number or string representing milliseconds since the epoch, or an ISO 8601 string",
+        "choices": [
+          {
+            "type": "string",
+            "pattern": "^[1-9]\\d*$"
+          },
+          {
+            "$ref": "extensionTypes.Date"
+          }
+        ]
       }
     ],
     "functions": [
       {
         "name": "search",
-        "unsupported": true,
         "type": "function",
         "description": "Searches the history for the last visit time of each page matching the query.",
         "async": "callback",
         "parameters": [
           {
             "name": "query",
             "type": "object",
             "properties": {
               "text": {
                 "type": "string",
                 "description": "A free-text query to the history service.  Leave empty to retrieve all pages."
               },
               "startTime": {
-                "type": "number",
+                "$ref": "HistoryTime",
                 "optional": true,
-                "description": "Limit results to those visited after this date, represented in milliseconds since the epoch. If not specified, this defaults to 24 hours in the past."
+                "description": "Limit results to those visited after this date. If not specified, this defaults to 24 hours in the past."
               },
               "endTime": {
-                "type": "number",
+                "$ref": "HistoryTime",
                 "optional": true,
-                "description": "Limit results to those visited before this date, represented in milliseconds since the epoch."
+                "description": "Limit results to those visited before this date."
               },
               "maxResults": {
                 "type": "integer",
                 "optional": true,
-                "minimum": 0,
+                "minimum": 1,
                 "description": "The maximum number of results to retrieve.  Defaults to 100."
               }
             }
           },
           {
             "name": "callback",
             "type": "function",
             "parameters": [
--- a/browser/components/extensions/test/browser/browser.ini
+++ b/browser/components/extensions/test/browser/browser.ini
@@ -8,16 +8,19 @@ support-files =
   file_popup_api_injection_a.html
   file_popup_api_injection_b.html
   file_iframe_document.html
   file_iframe_document.sjs
   file_bypass_cache.sjs
   file_language_fr_en.html
   file_language_ja.html
   file_dummy.html
+  searchSuggestionEngine.xml
+  searchSuggestionEngine.sjs
+
 
 [browser_ext_browserAction_context.js]
 [browser_ext_browserAction_disabled.js]
 [browser_ext_browserAction_pageAction_icon.js]
 [browser_ext_browserAction_popup.js]
 [browser_ext_browserAction_simple.js]
 [browser_ext_commands_execute_page_action.js]
 [browser_ext_commands_getAll.js]
@@ -60,16 +63,17 @@ support-files =
 [browser_ext_tabs_reload.js]
 [browser_ext_tabs_reload_bypass_cache.js]
 [browser_ext_tabs_sendMessage.js]
 [browser_ext_tabs_update.js]
 [browser_ext_tabs_zoom.js]
 [browser_ext_tabs_update_url.js]
 [browser_ext_topwindowid.js]
 [browser_ext_webNavigation_getFrames.js]
+[browser_ext_webNavigation_urlbar_transitions.js]
 [browser_ext_windows.js]
 [browser_ext_windows_create.js]
 tags = fullscreen
 [browser_ext_windows_create_tabId.js]
 [browser_ext_windows_events.js]
 [browser_ext_windows_size.js]
 skip-if = os == 'mac' # Fails when windows are randomly opened in fullscreen mode
 [browser_ext_windows_update.js]
--- a/browser/components/extensions/test/browser/browser_ext_history.js
+++ b/browser/components/extensions/test/browser/browser_ext_history.js
@@ -44,17 +44,17 @@ add_task(function* test_delete() {
   yield extension.awaitMessage("ready");
 
   let visits = [];
 
   // Add 5 visits for one uri and 3 visits for 3 others
   for (let i = 0; i < 8; ++i) {
     let baseUri = "http://mozilla.com/test_history/";
     let uri = (i > 4) ? `${baseUri}${i}/` : baseUri;
-    let dbDate = (Number(REFERENCE_DATE) + 3600 * 1000 * i) * 1000;
+    let dbDate = PlacesUtils.toPRTime(Number(REFERENCE_DATE) + 3600 * 1000 * i);
 
     let visit = {
       uri,
       title: "visit " + i,
       visitDate: dbDate,
     };
     visits.push(visit);
   }
@@ -66,30 +66,30 @@ add_task(function* test_delete() {
   let testUrl = visits[6].uri.spec;
   ok(yield PlacesTestUtils.isPageInDB(testUrl), "expected url found in history database");
 
   extension.sendMessage("delete-url", testUrl);
   yield extension.awaitMessage("url-deleted");
   is(yield PlacesTestUtils.isPageInDB(testUrl), false, "expected url not found in history database");
 
   let filter = {
-    startTime: visits[1].visitDate / 1000,
-    endTime: visits[3].visitDate / 1000,
+    startTime: PlacesUtils.toTime(visits[1].visitDate),
+    endTime: PlacesUtils.toTime(visits[3].visitDate),
   };
 
   extension.sendMessage("delete-range", filter);
   yield extension.awaitMessage("range-deleted");
 
   ok(yield PlacesTestUtils.isPageInDB(visits[0].uri), "expected uri found in history database");
   is(yield PlacesTestUtils.visitsInDB(visits[0].uri), 2, "2 visits for uri found in history database");
   ok(yield PlacesTestUtils.isPageInDB(visits[5].uri), "expected uri found in history database");
   is(yield PlacesTestUtils.visitsInDB(visits[5].uri), 1, "1 visit for uri found in history database");
 
-  filter.startTime = visits[0].visitDate / 1000;
-  filter.endTime = visits[5].visitDate / 1000;
+  filter.startTime = PlacesUtils.toTime(visits[0].visitDate);
+  filter.endTime = PlacesUtils.toTime(visits[5].visitDate);
 
   extension.sendMessage("delete-range", filter);
   yield extension.awaitMessage("range-deleted");
 
   is(yield PlacesTestUtils.isPageInDB(visits[0].uri), false, "expected uri not found in history database");
   is(yield PlacesTestUtils.visitsInDB(visits[0].uri), 0, "0 visits for uri found in history database");
   is(yield PlacesTestUtils.isPageInDB(visits[5].uri), false, "expected uri not found in history database");
   is(yield PlacesTestUtils.visitsInDB(visits[5].uri), 0, "0 visits for uri found in history database");
@@ -97,8 +97,95 @@ add_task(function* test_delete() {
   ok(yield PlacesTestUtils.isPageInDB(visits[7].uri), "expected uri found in history database");
 
   extension.sendMessage("delete-all");
   yield extension.awaitMessage("urls-deleted");
   is(PlacesUtils.history.hasHistoryEntries, false, "history is empty");
 
   yield extension.unload();
 });
+
+add_task(function* test_search() {
+  const SINGLE_VISIT_URL = "http://example.com/";
+  const DOUBLE_VISIT_URL = "http://example.com/2/";
+  const MOZILLA_VISIT_URL = "http://mozilla.com/";
+
+  function background() {
+    browser.test.onMessage.addListener(msg => {
+      browser.history.search({text: ""}).then(results => {
+        browser.test.sendMessage("empty-search", results);
+        return browser.history.search({text: "mozilla.com"});
+      }).then(results => {
+        browser.test.sendMessage("text-search", results);
+        return browser.history.search({text: "example.com", maxResults: 1});
+      }).then(results => {
+        browser.test.sendMessage("max-results-search", results);
+        return browser.history.search({text: "", startTime: Date.now()});
+      }).then(results => {
+        browser.test.assertEq(0, results.length, "no results returned for late start time");
+        return browser.history.search({text: "", endTime: 0});
+      }).then(results => {
+        browser.test.assertEq(0, results.length, "no results returned for early end time");
+        return browser.history.search({text: "", startTime: Date.now(), endTime: 0});
+      }).then(results => {
+        browser.test.fail("history.search rejects with startTime that is after the endTime");
+      }, error => {
+        browser.test.assertEq(
+          error.message,
+          "The startTime cannot be after the endTime",
+          "history.search rejects with startTime that is after the endTime");
+      }).then(() => {
+        browser.test.notifyPass("search");
+      });
+    });
+
+    browser.test.sendMessage("ready");
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    manifest: {
+      permissions: ["history"],
+    },
+    background: `(${background})()`,
+  });
+
+  function findResult(url, results) {
+    return results.find(r => r.url === url);
+  }
+
+  function checkResult(results, url, expectedCount) {
+    let result = findResult(url, results);
+    isnot(result, null, `history.search result was found for ${url}`);
+    is(result.visitCount, expectedCount, `history.search reports ${expectedCount} visit(s)`);
+    is(result.title, `test visit for ${url}`, "title for search result is correct");
+  }
+
+  yield extension.startup();
+  yield extension.awaitMessage("ready");
+  yield PlacesTestUtils.clearHistory();
+
+  yield PlacesTestUtils.addVisits([
+    {uri: makeURI(MOZILLA_VISIT_URL)},
+    {uri: makeURI(DOUBLE_VISIT_URL)},
+    {uri: makeURI(SINGLE_VISIT_URL)},
+    {uri: makeURI(DOUBLE_VISIT_URL)},
+  ]);
+
+  extension.sendMessage("check-history");
+
+  let results = yield extension.awaitMessage("empty-search");
+  is(results.length, 3, "history.search returned 3 results");
+  checkResult(results, SINGLE_VISIT_URL, 1);
+  checkResult(results, DOUBLE_VISIT_URL, 2);
+  checkResult(results, MOZILLA_VISIT_URL, 1);
+
+  results = yield extension.awaitMessage("text-search");
+  is(results.length, 1, "history.search returned 1 result");
+  checkResult(results, MOZILLA_VISIT_URL, 1);
+
+  results = yield extension.awaitMessage("max-results-search");
+  is(results.length, 1, "history.search returned 1 result");
+  checkResult(results, DOUBLE_VISIT_URL, 2);
+
+  yield extension.awaitFinish("search");
+  yield extension.unload();
+  yield PlacesTestUtils.clearHistory();
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/browser_ext_webNavigation_urlbar_transitions.js
@@ -0,0 +1,261 @@
+/* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
+/* vim: set sts=2 sw=2 et tw=80: */
+"use strict";
+
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesUtils",
+                                  "resource://gre/modules/PlacesUtils.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "PlacesTestUtils",
+                                  "resource://testing-common/PlacesTestUtils.jsm");
+
+const SUGGEST_URLBAR_PREF = "browser.urlbar.suggest.searches";
+const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml";
+
+function* addBookmark(bookmark) {
+  if (bookmark.keyword) {
+    yield PlacesUtils.keywords.insert({
+      keyword: bookmark.keyword,
+      url: bookmark.url,
+    });
+  }
+
+  yield PlacesUtils.bookmarks.insert({
+    parentGuid: PlacesUtils.bookmarks.unfiledGuid,
+    url: bookmark.url,
+    title: bookmark.title,
+  });
+
+  registerCleanupFunction(function* () {
+    yield PlacesUtils.bookmarks.eraseEverything();
+  });
+}
+
+function addSearchEngine(basename) {
+  return new Promise((resolve, reject) => {
+    info("Waiting for engine to be added: " + basename);
+    let url = getRootDirectory(gTestPath) + basename;
+    Services.search.addEngine(url, null, "", false, {
+      onSuccess: (engine) => {
+        info(`Search engine added: ${basename}`);
+        registerCleanupFunction(() => Services.search.removeEngine(engine));
+        resolve(engine);
+      },
+      onError: (errCode) => {
+        ok(false, `addEngine failed with error code ${errCode}`);
+        reject();
+      },
+    });
+  });
+}
+
+function* prepareSearchEngine() {
+  let oldCurrentEngine = Services.search.currentEngine;
+  Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, true);
+  let engine = yield addSearchEngine(TEST_ENGINE_BASENAME);
+  Services.search.currentEngine = engine;
+
+  registerCleanupFunction(function* () {
+    Services.prefs.clearUserPref(SUGGEST_URLBAR_PREF);
+    Services.search.currentEngine = oldCurrentEngine;
+
+    // Make sure the popup is closed for the next test.
+    gURLBar.blur();
+    gURLBar.popup.selectedIndex = -1;
+    gURLBar.popup.hidePopup();
+    ok(!gURLBar.popup.popupOpen, "popup should be closed");
+
+    // Clicking suggestions causes visits to search results pages, so clear that
+    // history now.
+    yield PlacesTestUtils.clearHistory();
+  });
+}
+
+add_task(function* test_webnavigation_urlbar_typed_transitions() {
+  function backgroundScript() {
+    browser.webNavigation.onCommitted.addListener((msg) => {
+      browser.test.assertEq("http://example.com/?q=typed", msg.url,
+                            "Got the expected url");
+      // assert from_address_bar transition qualifier
+      browser.test.assertTrue(msg.transitionQualifiers &&
+                          msg.transitionQualifiers.includes("from_address_bar"),
+                              "Got the expected from_address_bar transitionQualifier");
+      browser.test.assertEq("typed", msg.transitionType,
+                            "Got the expected transitionType");
+      browser.test.notifyPass("webNavigation.from_address_bar.typed");
+    });
+
+    browser.test.sendMessage("ready");
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background: backgroundScript,
+    manifest: {
+      permissions: ["webNavigation"],
+    },
+  });
+
+  yield extension.startup();
+
+  yield extension.awaitMessage("ready");
+
+  gURLBar.focus();
+  gURLBar.textValue = "http://example.com/?q=typed";
+
+  EventUtils.synthesizeKey("VK_RETURN", {altKey: true});
+
+  yield extension.awaitFinish("webNavigation.from_address_bar.typed");
+
+  yield extension.unload();
+  info("extension unloaded");
+});
+
+add_task(function* test_webnavigation_urlbar_bookmark_transitions() {
+  function backgroundScript() {
+    browser.webNavigation.onCommitted.addListener((msg) => {
+      browser.test.assertEq("http://example.com/?q=bookmark", msg.url,
+                            "Got the expected url");
+
+      // assert from_address_bar transition qualifier
+      browser.test.assertTrue(msg.transitionQualifiers &&
+                          msg.transitionQualifiers.includes("from_address_bar"),
+                              "Got the expected from_address_bar transitionQualifier");
+      browser.test.assertEq("auto_bookmark", msg.transitionType,
+                            "Got the expected transitionType");
+      browser.test.notifyPass("webNavigation.from_address_bar.auto_bookmark");
+    });
+
+    browser.test.sendMessage("ready");
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background: backgroundScript,
+    manifest: {
+      permissions: ["webNavigation"],
+    },
+  });
+
+  yield addBookmark({
+    title: "Bookmark To Click",
+    url: "http://example.com/?q=bookmark",
+  });
+
+  yield extension.startup();
+
+  yield extension.awaitMessage("ready");
+
+  gURLBar.focus();
+  gURLBar.value = "Bookmark To Click";
+  gURLBar.controller.startSearch("Bookmark To Click");
+
+  let item;
+
+  yield BrowserTestUtils.waitForCondition(() => {
+    item = gURLBar.popup.richlistbox.getItemAtIndex(1);
+    return item;
+  });
+
+  item.click();
+  yield extension.awaitFinish("webNavigation.from_address_bar.auto_bookmark");
+
+  yield extension.unload();
+  info("extension unloaded");
+});
+
+add_task(function* test_webnavigation_urlbar_keyword_transition() {
+  function backgroundScript() {
+    browser.webNavigation.onCommitted.addListener((msg) => {
+      browser.test.assertEq(`http://example.com/?q=search`, msg.url,
+                            "Got the expected url");
+
+      // assert from_address_bar transition qualifier
+      browser.test.assertTrue(msg.transitionQualifiers &&
+                          msg.transitionQualifiers.includes("from_address_bar"),
+                              "Got the expected from_address_bar transitionQualifier");
+      browser.test.assertEq("keyword", msg.transitionType,
+                            "Got the expected transitionType");
+      browser.test.notifyPass("webNavigation.from_address_bar.keyword");
+    });
+
+    browser.test.sendMessage("ready");
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background: backgroundScript,
+    manifest: {
+      permissions: ["webNavigation"],
+    },
+  });
+
+  yield addBookmark({
+    title: "Test Keyword",
+    url: "http://example.com/?q=%s",
+    keyword: "testkw",
+  });
+
+  yield extension.startup();
+
+  yield extension.awaitMessage("ready");
+
+  gURLBar.focus();
+  gURLBar.value = "testkw search";
+  gURLBar.controller.startSearch("testkw search");
+
+  yield BrowserTestUtils.waitForCondition(() => {
+    return gURLBar.popup.input.controller.matchCount;
+  });
+
+  let item = gURLBar.popup.richlistbox.getItemAtIndex(0);
+  item.click();
+
+  yield extension.awaitFinish("webNavigation.from_address_bar.keyword");
+
+  yield extension.unload();
+  info("extension unloaded");
+});
+
+add_task(function* test_webnavigation_urlbar_search_transitions() {
+  function backgroundScript() {
+    browser.webNavigation.onCommitted.addListener((msg) => {
+      browser.test.assertEq("http://mochi.test:8888/", msg.url,
+                            "Got the expected url");
+
+      // assert from_address_bar transition qualifier
+      browser.test.assertTrue(msg.transitionQualifiers &&
+                          msg.transitionQualifiers.includes("from_address_bar"),
+                              "Got the expected from_address_bar transitionQualifier");
+      browser.test.assertEq("generated", msg.transitionType,
+                            "Got the expected 'generated' transitionType");
+      browser.test.notifyPass("webNavigation.from_address_bar.generated");
+    });
+
+    browser.test.sendMessage("ready");
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background: backgroundScript,
+    manifest: {
+      permissions: ["webNavigation"],
+    },
+  });
+
+  yield extension.startup();
+
+  yield extension.awaitMessage("ready");
+
+  yield prepareSearchEngine();
+
+  gURLBar.focus();
+  gURLBar.value = "foo";
+  gURLBar.controller.startSearch("foo");
+
+  yield BrowserTestUtils.waitForCondition(() => {
+    return gURLBar.popup.input.controller.matchCount;
+  });
+
+  let item = gURLBar.popup.richlistbox.getItemAtIndex(0);
+  item.click();
+
+  yield extension.awaitFinish("webNavigation.from_address_bar.generated");
+
+  yield extension.unload();
+  info("extension unloaded");
+});
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/searchSuggestionEngine.sjs
@@ -0,0 +1,9 @@
+/* Any copyright is dedicated to the Public Domain.
+ * http://creativecommons.org/publicdomain/zero/1.0/ */
+
+function handleRequest(req, resp) {
+  let suffixes = ["foo", "bar"];
+  let data = [req.queryString, suffixes.map(s => req.queryString + s)];
+  resp.setHeader("Content-Type", "application/json", false);
+  resp.write(JSON.stringify(data));
+}
new file mode 100644
--- /dev/null
+++ b/browser/components/extensions/test/browser/searchSuggestionEngine.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Any copyright is dedicated to the Public Domain.
+   - http://creativecommons.org/publicdomain/zero/1.0/ -->
+
+<SearchPlugin xmlns="http://www.mozilla.org/2006/browser/search/">
+<ShortName>browser_searchSuggestionEngine searchSuggestionEngine.xml</ShortName>
+<Url type="application/x-suggestions+json" method="GET" template="http://mochi.test:8888/browser/browser/components/extensions/test/browser/searchSuggestionEngine.sjs?{searchTerms}"/>
+<Url type="text/html" method="GET" template="http://mochi.test:8888/" rel="searchform"/>
+</SearchPlugin>
--- a/browser/components/feeds/FeedWriter.js
+++ b/browser/components/feeds/FeedWriter.js
@@ -209,25 +209,16 @@ FeedWriter.prototype = {
     catch (e) {
       // Not allowed to load this link because secman.checkLoadURIStr threw
       return;
     }
 
     element.setAttribute(attribute, uri);
   },
 
-  __faviconService: null,
-  get _faviconService() {
-    if (!this.__faviconService)
-      this.__faviconService = Cc["@mozilla.org/browser/favicon-service;1"].
-                              getService(Ci.nsIFaviconService);
-
-    return this.__faviconService;
-  },
-
   __bundle: null,
   get _bundle() {
     if (!this.__bundle) {
       this.__bundle = Cc["@mozilla.org/intl/stringbundle;1"].
                       getService(Ci.nsIStringBundleService).
                       createBundle(URI_BUNDLE);
     }
     return this.__bundle;
@@ -1022,17 +1013,16 @@ FeedWriter.prototype = {
     prefs.removeObserver(PREF_VIDEO_SELECTED_APP, this);
 
     prefs.removeObserver(PREF_AUDIO_SELECTED_ACTION, this);
     prefs.removeObserver(PREF_AUDIO_SELECTED_READER, this);
     prefs.removeObserver(PREF_AUDIO_SELECTED_WEB, this);
     prefs.removeObserver(PREF_AUDIO_SELECTED_APP, this);
 
     this._removeFeedFromCache();
-    this.__faviconService = null;
     this.__bundle = null;
     this._feedURI = null;
 
     this._selectedApp = undefined;
     this._selectedAppMenuItem = null;
     this._defaultHandlerMenuItem = null;
   },
 
@@ -1163,62 +1153,16 @@ FeedWriter.prototype = {
         case PREF_SELECTED_ACTION:
         case PREF_VIDEO_SELECTED_ACTION:
         case PREF_AUDIO_SELECTED_ACTION:
           this._setAlwaysUseCheckedState(feedType);
       }
     }
   },
 
-  /**
-   * Sets the icon for the given web-reader item in the readers menu.
-   * The icon is fetched and stored through the favicon service.
-   *
-   * @param aReaderUrl
-   *        the reader url.
-   * @param aMenuItem
-   *        the reader item in the readers menulist.
-   *
-   * @note For privacy reasons we cannot set the image attribute directly
-   *       to the icon url.  See Bug 358878 for details.
-   */
-  _setFaviconForWebReader:
-  function FW__setFaviconForWebReader(aReaderUrl, aMenuItem) {
-    let readerURI = makeURI(aReaderUrl);
-    if (!/^https?$/.test(readerURI.scheme)) {
-      // Don't try to get a favicon for non http(s) URIs.
-      return;
-    }
-    let faviconURI = makeURI(readerURI.prePath + "/favicon.ico");
-    let self = this;
-
-    let docShell = this._window.QueryInterface(Ci.nsIInterfaceRequestor)
-                               .getInterface(Ci.nsIWebNavigation)
-                               .QueryInterface(Ci.nsIDocShell);
-    let usePrivateBrowsing = docShell.QueryInterface(Ci.nsILoadContext)
-                                     .usePrivateBrowsing;
-
-    // We probably need to call InheritFromDocShellToDoc for this, but right now
-    // we can't call it from JS.
-    let attrs = docShell.getOriginAttributes();
-    let ssm = Services.scriptSecurityManager;
-    let nullPrincipal = ssm.createNullPrincipal(attrs);
-
-    this._faviconService.setAndFetchFaviconForPage(readerURI, faviconURI, false,
-      usePrivateBrowsing ? this._faviconService.FAVICON_LOAD_PRIVATE
-                         : this._faviconService.FAVICON_LOAD_NON_PRIVATE,
-      function (aURI, aDataLen, aData, aMimeType) {
-        if (aDataLen > 0) {
-          let dataURL = "data:" + aMimeType + ";base64," +
-                        btoa(String.fromCharCode.apply(null, aData));
-          aMenuItem.setAttribute('image', dataURL);
-        }
-      }, nullPrincipal);
-  },
-
   get _mm() {
     let mm = this._window.QueryInterface(Ci.nsIInterfaceRequestor).
                           getInterface(Ci.nsIDocShell).
                           QueryInterface(Ci.nsIInterfaceRequestor).
                           getInterface(Ci.nsIContentFrameMessageManager);
     delete this._mm;
     return this._mm = mm;
   },
--- a/browser/components/feeds/moz.build
+++ b/browser/components/feeds/moz.build
@@ -34,11 +34,8 @@ for var in ('MOZ_APP_NAME', 'MOZ_MACBUND
     DEFINES[var] = CONFIG[var]
 
 LOCAL_INCLUDES += [
     '../build',
 ]
 
 with Files('**'):
     BUG_COMPONENT = ('Firefox', 'RSS Discovery and Preview')
-
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wshadow']
--- a/browser/components/migration/FirefoxProfileMigrator.js
+++ b/browser/components/migration/FirefoxProfileMigrator.js
@@ -24,16 +24,18 @@ XPCOMUtils.defineLazyModuleGetter(this, 
 XPCOMUtils.defineLazyModuleGetter(this, "SessionMigration",
                                   "resource:///modules/sessionstore/SessionMigration.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "OS",
                                   "resource://gre/modules/osfile.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "FileUtils",
                                   "resource://gre/modules/FileUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "ProfileAge",
                                   "resource://gre/modules/ProfileAge.jsm");
+XPCOMUtils.defineLazyModuleGetter(this, "AppConstants",
+                                  "resource://gre/modules/AppConstants.jsm");
 
 
 function FirefoxProfileMigrator() {
   this.wrappedJSObject = this; // for testing...
 }
 
 FirefoxProfileMigrator.prototype = Object.create(MigratorPrototype);
 
@@ -143,16 +145,21 @@ FirefoxProfileMigrator.prototype._getRes
           let buildID = Services.appinfo.platformBuildID;
           let mstone = Services.appinfo.platformVersion;
           // Force the browser to one-off resume the session that we give it:
           Services.prefs.setBoolPref("browser.sessionstore.resume_session_once", true);
           // Reset the homepage_override prefs so that the browser doesn't override our
           // session with the "what's new" page:
           Services.prefs.setCharPref("browser.startup.homepage_override.mstone", mstone);
           Services.prefs.setCharPref("browser.startup.homepage_override.buildID", buildID);
+          // Also set the Windows 10 pref to avoid the win10 intro page to show up
+          // on startup.
+          if (AppConstants.isPlatformAndVersionAtLeast("win", "10")) {
+            Services.prefs.setBoolPref("browser.usedOnWindows10", true);
+          }
           // It's too early in startup for the pref service to have a profile directory,
           // so we have to manually tell it where to save the prefs file.
           let newPrefsFile = currentProfileDir.clone();
           newPrefsFile.append("prefs.js");
           Services.prefs.savePrefFile(newPrefsFile);
           aCallback(true);
         }, function() {
           aCallback(false);
--- a/browser/components/migration/moz.build
+++ b/browser/components/migration/moz.build
@@ -1,16 +1,18 @@
 # -*- Mode: python; c-basic-offset: 4; indent-tabs-mode: nil; tab-width: 40 -*-
 # vim: set filetype=python:
 # 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/.
 
 XPCSHELL_TESTS_MANIFESTS += ['tests/unit/xpcshell.ini']
 
+MARIONETTE_UNIT_MANIFESTS += ['tests/marionette/manifest.ini']
+
 JAR_MANIFESTS += ['jar.mn']
 
 XPIDL_SOURCES += [
     'nsIBrowserProfileMigrator.idl',
 ]
 
 XPIDL_MODULE = 'migration'
 
new file mode 100644
--- /dev/null
+++ b/browser/components/migration/tests/marionette/manifest.ini
@@ -0,0 +1,5 @@
+[DEFAULT]
+run-if = buildapp == 'browser'
+
+[test_refresh_firefox.py]
+
new file mode 100644
--- /dev/null
+++ b/browser/components/migration/tests/marionette/test_refresh_firefox.py
@@ -0,0 +1,407 @@
+import os, shutil
+from marionette import MarionetteTestCase
+
+
+class TestFirefoxRefresh(MarionetteTestCase):
+    _username = "marionette-test-login"
+    _password = "marionette-test-password"
+    _bookmarkURL = "about:mozilla"
+    _bookmarkText = "Some bookmark from Marionette"
+
+    _cookieHost = "firefox-refresh.marionette-test.mozilla.org"
+    _cookiePath = "some/cookie/path"
+    _cookieName = "somecookie"
+    _cookieValue = "some cookie value"
+
+    _historyURL = "http://firefox-refresh.marionette-test.mozilla.org/"
+    _historyTitle = "Test visit for Firefox Reset"
+
+    _formHistoryFieldName = "some-very-unique-marionette-only-firefox-reset-field"
+    _formHistoryValue = "special-pumpkin-value"
+
+    _expectedURLs = ["about:robots", "about:mozilla"]
+
+    def savePassword(self):
+        self.runCode("""
+          let myLogin = new global.LoginInfo(
+            "test.marionette.mozilla.com",
+            "http://test.marionette.mozilla.com/some/form/",
+            null,
+            arguments[0],
+            arguments[1],
+            "username",
+            "password"
+          );
+          Services.logins.addLogin(myLogin)
+        """, script_args=[self._username, self._password])
+
+    def createBookmark(self):
+        self.marionette.execute_script("""
+          let url = arguments[0];
+          let title = arguments[1];
+          PlacesUtils.bookmarks.insertBookmark(PlacesUtils.bookmarks.bookmarksMenuFolder,
+            makeURI(url), 0, title);
+        """, script_args=[self._bookmarkURL, self._bookmarkText])
+
+    def createHistory(self):
+        error = self.runAsyncCode("""
+          // Copied from PlacesTestUtils, which isn't available in Marionette tests.
+          let didReturn;
+          PlacesUtils.asyncHistory.updatePlaces(
+            [{title: arguments[1], uri: makeURI(arguments[0]), visits: [{
+                transitionType: Ci.nsINavHistoryService.TRANSITION_LINK,
+                visitDate: (Date.now() - 5000) * 1000,
+                referrerURI: makeURI("about:mozilla"),
+              }]
+            }],
+            {
+              handleError(resultCode, place) {
+                didReturn = true;
+                marionetteScriptFinished("Unexpected error in adding visit: " + resultCode);
+              },
+              handleResult() {},
+              handleCompletion() {
+                if (!didReturn) {
+                  marionetteScriptFinished(false);
+                }
+              },
+            }
+          );
+        """, script_args=[self._historyURL, self._historyTitle])
+        if error:
+            print error
+
+    def createFormHistory(self):
+        error = self.runAsyncCode("""
+          let updateDefinition = {
+            op: "add",
+            fieldname: arguments[0],
+            value: arguments[1],
+            firstUsed: (Date.now() - 5000) * 1000,
+          };
+          let finished = false;
+          global.FormHistory.update(updateDefinition, {
+            handleError(error) {
+              finished = true;
+              marionetteScriptFinished(error);
+            },
+            handleCompletion() {
+              if (!finished) {
+                marionetteScriptFinished(false);
+              }
+            }
+          });
+        """, script_args=[self._formHistoryFieldName, self._formHistoryValue])
+        if error:
+          print error
+
+    def createCookie(self):
+        self.runCode("""
+          // Expire in 15 minutes:
+          let expireTime = Math.floor(Date.now() / 1000) + 15 * 60;
+          Services.cookies.add(arguments[0], arguments[1], arguments[2], arguments[3],
+                               true, false, false, expireTime);
+        """, script_args=[self._cookieHost, self._cookiePath, self._cookieName, self._cookieValue])
+
+    def createSession(self):
+        self.runAsyncCode("""
+          const COMPLETE_STATE = Ci.nsIWebProgressListener.STATE_STOP +
+                                 Ci.nsIWebProgressListener.STATE_IS_NETWORK;
+          let {TabStateFlusher} = Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
+          let expectedURLs = Array.from(arguments[0])
+          gBrowser.addTabsProgressListener({
+            onStateChange(browser, webprogress, request, flags, status) {
+              try {
+                request && request.QueryInterface(Ci.nsIChannel);
+              } catch (ex) {}
+              let uriLoaded = request.originalURI && request.originalURI.spec;
+              if ((flags & COMPLETE_STATE == COMPLETE_STATE) && uriLoaded &&
+                  expectedURLs.includes(uriLoaded)) {
+                TabStateFlusher.flush(browser).then(function() {
+                  expectedURLs.splice(expectedURLs.indexOf(uriLoaded), 1);
+                  if (!expectedURLs.length) {
+                    gBrowser.removeTabsProgressListener(this);
+                    marionetteScriptFinished();
+                  }
+                });
+              }
+            }
+          });
+          for (let url of expectedURLs) {
+            gBrowser.addTab(url);
+          }
+        """, script_args=[self._expectedURLs])
+
+    def checkPassword(self):
+        loginInfo = self.marionette.execute_script("""
+          let ary = Services.logins.findLogins({},
+            "test.marionette.mozilla.com",
+            "http://test.marionette.mozilla.com/some/form/",
+            null, {});
+          return ary.length ? ary : {username: "null", password: "null"};
+        """)
+        self.assertEqual(len(loginInfo), 1)
+        self.assertEqual(loginInfo[0]['username'], self._username)
+        self.assertEqual(loginInfo[0]['password'], self._password)
+
+        loginCount = self.marionette.execute_script("""
+          return Services.logins.getAllLogins().length;
+        """)
+        self.assertEqual(loginCount, 1, "No other logins are present")
+
+    def checkBookmark(self):
+        titleInBookmarks = self.marionette.execute_script("""
+          let url = arguments[0];
+          let bookmarkIds = PlacesUtils.bookmarks.getBookmarkIdsForURI(makeURI(url), {}, {});
+          return bookmarkIds.length == 1 ? PlacesUtils.bookmarks.getItemTitle(bookmarkIds[0]) : "";
+        """, script_args=[self._bookmarkURL])
+        self.assertEqual(titleInBookmarks, self._bookmarkText)
+
+    def checkHistory(self):
+        historyResults = self.runAsyncCode("""
+          let placeInfos = [];
+          PlacesUtils.asyncHistory.getPlacesInfo(makeURI(arguments[0]), {
+            handleError(resultCode, place) {
+              placeInfos = null;
+              marionetteScriptFinished("Unexpected error in fetching visit: " + resultCode);
+            },
+            handleResult(placeInfo) {
+              placeInfos.push(placeInfo);
+            },
+            handleCompletion() {
+              if (placeInfos) {
+                if (!placeInfos.length) {
+                  marionetteScriptFinished("No visits found");
+                } else {
+                  marionetteScriptFinished(placeInfos);
+                }
+              }
+            },
+          });
+        """, script_args=[self._historyURL])
+        if type(historyResults) == str:
+            self.fail(historyResults)
+            return
+
+        historyCount = len(historyResults)
+        self.assertEqual(historyCount, 1, "Should have exactly 1 entry for URI, got %d" % historyCount)
+        if historyCount == 1:
+            self.assertEqual(historyResults[0]['title'], self._historyTitle)
+
+    def checkFormHistory(self):
+        formFieldResults = self.runAsyncCode("""
+          let results = [];
+          global.FormHistory.search(["value"], {fieldname: arguments[0]}, {
+            handleError(error) {
+              results = error;
+            },
+            handleResult(result) {
+              results.push(result);
+            },
+            handleCompletion() {
+              marionetteScriptFinished(results);
+            },
+          });
+        """, script_args=[self._formHistoryFieldName])
+        if type(formFieldResults) == str:
+            self.fail(formFieldResults)
+            return
+
+        formFieldResultCount = len(formFieldResults)
+        self.assertEqual(formFieldResultCount, 1, "Should have exactly 1 entry for this field, got %d" % formFieldResultCount)
+        if formFieldResultCount == 1:
+            self.assertEqual(formFieldResults[0]['value'], self._formHistoryValue)
+
+        formHistoryCount = self.runAsyncCode("""
+          let count;
+          let callbacks = {
+            handleResult: rv => count = rv,
+            handleCompletion() {
+              marionetteScriptFinished(count);
+            },
+          };
+          global.FormHistory.count({}, callbacks);
+        """)
+        self.assertEqual(formHistoryCount, 1, "There should be only 1 entry in the form history")
+
+    def checkCookie(self):
+        cookieInfo = self.runCode("""
+          try {
+            let cookieEnum = Services.cookies.getCookiesFromHost(arguments[0]);
+            let cookie = null;
+            while (cookieEnum.hasMoreElements()) {
+              if (cookie != null) {
+                return "more than 1 cookie! That shouldn't happen!";
+              }
+              cookie = cookieEnum.getNext();
+              cookie.QueryInterface(Ci.nsICookie2);
+            }
+            return {path: cookie.path, name: cookie.name, value: cookie.value};
+          } catch (ex) {
+            return "got exception trying to fetch cookie: " + ex;
+          }
+        """, script_args=[self._cookieHost])
+        self.assertEqual(cookieInfo['path'], self._cookiePath)
+        self.assertEqual(cookieInfo['value'], self._cookieValue)
+        self.assertEqual(cookieInfo['name'], self._cookieName)
+
+    def checkSession(self):
+        tabURIs = self.runCode("""
+          return [... gBrowser.browsers].map(b => b.currentURI && b.currentURI.spec)
+        """)
+        self.assertSequenceEqual(tabURIs, ["about:welcomeback"])
+
+        tabURIs = self.runAsyncCode("""
+          let mm = gBrowser.selectedBrowser.messageManager;
+          let fs = function() {
+            content.document.getElementById("errorTryAgain").click();
+          };
+          let {TabStateFlusher} = Cu.import("resource:///modules/sessionstore/TabStateFlusher.jsm", {});
+          window.addEventListener("SSWindowStateReady", function testSSPostReset() {
+            window.removeEventListener("SSWindowStateReady", testSSPostReset, false);
+            Promise.all(gBrowser.browsers.map(b => TabStateFlusher.flush(b))).then(function() {
+              marionetteScriptFinished([... gBrowser.browsers].map(b => b.currentURI && b.currentURI.spec));
+            });
+          }, false);
+          mm.loadFrameScript("data:application/javascript,(" + fs.toString() + ")()", true);
+        """)
+        self.assertSequenceEqual(tabURIs, ["about:blank"] + self._expectedURLs)
+        pass
+
+    def checkProfile(self, hasMigrated=False):
+        self.checkPassword()
+        self.checkBookmark()
+        self.checkHistory()
+        self.checkFormHistory()
+        self.checkCookie()
+        if hasMigrated:
+            self.checkSession()
+
+    def createProfileData(self):
+        self.savePassword()
+        self.createBookmark()
+        self.createHistory()
+        self.createFormHistory()
+        self.createCookie()
+        self.createSession()
+
+    def setUpScriptData(self):
+        self.marionette.set_context(self.marionette.CONTEXT_CHROME)
+        self.marionette.execute_script("""
+          global.LoginInfo = Components.Constructor("@mozilla.org/login-manager/loginInfo;1", "nsILoginInfo", "init");
+          global.profSvc = Cc["@mozilla.org/toolkit/profile-service;1"].getService(Ci.nsIToolkitProfileService);
+          global.Preferences = Cu.import("resource://gre/modules/Preferences.jsm", {}).Preferences;
+          global.FormHistory = Cu.import("resource://gre/modules/FormHistory.jsm", {}).FormHistory;
+        """, new_sandbox=False, sandbox='system')
+
+    def runCode(self, script, *args, **kwargs):
+        return self.marionette.execute_script(script, new_sandbox=False, sandbox='system', *args, **kwargs)
+
+    def runAsyncCode(self, script, *args, **kwargs):
+        return self.marionette.execute_async_script(script, new_sandbox=False, sandbox='system', *args, **kwargs)
+
+    def setUp(self):
+        MarionetteTestCase.setUp(self)
+        self.setUpScriptData()
+
+        self.reset_profile_path = None
+        self.desktop_backup_path = None
+
+        self.createProfileData()
+
+    def tearDown(self):
+        # Force yet another restart with a clean profile to disconnect from the
+        # profile and environment changes we've made, to leave a more or less
+        # blank slate for the next person.
+        self.marionette.restart(clean=True, in_app=False)
+        self.setUpScriptData()
+
+        # Super
+        MarionetteTestCase.tearDown(self)
+
+        # Some helpers to deal with removing a load of files
+        import errno, stat
+        def handleRemoveReadonly(func, path, exc):
+            excvalue = exc[1]
+            if func in (os.rmdir, os.remove) and excvalue.errno == errno.EACCES:
+                os.chmod(path, stat.S_IRWXU| stat.S_IRWXG| stat.S_IRWXO) # 0777
+                func(path)
+            else:
+                raise
+
+        if self.desktop_backup_path:
+            shutil.rmtree(self.desktop_backup_path, ignore_errors=False, onerror=handleRemoveReadonly)
+
+        if self.reset_profile_path:
+            # Remove ourselves from profiles.ini
+            profileLeafName = os.path.basename(os.path.normpath(self.reset_profile_path))
+            self.runCode("""
+              let [salt, name] = arguments[0].split(".");
+              let profile = global.profSvc.getProfileByName(name);
+              profile.remove(false)
+              global.profSvc.flush();
+            """, script_args=[profileLeafName])
+            # And delete all the files.
+            shutil.rmtree(self.reset_profile_path, ignore_errors=False, onerror=handleRemoveReadonly)
+
+    def doReset(self):
+        self.runCode("""
+          // Ensure the current (temporary) profile is in profiles.ini:
+          let profD = Services.dirsvc.get("ProfD", Ci.nsIFile);
+          let profileName = "marionette-test-profile-" + Date.now();
+          let myProfile = global.profSvc.createProfile(profD, profileName);
+          global.profSvc.flush()
+
+          // Now add the reset parameters:
+          let env = Cc["@mozilla.org/process/environment;1"].getService(Ci.nsIEnvironment);
+          let allMarionettePrefs = Services.prefs.getChildList("marionette.");
+          let prefObj = {};
+          for (let pref of allMarionettePrefs) {
+            let prefSuffix = pref.substr("marionette.".length);
+            let prefVal = global.Preferences.get(pref);
+            prefObj[prefSuffix] = prefVal;
+          }
+          let marionetteInfo = JSON.stringify(prefObj);
+          env.set("MOZ_MARIONETTE_PREF_STATE_ACROSS_RESTARTS", marionetteInfo);
+          env.set("MOZ_RESET_PROFILE_RESTART", "1");
+          env.set("XRE_PROFILE_PATH", arguments[0]);
+          env.set("XRE_PROFILE_NAME", profileName);
+        """, script_args=[self.marionette.instance.profile.profile])
+
+        profileLeafName = os.path.basename(os.path.normpath(self.marionette.instance.profile.profile))
+
+        # Now restart the browser to get it reset:
+        self.marionette.restart(clean=False, in_app=True)
+        self.setUpScriptData()
+
+        # Determine the new profile path (we'll need to remove it when we're done)
+        self.reset_profile_path = self.runCode("""
+          let profD = Services.dirsvc.get("ProfD", Ci.nsIFile);
+          return profD.path;
+        """)
+
+        # Determine the backup path
+        self.desktop_backup_path = self.runCode("""
+          let container;
+          try {
+            container = Services.dirsvc.get("Desk", Ci.nsIFile);
+          } catch (ex) {
+            container = Services.dirsvc.get("Home", Ci.nsIFile);
+          }
+          let bundle = Services.strings.createBundle("chrome://mozapps/locale/profile/profileSelection.properties");
+          let dirName = bundle.formatStringFromName("resetBackupDirectory", [Services.appinfo.name], 1);
+          container.append(dirName);
+          container.append(arguments[0]);
+          return container.path;
+        """, script_args = [profileLeafName])
+
+        self.assertTrue(os.path.isdir(self.reset_profile_path), "Reset profile path should be present")
+        self.assertTrue(os.path.isdir(self.desktop_backup_path), "Backup profile path should be present")
+
+    def testReset(self):
+        self.checkProfile()
+
+        self.doReset()
+
+        # Now check that we're doing OK...
+        self.checkProfile(hasMigrated=True)
--- a/browser/components/newtab/tests/browser/browser.ini
+++ b/browser/components/newtab/tests/browser/browser.ini
@@ -7,9 +7,10 @@ support-files =
   newtabmessages_prefs.html
   newtabmessages_preview.html
   newtabmessages_search.html
 
 [browser_PreviewProvider.js]
 [browser_remotenewtab_pageloads.js]
 [browser_newtab_overrides.js]
 [browser_newtabmessages.js]
+skip-if = true # Bug 1271177, bug 1262719
 [browser_newtabwebchannel.js]
--- a/browser/components/nsBrowserGlue.js
+++ b/browser/components/nsBrowserGlue.js
@@ -112,21 +112,16 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/LoginHelper.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "SimpleServiceDiscovery",
                                   "resource://gre/modules/SimpleServiceDiscovery.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "ContentSearch",
                                   "resource:///modules/ContentSearch.jsm");
 
-if (AppConstants.E10S_TESTING_ONLY) {
-  XPCOMUtils.defineLazyModuleGetter(this, "UpdateUtils",
-                                    "resource://gre/modules/UpdateUtils.jsm");
-}
-
 XPCOMUtils.defineLazyModuleGetter(this, "TabCrashHandler",
                                   "resource:///modules/ContentCrashHandlers.jsm");
 if (AppConstants.MOZ_CRASHREPORTER) {
   XPCOMUtils.defineLazyModuleGetter(this, "PluginCrashReporter",
                                     "resource:///modules/ContentCrashHandlers.jsm");
 }
 
 XPCOMUtils.defineLazyGetter(this, "gBrandBundle", function() {
@@ -378,17 +373,24 @@ BrowserGlue.prototype = {
       case "initial-migration-did-import-default-bookmarks":
         this._initPlaces(true);
         break;
       case "handle-xul-text-link":
         let linkHandled = subject.QueryInterface(Ci.nsISupportsPRBool);
         if (!linkHandled.data) {
           let win = RecentWindow.getMostRecentBrowserWindow();
           if (win) {
-            win.openUILinkIn(data, "tab");
+            data = JSON.parse(data);
+            let where = win.whereToOpenLink(data);
+            // Preserve legacy behavior of non-modifier left-clicks
+            // opening in a new selected tab.
+            if (where == "current") {
+              where = "tab";
+            }
+            win.openUILinkIn(data.href, where);
             linkHandled.data = true;
           }
         }
         break;
       case "profile-before-change":
          // Any component depending on Places should be finalized in
          // _onPlacesShutdown.  Any component that doesn't need to act after
          // the UI has gone should be finalized in _onQuitApplicationGranted.
@@ -1269,19 +1271,16 @@ BrowserGlue.prototype = {
 
       if (willPrompt) {
         Services.tm.mainThread.dispatch(function() {
           DefaultBrowserCheck.prompt(RecentWindow.getMostRecentBrowserWindow());
         }.bind(this), Ci.nsIThread.DISPATCH_NORMAL);
       }
     }
 
-    if (AppConstants.E10S_TESTING_ONLY) {
-      E10SUINotification.checkStatus();
-    }
     if (AppConstants.platform == "win" ||
         AppConstants.platform == "macosx") {
       // Handles prompting to inform about incompatibilites when accessibility
       // and e10s are active together.
       E10SAccessibilityCheck.init();
     }
   },
 
@@ -2991,164 +2990,16 @@ var DefaultBrowserCheck = {
       let popup = doc.getElementById(this.OPTIONPOPUP);
       popup.removeEventListener("command", this);
       popup.remove();
       delete this._notification;
     }
   },
 };
 
-var E10SUINotification = {
-  CURRENT_PROMPT_PREF: "browser.displayedE10SPrompt.1",
-  PREVIOUS_PROMPT_PREF: "browser.displayedE10SPrompt",
-
-  get forcedOn() {
-    try {
-      return Services.prefs.getBoolPref("browser.tabs.remote.force-enable");
-    } catch (e) {}
-    return false;
-  },
-
-  get a11yRecentlyRan() {
-    try {
-      if (Services.prefs.getBoolPref("accessibility.loadedInLastSession")) {
-        return true;
-      }
-    } catch (e) {}
-    try {
-      Services.prefs.getBoolPref("accessibility.lastLoadDate");
-      return true;
-    } catch (e) {}
-    return false;
-  },
-
-  checkStatus: function() {
-    let updateChannel = UpdateUtils.UpdateChannel;
-    let channelAuthorized = updateChannel == "nightly" || updateChannel == "aurora";
-    if (!channelAuthorized) {
-      return;
-    }
-
-    if (!Services.appinfo.browserTabsRemoteAutostart) {
-      let displayFeedbackRequest = false;
-      try {
-        displayFeedbackRequest = Services.prefs.getBoolPref("browser.requestE10sFeedback");
-      } catch (e) {}
-
-      if (displayFeedbackRequest) {
-        let win = RecentWindow.getMostRecentBrowserWindow();
-        if (!win) {
-          return;
-        }
-
-        Services.prefs.clearUserPref("browser.requestE10sFeedback");
-
-        let url = Services.urlFormatter.formatURLPref("app.feedback.baseURL");
-        url += "?utm_source=tab&utm_campaign=e10sfeedback";
-
-        win.openUILinkIn(url, "tab");
-        return;
-      }
-
-      // If accessibility recently ran, don't prompt about trying out e10s
-      if (this.a11yRecentlyRan) {
-        return;
-      }
-
-      let e10sPromptShownCount = 0;
-      try {
-        e10sPromptShownCount = Services.prefs.getIntPref(this.CURRENT_PROMPT_PREF);
-      } catch(e) {}
-
-      let isHardwareAccelerated = true;
-      // Linux and Windows are currently ok, mac not so much.
-      if (AppConstants.platform == "macosx") {
-        try {
-          let win = RecentWindow.getMostRecentBrowserWindow();
-          let winutils = win.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowUtils);
-          isHardwareAccelerated = winutils.layerManagerType != "Basic";
-        } catch (e) {}
-      }
-
-      if (!Services.appinfo.inSafeMode &&
-          !Services.appinfo.accessibilityEnabled &&
-          isHardwareAccelerated &&
-          e10sPromptShownCount < 5) {
-        Services.tm.mainThread.dispatch(() => {
-          try {
-            this._showE10SPrompt();
-            Services.prefs.setIntPref(this.CURRENT_PROMPT_PREF, e10sPromptShownCount + 1);
-            Services.prefs.clearUserPref(this.PREVIOUS_PROMPT_PREF);
-          } catch (ex) {
-            Cu.reportError("Failed to show e10s prompt: " + ex);
-          }
-        }, Ci.nsIThread.DISPATCH_NORMAL);
-      }
-    }
-  },
-
-  QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
-
-  _showE10SPrompt: function BG__showE10SPrompt() {
-    let win = RecentWindow.getMostRecentBrowserWindow();
-    if (!win)
-      return;
-
-    let browser = win.gBrowser.selectedBrowser;
-
-    let promptMessage = win.gNavigatorBundle.getFormattedString(
-                          "e10s.offerPopup.mainMessage",
-                          [gBrandBundle.GetStringFromName("brandShortName")]
-                        );
-    let mainAction = {
-      label: win.gNavigatorBundle.getString("e10s.offerPopup.enableAndRestart.label"),
-      accessKey: win.gNavigatorBundle.getString("e10s.offerPopup.enableAndRestart.accesskey"),
-      callback: function () {
-        Services.prefs.setBoolPref("browser.tabs.remote.autostart", true);
-        Services.prefs.setBoolPref("browser.enabledE10SFromPrompt", true);
-        // Restart the app
-        let cancelQuit = Cc["@mozilla.org/supports-PRBool;1"].createInstance(Ci.nsISupportsPRBool);
-        Services.obs.notifyObservers(cancelQuit, "quit-application-requested", "restart");
-        if (cancelQuit.data)
-          return; // somebody canceled our quit request
-        Services.startup.quit(Services.startup.eAttemptQuit | Services.startup.eRestart);
-      }
-    };
-    let secondaryActions = [
-      {
-        label: win.gNavigatorBundle.getString("e10s.offerPopup.noThanks.label"),
-        accessKey: win.gNavigatorBundle.getString("e10s.offerPopup.noThanks.accesskey"),
-        callback: function () {
-          Services.prefs.setIntPref(E10SUINotification.CURRENT_PROMPT_PREF, 5);
-        }
-      }
-    ];
-    let options = {
-      popupIconURL: "chrome://browser/skin/e10s-64@2x.png",
-      learnMoreURL: "https://wiki.mozilla.org/Electrolysis",
-      persistWhileVisible: true
-    };
-
-    win.PopupNotifications.show(browser, "enable-e10s", promptMessage, null, mainAction, secondaryActions, options);
-
-    let highlights = [
-      win.gNavigatorBundle.getString("e10s.offerPopup.highlight1"),
-      win.gNavigatorBundle.getString("e10s.offerPopup.highlight2")
-    ];
-
-    let doorhangerExtraContent = win.document.getElementById("enable-e10s-notification")
-                                             .querySelector("popupnotificationcontent");
-    for (let highlight of highlights) {
-      let highlightLabel = win.document.createElement("label");
-      highlightLabel.setAttribute("value", highlight);
-      doorhangerExtraContent.appendChild(highlightLabel);
-    }
-  }
-};
-
 var E10SAccessibilityCheck = {
   init: function() {
     Services.obs.addObserver(this, "a11y-init-or-shutdown", true);
     Services.obs.addObserver(this, "quit-application-granted", true);
   },
 
   QueryInterface: XPCOMUtils.generateQI([Ci.nsIObserver, Ci.nsISupportsWeakReference]),
 
--- a/browser/components/places/PlacesUIUtils.jsm
+++ b/browser/components/places/PlacesUIUtils.jsm
@@ -7,16 +7,17 @@ this.EXPORTED_SYMBOLS = ["PlacesUIUtils"
 
 var Ci = Components.interfaces;
 var Cc = Components.classes;
 var Cr = Components.results;
 var Cu = Components.utils;
 
 Cu.import("resource://gre/modules/XPCOMUtils.jsm");
 Cu.import("resource://gre/modules/Services.jsm");
+Cu.import("resource://gre/modules/Timer.jsm");
 
 Cu.import("resource://gre/modules/PlacesUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PluralForm",
                                   "resource://gre/modules/PluralForm.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "PrivateBrowsingUtils",
                                   "resource://gre/modules/PrivateBrowsingUtils.jsm");
 XPCOMUtils.defineLazyModuleGetter(this, "NetUtil",
                                   "resource://gre/modules/NetUtil.jsm");
@@ -32,16 +33,21 @@ XPCOMUtils.defineLazyModuleGetter(this, 
                                   "resource://gre/modules/PlacesTransactions.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "CloudSync",
                                   "resource://gre/modules/CloudSync.jsm");
 
 XPCOMUtils.defineLazyModuleGetter(this, "Weave",
                                   "resource://services-sync/main.js");
 
+const gInContentProcess = Services.appinfo.processType == Ci.nsIXULRuntime.PROCESS_TYPE_CONTENT;
+const FAVICON_REQUEST_TIMEOUT = 60 * 1000;
+// Map from windows to arrays of data about pending favicon loads.
+let gFaviconLoadDataMap = new Map();
+
 // copied from utilityOverlay.js
 const TAB_DROP_TYPE = "application/x-moz-tabbrowser-tab";
 
 // This function isn't public both because it's synchronous and because it is
 // going to be removed in bug 1072833.
 function IsLivemark(aItemId) {
   // Since this check may be done on each dragover event, it's worth maintaining
   // a cache.
@@ -72,16 +78,159 @@ function IsLivemark(aItemId) {
     PlacesUtils.annotations.addObserver(obs);
     PlacesUtils.registerShutdownFunction(() => {
       PlacesUtils.annotations.removeObserver(obs);
     });
   }
   return self.ids.has(aItemId);
 }
 
+let InternalFaviconLoader = {
+  /**
+   * This gets called for every inner window that is destroyed.
+   * In the parent process, we process the destruction ourselves. In the child process,
+   * we notify the parent which will then process it based on that message.
+   */
+  observe(subject, topic, data) {
+    let innerWindowID = subject.QueryInterface(Ci.nsISupportsPRUint64).data;
+    this.onInnerDestroyed(innerWindowID);
+  },
+
+  /**
+   * Actually cancel the request, and clear the timeout for cancelling it.
+   */
+  _cancelRequest({uri, innerWindowID, timerID, callback}, reason) {
+    // Break cycle
+    let request = callback.request;
+    delete callback.request;
+    // Ensure we don't time out.
+    clearTimeout(timerID);
+    try {
+      request.cancel();
+    } catch (ex) {
+      Cu.reportError("When cancelling a request for " + uri.spec + " because " + reason + ", it was already canceled!");
+    }
+  },
+
+  /**
+   * Called for every inner that gets destroyed, only in the parent process.
+   */
+  onInnerDestroyed(innerID) {
+    for (let [window, loadDataForWindow] of gFaviconLoadDataMap) {
+      let newLoadDataForWindow = loadDataForWindow.filter(loadData => {
+        let innerWasDestroyed = loadData.innerWindowID == innerID;
+        if (innerWasDestroyed) {
+          this._cancelRequest(loadData, "the inner window was destroyed");
+        }
+        // Keep the items whose inner is still alive.
+        return !innerWasDestroyed;
+      });
+      // Map iteration with for...of is safe against modification, so
+      // now just replace the old value:
+      gFaviconLoadDataMap.set(window, newLoadDataForWindow);
+    }
+  },
+
+  /**
+   * Called when a toplevel chrome window unloads. We use this to tidy up after ourselves,
+   * avoid leaks, and cancel any remaining requests. The last part should in theory be
+   * handled by the inner-window-destroyed handlers. We clean up just to be on the safe side.
+   */
+  onUnload(win) {
+    let loadDataForWindow = gFaviconLoadDataMap.get(win);
+    if (loadDataForWindow) {
+      for (let loadData of loadDataForWindow) {
+        this._cancelRequest(loadData, "the chrome window went away");
+      }
+    }
+    gFaviconLoadDataMap.delete(win);
+  },
+
+  /**
+   * Create a function to use as a nsIFaviconDataCallback, so we can remove cancelling
+   * information when the request succeeds. Note that right now there are some edge-cases,
+   * such as about: URIs with chrome:// favicons where the success callback is not invoked.
+   * This is OK: we will 'cancel' the request after the timeout (or when the window goes
+   * away) but that will be a no-op in such cases.
+   */
+  _makeCompletionCallback(win, id) {
+    return {
+      onComplete(uri) {
+        let loadDataForWindow = gFaviconLoadDataMap.get(win);
+        if (loadDataForWindow) {
+          let itemIndex = loadDataForWindow.findIndex(loadData => {
+            return loadData.innerWindowID == id &&
+                   loadData.uri.equals(uri) &&
+                   loadData.callback.request == this.request;
+          });
+          if (itemIndex != -1) {
+            let loadData = loadDataForWindow[itemIndex];
+            clearTimeout(loadData.timerID);
+            loadDataForWindow.splice(itemIndex, 1);
+          }
+        }
+        delete this.request;
+      },
+    };
+  },
+
+  ensureInitialized() {
+    if (this._initialized) {
+      return;
+    }
+    this._initialized = true;
+
+    Services.obs.addObserver(this, "inner-window-destroyed", false);
+    Services.ppmm.addMessageListener("Toolkit:inner-window-destroyed", msg => {
+      this.onInnerDestroyed(msg.data);
+    });
+  },
+
+  loadFavicon(browser, principal, uri) {
+    this.ensureInitialized();
+    let win = browser.ownerDocument.defaultView;
+    if (!gFaviconLoadDataMap.has(win)) {
+      gFaviconLoadDataMap.set(win, []);
+      let unloadHandler = event => {
+        let doc = event.target;
+        let eventWin = doc.defaultview;
+        if (win == win.top && doc.documentURI != "about:blank") {
+          win.removeEventListener("unload", unloadHandler);
+          this.onUnload(win);
+        }
+      };
+      win.addEventListener("unload", unloadHandler, true);
+    }
+
+    // First we do the actual setAndFetch call:
+    let {innerWindowID, currentURI} = browser;
+    let loadType = PrivateBrowsingUtils.isWindowPrivate(win)
+      ? PlacesUtils.favicons.FAVICON_LOAD_PRIVATE
+      : PlacesUtils.favicons.FAVICON_LOAD_NON_PRIVATE;
+    let callback = this._makeCompletionCallback(win, innerWindowID);
+    let request = PlacesUtils.favicons.setAndFetchFaviconForPage(currentURI, uri, false,
+                                                                 loadType, callback, principal);
+
+    // Now register the result so we can cancel it if/when necessary.
+    if (!request) {
+      // The favicon service can return with success but no-op (and leave request
+      // as null) if the icon is the same as the page (e.g. for images) or if it is
+      // the favicon for an error page. In this case, we do not need to do anything else.
+      return;
+    }
+    callback.request = request;
+    let loadData = {innerWindowID, uri, callback};
+    loadData.timerID = setTimeout(() => {
+      this._cancelRequest(loadData, "it timed out");
+    }, FAVICON_REQUEST_TIMEOUT);
+    let loadDataForWindow = gFaviconLoadDataMap.get(win);
+    loadDataForWindow.push(loadData);
+  },
+};
+
 this.PlacesUIUtils = {
   ORGANIZER_LEFTPANE_VERSION: 7,
   ORGANIZER_FOLDER_ANNO: "PlacesOrganizer/OrganizerFolder",
   ORGANIZER_QUERY_ANNO: "PlacesOrganizer/OrganizerQuery",
 
   LOAD_IN_SIDEBAR_ANNO: "bookmarkProperties/loadInSidebar",
   DESCRIPTION_ANNO: "bookmarkProperties/description",
 
@@ -477,16 +626,29 @@ this.PlacesUIUtils = {
     return ("performed" in aInfo && aInfo.performed);
   },
 
   _getTopBrowserWin: function PUIU__getTopBrowserWin() {
     return RecentWindow.getMostRecentBrowserWindow();
   },
 
   /**
+   * set and fetch a favicon. Can only be used from the parent process.
+   * @param browser   {Browser}   The XUL browser element for which we're fetching a favicon.
+   * @param principal {Principal} The loading principal to use for the fetch.
+   * @param uri       {URI}       The URI to fetch.
+   */
+  loadFavicon(browser, principal, uri) {
+    if (gInContentProcess) {
+      throw new Error("Can't track loads from within the child process!");
+    }
+    InternalFaviconLoader.loadFavicon(browser, principal, uri);
+  },
+
+  /**
    * Returns the closet ancestor places view for the given DOM node
    * @param aNode
    *        a DOM node
    * @return the closet ancestor places view if exists, null otherwsie.
    */
   getViewForNode: function PUIU_getViewForNode(aNode) {
     let node = aNode;
 
@@ -607,18 +769,20 @@ this.PlacesUIUtils = {
    * history or in bookmarks).
    *
    * @param aNode
    *        a node, except the root node of a query.
    * @return true if the aNode represents a removable entry, false otherwise.
    */
   canUserRemove: function (aNode) {
     let parentNode = aNode.parent;
-    if (!parentNode)
-      throw new Error("canUserRemove doesn't accept root nodes");
+    if (!parentNode) {
+      // canUserRemove doesn't accept root nodes.
+      return false;
+    }
 
     // If it's not a bookmark, we can remove it unless it's a child of a
     // livemark.
     if (aNode.itemId == -1) {
       // Rather than executing a db query, checking the existence of the feedURI
       // annotation, detect livemark children by the fact that they are the only
       // direct non-bookmark children of bookmark folders.
       return !PlacesUtils.nodeIsFolder(parentNode);
--- a/browser/components/places/content/browserPlacesViews.js
+++ b/browser/components/places/content/browserPlacesViews.js
@@ -191,17 +191,17 @@ PlacesViewBase.prototype = {
     let container = this._resultNode;
     let orientation = Ci.nsITreeView.DROP_BEFORE;
     let tagName = null;
 
     let selectedNode = this.selectedNode;
     if (selectedNode) {
       let popup = document.popupNode;
       if (!popup._placesNode || popup._placesNode == this._resultNode ||
-          popup._placesNode.itemId == -1) {
+          popup._placesNode.itemId == -1 || !selectedNode.parent) {
         // If a static menuitem is selected, or if the root node is selected,
         // the insertion point is inside the folder, at the end.
         container = selectedNode;
         orientation = Ci.nsITreeView.DROP_ON;
       }
       else {
         // In all other cases the insertion point is before that node.
         container = selectedNode.parent;
@@ -889,17 +889,18 @@ PlacesViewBase.prototype = {
       // Menus that have static content at the end, but are initially empty,
       // use a special "builder" attribute to figure out where to start
       // inserting places nodes.
       if (child.getAttribute("builder") == "end") {
         aPopup.insertBefore(aPopup._endMarker, child);
         break;
       }
 
-      if (child._placesNode && !firstNonStaticNodeFound) {
+      if (child._placesNode && !child.hasAttribute("simulated-places-node") &&
+          !firstNonStaticNodeFound) {
         firstNonStaticNodeFound = true;
         aPopup.insertBefore(aPopup._startMarker, child);
       }
     }
     if (!firstNonStaticNodeFound) {
       aPopup.insertBefore(aPopup._startMarker, aPopup._endMarker);
     }
   },
@@ -1654,17 +1655,17 @@ PlacesToolbar.prototype = {
           else {
             translateX += this._rootElt.childNodes[dropPoint.beforeIndex]
                               .getBoundingClientRect().left;
           }
         }
       }
 
       ind.style.transform = "translate(" + Math.round(translateX) + "px)";
-      ind.style.MozMarginStart = (-ind.clientWidth) + "px";
+      ind.style.marginInlineStart = (-ind.clientWidth) + "px";
       ind.collapsed = false;
 
       // Clear out old folder information.
       this._clearOverFolder();
     }
 
     aEvent.preventDefault();
     aEvent.stopPropagation();
--- a/browser/components/places/content/controller.js
+++ b/browser/components/places/content/controller.js
@@ -451,18 +451,16 @@ PlacesController.prototype = {
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_SEPARATOR:
           nodeData["separator"] = true;
           break;
         case Ci.nsINavHistoryResultNode.RESULT_TYPE_URI:
           nodeData["link"] = true;
           uri = NetUtil.newURI(node.uri);
           if (PlacesUtils.nodeIsBookmark(node)) {
             nodeData["bookmark"] = true;
-            PlacesUtils.nodeIsTagQuery(node.parent)
-
             var parentNode = node.parent;
             if (parentNode) {
               if (PlacesUtils.nodeIsTagQuery(parentNode))
                 nodeData["tagChild"] = true;
               else if (this.hasCachedLivemarkInfo(parentNode))
                 nodeData["livemarkChild"] = true;
             }
           }
--- a/browser/components/places/tests/browser/browser_views_liveupdate.js
+++ b/browser/components/places/tests/browser/browser_views_liveupdate.js
@@ -317,17 +317,17 @@ function getNodeForToolbarItem(aItemId, 
   var toolbar = document.getElementById("PlacesToolbarItems");
 
   function findNode(aContainer) {
     var children = aContainer.childNodes;
     for (var i = 0, staticNodes = 0; i < children.length; i++) {
       var child = children[i];
 
       // Is this a Places node?
-      if (!child._placesNode) {
+      if (!child._placesNode || child.hasAttribute("simulated-places-node")) {
         staticNodes++;
         continue;
       }
 
       if (child._placesNode.itemId == aItemId) {
         let valid = aValidator ? aValidator(child) : true;
         return [child._placesNode, i - staticNodes, valid];
       }
@@ -360,17 +360,17 @@ function getNodeForMenuItem(aItemId, aVa
   var menu = document.getElementById("bookmarksMenu");
 
   function findNode(aContainer) {
     var children = aContainer.childNodes;
     for (var i = 0, staticNodes = 0; i < children.length; i++) {
       var child = children[i];
 
       // Is this a Places node?
-      if (!child._placesNode) {
+      if (!child._placesNode || child.hasAttribute("simulated-places-node")) {
         staticNodes++;
         continue;
       }
 
       if (child._placesNode.itemId == aItemId) {
         let valid = aValidator ? aValidator(child) : true;
         return [child._placesNode, i - staticNodes, valid];
       }
--- a/browser/components/preferences/cookies.js
+++ b/browser/components/preferences/cookies.js
@@ -2,17 +2,20 @@
 /* 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 nsICookie = Components.interfaces.nsICookie;
 
 Components.utils.import("resource://gre/modules/PluralForm.jsm");
 Components.utils.import("resource://gre/modules/Services.jsm")
-Components.utils.import("resource:///modules/UserContextUI.jsm");
+Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
+
+XPCOMUtils.defineLazyModuleGetter(this, "ContextualIdentityService",
+                                  "resource:///modules/ContextualIdentityService.jsm");
 
 var gCookiesWindow = {
   _cm               : Components.classes["@mozilla.org/cookiemanager;1"]
                                 .getService(Components.interfaces.nsICookieManager),
   _ds               : Components.classes["@mozilla.org/intl/scriptabledateformat;1"]
                                 .getService(Components.interfaces.nsIScriptableDateFormat),
   _hosts            : {},
   _hostOrder        : [],
@@ -511,17 +514,17 @@ var gCookiesWindow = {
     return this._bundle.getString("expireAtEndOfSession");
   },
 
   _getUserContextString: function(aUserContextId) {
     if (parseInt(aUserContextId) == 0) {
       return this._bundle.getString("defaultUserContextLabel");
     }
 
-    return UserContextUI.getUserContextLabel(aUserContextId);
+    return ContextualIdentityService.getUserContextLabel(aUserContextId);
   },
 
   _updateCookieData: function (aItem) {
     var seln = this._view.selection;
     var ids = ["name", "value", "host", "path", "isSecure", "expires", "userContext"];
     var properties;
 
     if (aItem && !aItem.container && seln.count > 0) {
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -156,22 +156,16 @@ var gMainPane = {
                                    "restart");
       shouldProceed = !cancelQuit.data;
 
       if (shouldProceed) {
         for (let prefToChange of prefsToChange) {
           prefToChange.value = e10sCheckbox.checked;
         }
 
-        let tmp = {};
-        Components.utils.import("resource://gre/modules/UpdateUtils.jsm", tmp);
-        if (!e10sCheckbox.checked && tmp.UpdateUtils.UpdateChannel != "default") {
-          Services.prefs.setBoolPref("browser.requestE10sFeedback", true);
-          Services.prompt.alert(window, brandName, bundle.getString("e10sFeedbackAfterRestart"));
-        }
         Services.startup.quit(Ci.nsIAppStartup.eAttemptQuit |  Ci.nsIAppStartup.eRestart);
       }
     }
 
     // Revert the checkbox in case we didn't quit
     e10sCheckbox.checked = e10sPref.value || e10sTempPref.value;
   },
 #endif
--- a/browser/components/search/test/browser_contextSearchTabPosition.js
+++ b/browser/components/search/test/browser_contextSearchTabPosition.js
@@ -1,13 +1,14 @@
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 add_task(function* test() {
+  yield SpecialPowers.pushPrefEnv({set: [["toolkit.telemetry.enabled", true]]});
   let engine = yield promiseNewEngine("testEngine.xml");
   let histogramKey = "other-" + engine.name + ".contextmenu";
   let numSearchesBefore = 0;
 
   try {
     let hs = Services.telemetry.getKeyedHistogramById("SEARCH_COUNTS").snapshot();
     if (histogramKey in hs) {
       numSearchesBefore = hs[histogramKey].sum;
--- a/browser/components/search/test/browser_healthreport.js
+++ b/browser/components/search/test/browser_healthreport.js
@@ -65,17 +65,18 @@ function test() {
       case "engine-removed":
         Services.obs.removeObserver(observer, "browser-search-engine-modified");
         finish();
         break;
     }
   }
 
   Services.obs.addObserver(observer, "browser-search-engine-modified", false);
-  Services.search.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
-                            null, "data:image/x-icon,%00", false);
-
+  SpecialPowers.pushPrefEnv({set: [["toolkit.telemetry.enabled", true]]}).then(function() {
+    Services.search.addEngine("http://mochi.test:8888/browser/browser/components/search/test/testEngine.xml",
+                              null, "data:image/x-icon,%00", false);
+  });
 }
 
 function resetPreferences() {
   Preferences.resetBranch("datareporting.policy.");
   Preferences.set("datareporting.policy.dataSubmissionPolicyBypassNotification", true);
 }
--- a/browser/components/sessionstore/SessionHistory.jsm
+++ b/browser/components/sessionstore/SessionHistory.jsm
@@ -257,23 +257,16 @@ var SessionHistoryInternal = {
    * @param docShell
    *        The docShell that owns the session history.
    * @param tabData
    *        The tabdata including all history entries.
    */
   restore: function (docShell, tabData) {
     let webNavigation = docShell.QueryInterface(Ci.nsIWebNavigation);
     let history = webNavigation.sessionHistory;
-
-    if ("userContextId" in tabData) {
-      let attrs = docShell.getOriginAttributes();
-      attrs.userContextId = tabData.userContextId;
-      docShell.setOriginAttributes(attrs);
-    }
-
     if (history.count > 0) {
       history.PurgeHistory(history.count);
     }
     history.QueryInterface(Ci.nsISHistoryInternal);
 
     let idMap = { used: {} };
     let docIdentMap = {};
     for (let i = 0; i < tabData.entries.length; i++) {
--- a/browser/components/sessionstore/SessionStore.jsm
+++ b/browser/components/sessionstore/SessionStore.jsm
@@ -815,17 +815,17 @@ var SessionStoreInternal = {
         event.initEvent("SSTabRestoring", true, false);
         tab.dispatchEvent(event);
         break;
       case "SessionStore:restoreTabContentStarted":
         if (browser.__SS_restoreState == TAB_STATE_NEEDS_RESTORE) {
           // If a load not initiated by sessionstore was started in a
           // previously pending tab. Mark the tab as no longer pending.
           this.markTabAsRestoring(tab);
-        } else {
+        } else if (!data.isRemotenessUpdate) {
           // If the user was typing into the URL bar when we crashed, but hadn't hit
           // enter yet, then we just need to write that value to the URL bar without
           // loading anything. This must happen after the load, as the load will clear
           // userTypedValue.
           let tabData = TabState.collect(tab);
           if (tabData.userTypedValue && !tabData.userTypedClear && !browser.userTypedValue) {
             browser.userTypedValue = tabData.userTypedValue;
             win.URLBarSetURI();
@@ -2067,19 +2067,20 @@ var SessionStoreInternal = {
     if (!aTab.ownerDocument.defaultView.__SSi) {
       throw Components.Exception("Default view is not tracked", Cr.NS_ERROR_INVALID_ARG);
     }
     if (!aWindow.gBrowser) {
       throw Components.Exception("Invalid window object: no gBrowser", Cr.NS_ERROR_INVALID_ARG);
     }
 
     // Create a new tab.
+    let userContextId = aTab.getAttribute("usercontextid");
     let newTab = aTab == aWindow.gBrowser.selectedTab ?
-      aWindow.gBrowser.addTab(null, {relatedToCurrent: true, ownerTab: aTab}) :
-      aWindow.gBrowser.addTab();
+      aWindow.gBrowser.addTab(null, {relatedToCurrent: true, ownerTab: aTab, userContextId}) :
+      aWindow.gBrowser.addTab(null, {userContextId});
 
     // Set tab title to "Connecting..." and start the throbber to pretend we're
     // doing something while actually waiting for data from the frame script.
     aWindow.gBrowser.setTabTitleLoading(newTab);
     newTab.setAttribute("busy", "true");
 
     // Collect state before flushing.
     let tabState = TabState.clone(aTab);
@@ -3198,20 +3199,16 @@ var SessionStoreInternal = {
     }
 
     if (tabData.hidden) {
       tabbrowser.hideTab(tab);
     } else {
       tabbrowser.showTab(tab);
     }
 
-    if (tabData.userContextId) {
-      tab.setUserContextId(tabData.userContextId);
-    }
-
     if (!!tabData.muted != browser.audioMuted) {
       tab.toggleMuteAudio(tabData.muteReason);
     }
 
     if (tabData.lastAccessed) {
       tab.lastAccessed = tabData.lastAccessed;
     }
 
--- a/browser/components/sessionstore/content/content-sessionStore.js
+++ b/browser/components/sessionstore/content/content-sessionStore.js
@@ -184,17 +184,17 @@ var MessageListener = {
 
     // We need to pass the value of didStartLoad back to SessionStore.jsm.
     let didStartLoad = gContentRestore.restoreTabContent(loadArguments, isRemotenessUpdate, () => {
       // Tell SessionStore.jsm that it may want to restore some more tabs,
       // since it restores a max of MAX_CONCURRENT_TAB_RESTORES at a time.
       sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch, isRemotenessUpdate});
     });
 
-    sendAsyncMessage("SessionStore:restoreTabContentStarted", {epoch, didStartLoad});
+    sendAsyncMessage("SessionStore:restoreTabContentStarted", {epoch, isRemotenessUpdate});
 
     if (!didStartLoad) {
       // Pretend that the load succeeded so that event handlers fire correctly.
       sendAsyncMessage("SessionStore:restoreTabContentComplete", {epoch, isRemotenessUpdate});
     }
   },
 
   flush({id}) {
--- a/browser/components/sessionstore/test/browser.ini
+++ b/browser/components/sessionstore/test/browser.ini
@@ -218,10 +218,12 @@ skip-if = os == "mac"
 
 [browser_911547.js]
 [browser_send_async_message_oom.js]
 [browser_multiple_navigateAndRestore.js]
 run-if = e10s
 [browser_async_window_flushing.js]
 [browser_forget_async_closings.js]
 [browser_newtab_userTypedValue.js]
+[browser_parentProcessRestoreHash.js]
+run-if = e10s
 [browser_sessionStoreContainer.js]
 [browser_1234021.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/sessionstore/test/browser_parentProcessRestoreHash.js
@@ -0,0 +1,95 @@
+"use strict";
+
+const SELFCHROMEURL =
+  "chrome://mochitests/content/browser/browser/" +
+  "components/sessionstore/test/browser_parentProcessRestoreHash.js";
+
+const Cm = Components.manager;
+
+const TESTCLASSID = "78742c04-3630-448c-9be3-6c5070f062de";
+
+const TESTURL = "about:testpageforsessionrestore#foo";
+
+
+let TestAboutPage = {
+  QueryInterface: XPCOMUtils.generateQI([Ci.nsIAboutModule]),
+  getURIFlags: function(aURI) {
+    // No CAN_ or MUST_LOAD_IN_CHILD means this loads in the parent:
+    return Ci.nsIAboutModule.ALLOW_SCRIPT |
+           Ci.nsIAboutModule.URI_SAFE_FOR_UNTRUSTED_CONTENT |
+           Ci.nsIAboutModule.HIDE_FROM_ABOUTABOUT;
+  },
+
+  newChannel: function(aURI, aLoadInfo) {
+    // about: page inception!
+    let newURI = Services.io.newURI(SELFCHROMEURL, null, null);
+    let channel = Services.io.newChannelFromURIWithLoadInfo(newURI,
+                                                            aLoadInfo);
+    channel.originalURI = aURI;
+    return channel;
+  },
+
+  createInstance: function(outer, iid) {
+    if (outer != null) {
+      throw Cr.NS_ERROR_NO_AGGREGATION;
+    }
+    return this.QueryInterface(iid);
+  },
+
+  register: function() {
+    Cm.QueryInterface(Ci.nsIComponentRegistrar).registerFactory(
+      Components.ID(TESTCLASSID), "Only here for a test",
+      "@mozilla.org/network/protocol/about;1?what=testpageforsessionrestore", this);
+  },
+
+  unregister: function() {
+    Cm.QueryInterface(Ci.nsIComponentRegistrar).unregisterFactory(
+      Components.ID(TESTCLASSID), this);
+  }
+};
+
+
+/**
+ * Test that switching from a remote to a parent process browser
+ * correctly clears the userTypedValue
+ */
+add_task(function* () {
+  TestAboutPage.register();
+  let tab = yield BrowserTestUtils.openNewForegroundTab(gBrowser, "http://example.com/", true, true);
+  ok(tab.linkedBrowser.isRemoteBrowser, "Browser should be remote");
+
+  let resolveLocationChangePromise;
+  let locationChangePromise = new Promise(r => resolveLocationChangePromise = r);
+  let wpl = {
+    onStateChange(wpl, request, state, status) {
+      let location = request.QueryInterface(Ci.nsIChannel).originalURI;
+      // Ignore about:blank loads.
+      let docStop = Ci.nsIWebProgressListener.STATE_STOP |
+                    Ci.nsIWebProgressListener.STATE_IS_NETWORK;
+      if (location.spec == "about:blank" || (state & docStop == docStop)) {
+        return;
+      }
+      is(location.spec, TESTURL, "Got the expected URL");
+      resolveLocationChangePromise();
+    },
+  };
+  gBrowser.addProgressListener(wpl);
+
+  gURLBar.value = TESTURL;
+  gURLBar.select();
+  EventUtils.sendKey("return");
+
+  yield locationChangePromise;
+
+  ok(!tab.linkedBrowser.isRemoteBrowser, "Browser should no longer be remote");
+
+  is(gURLBar.textValue, TESTURL, "URL bar visible value should be correct.");
+  is(gURLBar.value, TESTURL, "URL bar value should be correct.");
+  is(gURLBar.getAttribute("pageproxystate"), "valid", "URL bar is in valid page proxy state");
+
+  ok(!tab.linkedBrowser.userTypedValue, "No userTypedValue should be on the browser.");
+
+  yield BrowserTestUtils.removeTab(tab);
+  gBrowser.removeProgressListener(wpl);
+  TestAboutPage.unregister();
+});
--- a/browser/components/sessionstore/test/browser_sessionStoreContainer.js
+++ b/browser/components/sessionstore/test/browser_sessionStoreContainer.js
@@ -5,22 +5,45 @@
 add_task(function* () {
   for (let i = 0; i < 3; ++i) {
     let tab = gBrowser.addTab("http://example.com/", {userContextId: i});
     let browser = tab.linkedBrowser;
 
     yield promiseBrowserLoaded(browser);
 
     let tab2 = gBrowser.duplicateTab(tab);
+    Assert.equal(tab2.getAttribute("usercontextid"), i);
     let browser2 = tab2.linkedBrowser;
     yield promiseTabRestored(tab2)
 
     yield ContentTask.spawn(browser2, { expectedId: i }, function* (args) {
       let loadContext = docShell.QueryInterface(Ci.nsILoadContext);
       Assert.equal(loadContext.originAttributes.userContextId,
         args.expectedId, "The docShell has the correct userContextId");
     });
 
     yield promiseRemoveTab(tab);
     yield promiseRemoveTab(tab2);
   }
 });
 
+add_task(function* () {
+  let tab = gBrowser.addTab("http://example.com/", {userContextId: 1});
+  let browser = tab.linkedBrowser;
+
+  yield promiseBrowserLoaded(browser);
+
+  gBrowser.selectedTab = tab;
+
+  let tab2 = gBrowser.duplicateTab(tab);
+  let browser2 = tab2.linkedBrowser;
+  yield promiseTabRestored(tab2)
+
+  yield ContentTask.spawn(browser2, { expectedId: 1}, function* (args) {
+    Assert.equal(docShell.getOriginAttributes().userContextId,
+                 args.expectedId,
+                 "The docShell has the correct userContextId");
+  });
+
+  yield promiseRemoveTab(tab);
+  yield promiseRemoveTab(tab2);
+});
+
--- a/browser/components/shell/moz.build
+++ b/browser/components/shell/moz.build
@@ -55,11 +55,8 @@ EXTRA_JS_MODULES += [
 
 for var in ('MOZ_APP_NAME', 'MOZ_APP_VERSION'):
     DEFINES[var] = '"%s"' % CONFIG[var]
 
 CXXFLAGS += CONFIG['TK_CFLAGS']
 
 with Files('**'):
     BUG_COMPONENT = ('Firefox', 'Shell Integration')
-
-if CONFIG['GNU_CXX']:
-    CXXFLAGS += ['-Wshadow']
--- a/browser/components/syncedtabs/TabListComponent.js
+++ b/browser/components/syncedtabs/TabListComponent.js
@@ -1,19 +1,24 @@
 /* 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";
 
 const {classes: Cc, interfaces: Ci, utils: Cu, results: Cr} = Components;
 
+Cu.import("resource://gre/modules/XPCOMUtils.jsm");
+
 let log = Cu.import("resource://gre/modules/Log.jsm", {})
             .Log.repository.getLogger("Sync.RemoteTabs");
 
+XPCOMUtils.defineLazyModuleGetter(this, "BrowserUITelemetry",
+  "resource:///modules/BrowserUITelemetry.jsm");
+
 this.EXPORTED_SYMBOLS = [
   "TabListComponent"
 ];
 
 /**
  * TabListComponent
  *
  * The purpose of this component is to compose the view, state, and actions.
@@ -100,16 +105,17 @@ TabListComponent.prototype = {
   onBookmarkTab(uri, title) {
     this._window.top.PlacesCommandHook
       .bookmarkLink(this._window.top.PlacesUtils.bookmarksMenuFolderId, uri, title)
       .catch(Cu.reportError);
   },
 
   onOpenTab(url, where, params) {
     this._window.openUILinkIn(url, where, params);
+    BrowserUITelemetry.countSyncedTabEvent("open", "sidebar");
   },
 
   onCopyTabLocation(url) {
     this._clipboardHelper.copyString(url);
   },
 
   onSyncRefresh() {
     this._SyncedTabs.syncTabs(true);
--- a/browser/components/syncedtabs/TabListView.js
+++ b/browser/components/syncedtabs/TabListView.js
@@ -46,16 +46,17 @@ function TabListView(w