Merge m-c to graphics, a=merge
authorKartikaya Gupta <kgupta@mozilla.com>
Thu, 25 May 2017 08:06:56 -0400
changeset 409347 9c8bcb590b888c5c077e3a05625800ed0d6786a8
parent 409346 e4db9580e41b486ee1dbd603bd2e011003f5fb1f (current diff)
parent 408675 0ed0fd886134b6698f593edbf0d362ac9e12fe07 (diff)
child 409348 1a0568ebe975cafcd2f8e785730a2a13d5ee9a9e
push id7391
push usermtabara@mozilla.com
push dateMon, 12 Jun 2017 13:08:53 +0000
treeherdermozilla-beta@2191d7f87e2e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone55.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge m-c to graphics, a=merge MozReview-Commit-ID: 3cEYFBtGvTZ
browser/base/content/defaultthemes/1.footer.jpg
browser/base/content/defaultthemes/2.footer.jpg
browser/base/content/defaultthemes/3.footer.png
browser/base/content/defaultthemes/4.footer.png
browser/base/content/defaultthemes/5.footer.png
browser/themes/osx/customizableui/customize-titleBar-toggle.png
browser/themes/osx/customizableui/customize-titleBar-toggle@2x.png
browser/themes/shared/sidebar/arrow-dropdown.svg
browser/themes/windows/customizableui/customize-titleBar-toggle.png
browser/themes/windows/customizableui/customize-titleBar-toggle@2x.png
dom/file/ipc/Blob.cpp
dom/file/ipc/BlobChild.h
dom/file/ipc/BlobParent.h
dom/file/ipc/MemoryStreamChild.h
dom/file/ipc/MemoryStreamParent.cpp
dom/file/ipc/MemoryStreamParent.h
dom/file/ipc/PBlob.ipdl
dom/file/ipc/PBlobStream.ipdl
dom/file/ipc/PMemoryStream.ipdl
dom/file/ipc/nsIRemoteBlob.h
mobile/android/base/java/org/mozilla/gecko/GeckoActivityStatus.java
mobile/android/branding/aurora/configure.sh
mobile/android/branding/aurora/content/about.png
mobile/android/branding/aurora/content/favicon32.png
mobile/android/branding/aurora/content/favicon64.png
mobile/android/branding/aurora/content/jar.mn
mobile/android/branding/aurora/content/moz.build
mobile/android/branding/aurora/locales/en-US/brand.dtd
mobile/android/branding/aurora/locales/en-US/brand.properties
mobile/android/branding/aurora/locales/jar.mn
mobile/android/branding/aurora/locales/moz.build
mobile/android/branding/aurora/moz.build
mobile/android/branding/aurora/res/drawable-hdpi/icon.png
mobile/android/branding/aurora/res/drawable-hdpi/large_icon.png
mobile/android/branding/aurora/res/drawable-hdpi/launcher_widget.png
mobile/android/branding/aurora/res/drawable-hdpi/widget_icon.png
mobile/android/branding/aurora/res/drawable-xhdpi/icon.png
mobile/android/branding/aurora/res/drawable-xhdpi/large_icon.png
mobile/android/branding/aurora/res/drawable-xhdpi/launcher_widget.png
mobile/android/branding/aurora/res/drawable-xhdpi/widget_icon.png
mobile/android/branding/aurora/res/drawable-xxhdpi/icon.png
mobile/android/branding/aurora/res/drawable-xxhdpi/large_icon.png
mobile/android/branding/aurora/res/drawable-xxhdpi/launcher_widget.png
mobile/android/branding/aurora/res/drawable-xxhdpi/widget_icon.png
mobile/android/branding/aurora/res/drawable-xxxhdpi/icon.png
mobile/android/config/mozconfigs/android-api-15/nightly-aurora-id
netwerk/base/ThrottlingService.cpp
netwerk/base/ThrottlingService.h
netwerk/base/nsIThrottlingService.idl
parser/html/nsHtml5StreamParserPtr.h
testing/web-platform/meta/XMLHttpRequest/event-readystatechange-loaded.htm.ini
testing/web-platform/meta/XMLHttpRequest/overridemimetype-invalid-mime-type.htm.ini
testing/web-platform/meta/XMLHttpRequest/send-entity-body-document-bogus.htm.ini
testing/web-platform/meta/XMLHttpRequest/send-redirect-post-upload.htm.ini
testing/web-platform/meta/battery-status/battery-interface-idlharness.html.ini
testing/web-platform/meta/battery-status/battery-promise-iframe.html.ini
testing/web-platform/meta/battery-status/battery-promise-window.html.ini
testing/web-platform/meta/battery-status/battery-promise.html.ini
testing/web-platform/meta/content-security-policy/navigation/to-javascript-url.html.ini
testing/web-platform/meta/fullscreen/api/__dir__.ini
testing/web-platform/meta/intersection-observer/client-rect.html.ini
testing/web-platform/meta/intersection-observer/observer-attributes.html.ini
testing/web-platform/meta/intersection-observer/observer-exceptions.html.ini
testing/web-platform/meta/intersection-observer/observer-in-iframe.html.ini
testing/web-platform/meta/url/interfaces.html.ini
testing/web-platform/meta/webusb/idlharness.html.ini
testing/web-platform/tests/DOM-parsing/todo/internalSubset.html
testing/web-platform/tests/battery-status/battery-charging-manual.html
testing/web-platform/tests/battery-status/battery-discharging-manual.html
testing/web-platform/tests/battery-status/battery-full-manual.html
testing/web-platform/tests/battery-status/battery-interface-idlharness.html
testing/web-platform/tests/battery-status/battery-plugging-in-manual.html
testing/web-platform/tests/battery-status/battery-promise-iframe.html
testing/web-platform/tests/battery-status/battery-promise-window.html
testing/web-platform/tests/battery-status/battery-promise.html
testing/web-platform/tests/battery-status/battery-unplugging-manual.html
testing/web-platform/tests/battery-status/support-iframe-initial.html
testing/web-platform/tests/content-security-policy/navigation/to-javascript-url.html
testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/iframe_sandbox_009.htm
testing/web-platform/tests/old-tests/submission/Microsoft/sandbox/sandbox_009-manual.htm
testing/web-platform/tests/presentation-api/controlling-ua/PresentationConnection_onclosed-manual.html
testing/web-platform/tests/presentation-api/controlling-ua/PresentationConnection_onconnected-manual.html
testing/web-platform/tests/presentation-api/controlling-ua/PresentationConnection_onterminated-manual.html
testing/web-platform/tests/url/interfaces.html
testing/web-platform/tests/webusb/idlharness.html
--- a/accessible/tests/browser/browser_shutdown_acc_reference.js
+++ b/accessible/tests/browser/browser_shutdown_acc_reference.js
@@ -1,26 +1,26 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Create a11y service.
   let a11yInit = initPromise();
   let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
 
-  yield a11yInit;
+  await a11yInit;
   ok(accService, 'Service initialized');
 
   // Accessible object reference will live longer than the scope of this
   // function.
-  let acc = yield new Promise(resolve => {
+  let acc = await new Promise(resolve => {
     let intervalId = setInterval(() => {
       let tabAcc = accService.getAccessibleFor(gBrowser.mCurrentTab);
       if (tabAcc) {
         clearInterval(intervalId);
         resolve(tabAcc);
       }
     }, 10);
   });
@@ -36,20 +36,20 @@ add_task(function* () {
 
   accService = null;
   ok(!accService, 'Service is removed');
 
   // Force garbage collection that should not trigger shutdown because there is
   // a reference to an accessible object.
   forceGC();
   // Have some breathing room when removing a11y service references.
-  yield new Promise(resolve => executeSoon(resolve));
+  await new Promise(resolve => executeSoon(resolve));
 
   // Now allow a11y service to shutdown.
   canShutdown = true;
   // Remove a reference to an accessible object.
   acc = null;
   ok(!acc, 'Accessible object is removed');
 
   // Force garbage collection that should now trigger shutdown.
   forceGC();
-  yield a11yShutdown;
+  await a11yShutdown;
 });
--- a/accessible/tests/browser/browser_shutdown_doc_acc_reference.js
+++ b/accessible/tests/browser/browser_shutdown_doc_acc_reference.js
@@ -1,21 +1,21 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Create a11y service.
   let a11yInit = initPromise();
   let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
 
-  yield a11yInit;
+  await a11yInit;
   ok(accService, 'Service initialized');
 
   // Accessible document reference will live longer than the scope of this
   // function.
   let docAcc = accService.getAccessibleFor(document);
   ok(docAcc, 'Accessible document is created');
 
   let canShutdown = false;
@@ -28,20 +28,20 @@ add_task(function* () {
 
   accService = null;
   ok(!accService, 'Service is removed');
 
   // Force garbage collection that should not trigger shutdown because there is
   // a reference to an accessible document.
   forceGC();
   // Have some breathing room when removing a11y service references.
-  yield new Promise(resolve => executeSoon(resolve));
+  await new Promise(resolve => executeSoon(resolve));
 
   // Now allow a11y service to shutdown.
   canShutdown = true;
   // Remove a reference to an accessible document.
   docAcc = null;
   ok(!docAcc, 'Accessible document is removed');
 
   // Force garbage collection that should now trigger shutdown.
   forceGC();
-  yield a11yShutdown;
+  await a11yShutdown;
 });
--- a/accessible/tests/browser/browser_shutdown_multi_acc_reference_doc.js
+++ b/accessible/tests/browser/browser_shutdown_multi_acc_reference_doc.js
@@ -1,29 +1,29 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Create a11y service.
   let a11yInit = initPromise();
   let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
 
-  yield a11yInit;
+  await a11yInit;
   ok(accService, 'Service initialized');
 
   let docAcc = accService.getAccessibleFor(document);
   ok(docAcc, 'Accessible document is created');
 
   // Accessible object reference will live longer than the scope of this
   // function.
-  let acc = yield new Promise(resolve => {
+  let acc = await new Promise(resolve => {
     let intervalId = setInterval(() => {
       let tabAcc = accService.getAccessibleFor(gBrowser.mCurrentTab);
       if (tabAcc) {
         clearInterval(intervalId);
         resolve(tabAcc);
       }
     }, 10);
   });
@@ -39,29 +39,29 @@ add_task(function* () {
 
   accService = null;
   ok(!accService, 'Service is removed');
 
   // Force garbage collection that should not trigger shutdown because there are
   // references to accessible objects.
   forceGC();
   // Have some breathing room when removing a11y service references.
-  yield new Promise(resolve => executeSoon(resolve));
+  await new Promise(resolve => executeSoon(resolve));
 
   // Remove a reference to an accessible object.
   acc = null;
   ok(!acc, 'Accessible object is removed');
   // Force garbage collection that should not trigger shutdown because there is
   // a reference to an accessible document.
   forceGC();
   // Have some breathing room when removing a11y service references.
-  yield new Promise(resolve => executeSoon(resolve));
+  await new Promise(resolve => executeSoon(resolve));
 
   // Now allow a11y service to shutdown.
   canShutdown = true;
   // Remove a reference to an accessible document.
   docAcc = null;
   ok(!docAcc, 'Accessible document is removed');
 
   // Force garbage collection that should now trigger shutdown.
   forceGC();
-  yield a11yShutdown;
+  await a11yShutdown;
 });
--- a/accessible/tests/browser/browser_shutdown_multi_acc_reference_obj.js
+++ b/accessible/tests/browser/browser_shutdown_multi_acc_reference_obj.js
@@ -1,29 +1,29 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Create a11y service.
   let a11yInit = initPromise();
   let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
 
-  yield a11yInit;
+  await a11yInit;
   ok(accService, 'Service initialized');
 
   let docAcc = accService.getAccessibleFor(document);
   ok(docAcc, 'Accessible document is created');
 
   // Accessible object reference will live longer than the scope of this
   // function.
-  let acc = yield new Promise(resolve => {
+  let acc = await new Promise(resolve => {
     let intervalId = setInterval(() => {
       let tabAcc = accService.getAccessibleFor(gBrowser.mCurrentTab);
       if (tabAcc) {
         clearInterval(intervalId);
         resolve(tabAcc);
       }
     }, 10);
   });
@@ -39,29 +39,29 @@ add_task(function* () {
 
   accService = null;
   ok(!accService, 'Service is removed');
 
   // Force garbage collection that should not trigger shutdown because there are
   // references to accessible objects.
   forceGC();
   // Have some breathing room when removing a11y service references.
-  yield new Promise(resolve => executeSoon(resolve));
+  await new Promise(resolve => executeSoon(resolve));
 
   // Remove a reference to an accessible document.
   docAcc = null;
   ok(!docAcc, 'Accessible document is removed');
   // Force garbage collection that should not trigger shutdown because there is
   // a reference to an accessible object.
   forceGC();
   // Have some breathing room when removing a11y service references.
-  yield new Promise(resolve => executeSoon(resolve));
+  await new Promise(resolve => executeSoon(resolve));
 
   // Now allow a11y service to shutdown.
   canShutdown = true;
   // Remove a reference to an accessible object.
   acc = null;
   ok(!acc, 'Accessible object is removed');
 
   // Force garbage collection that should now trigger shutdown.
   forceGC();
-  yield a11yShutdown;
+  await a11yShutdown;
 });
--- a/accessible/tests/browser/browser_shutdown_multi_proxy_acc_reference_doc.js
+++ b/accessible/tests/browser/browser_shutdown_multi_proxy_acc_reference_doc.js
@@ -1,38 +1,38 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Making sure that the e10s is enabled on Windows for testing.
-  yield setE10sPrefs();
+  await setE10sPrefs();
 
   let docLoaded = waitForEvent(
     Ci.nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE, 'body');
   let a11yInit = initPromise();
   let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
   ok(accService, 'Service initialized');
-  yield a11yInit;
+  await a11yInit;
 
-  yield BrowserTestUtils.withNewTab({
+  await BrowserTestUtils.withNewTab({
     gBrowser,
     url: `data:text/html,
       <html>
         <head>
           <meta charset="utf-8"/>
           <title>Accessibility Test</title>
         </head>
         <body id="body"><div id="div"></div></body>
       </html>`
-  }, function*(browser) {
-    let docLoadedEvent = yield docLoaded;
+  }, async function(browser) {
+    let docLoadedEvent = await docLoaded;
     let docAcc = docLoadedEvent.accessibleDocument;
     ok(docAcc, 'Accessible document proxy is created');
     // Remove unnecessary dangling references
     docLoaded = null;
     docLoadedEvent = null;
     forceGC();
 
     let acc = docAcc.getChildAt(0);
@@ -44,33 +44,33 @@ add_task(function* () {
       reject('Accessible service was shut down incorrectly')));
 
     accService = null;
     ok(!accService, 'Service is removed');
     // Force garbage collection that should not trigger shutdown because there
     // is a reference to an accessible proxy.
     forceGC();
     // Have some breathing room when removing a11y service references.
-    yield new Promise(resolve => executeSoon(resolve));
+    await new Promise(resolve => executeSoon(resolve));
 
     // Remove a reference to an accessible proxy.
     acc = null;
     ok(!acc, 'Accessible proxy is removed');
     // Force garbage collection that should not trigger shutdown because there is
     // a reference to an accessible document proxy.
     forceGC();
     // Have some breathing room when removing a11y service references.
-    yield new Promise(resolve => executeSoon(resolve));
+    await new Promise(resolve => executeSoon(resolve));
 
     // Now allow a11y service to shutdown.
     canShutdown = true;
     // Remove a last reference to an accessible document proxy.
     docAcc = null;
     ok(!docAcc, 'Accessible document proxy is removed');
 
     // Force garbage collection that should now trigger shutdown.
     forceGC();
-    yield a11yShutdown;
+    await a11yShutdown;
   });
 
   // Unsetting e10s related preferences.
-  yield unsetE10sPrefs();
+  await unsetE10sPrefs();
 });
--- a/accessible/tests/browser/browser_shutdown_multi_proxy_acc_reference_obj.js
+++ b/accessible/tests/browser/browser_shutdown_multi_proxy_acc_reference_obj.js
@@ -1,38 +1,38 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Making sure that the e10s is enabled on Windows for testing.
-  yield setE10sPrefs();
+  await setE10sPrefs();
 
   let docLoaded = waitForEvent(
     Ci.nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE, 'body');
   let a11yInit = initPromise();
   let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
   ok(accService, 'Service initialized');
-  yield a11yInit;
+  await a11yInit;
 
-  yield BrowserTestUtils.withNewTab({
+  await BrowserTestUtils.withNewTab({
     gBrowser,
     url: `data:text/html,
       <html>
         <head>
           <meta charset="utf-8"/>
           <title>Accessibility Test</title>
         </head>
         <body id="body"><div id="div"></div></body>
       </html>`
-  }, function*(browser) {
-    let docLoadedEvent = yield docLoaded;
+  }, async function(browser) {
+    let docLoadedEvent = await docLoaded;
     let docAcc = docLoadedEvent.accessibleDocument;
     ok(docAcc, 'Accessible document proxy is created');
     // Remove unnecessary dangling references
     docLoaded = null;
     docLoadedEvent = null;
     forceGC();
 
     let acc = docAcc.getChildAt(0);
@@ -44,33 +44,33 @@ add_task(function* () {
       reject('Accessible service was shut down incorrectly')));
 
     accService = null;
     ok(!accService, 'Service is removed');
     // Force garbage collection that should not trigger shutdown because there
     // is a reference to an accessible proxy.
     forceGC();
     // Have some breathing room when removing a11y service references.
-    yield new Promise(resolve => executeSoon(resolve));
+    await new Promise(resolve => executeSoon(resolve));
 
     // Remove a reference to an accessible document proxy.
     docAcc = null;
     ok(!docAcc, 'Accessible document proxy is removed');
     // Force garbage collection that should not trigger shutdown because there is
     // a reference to an accessible proxy.
     forceGC();
     // Have some breathing room when removing a11y service references.
-    yield new Promise(resolve => executeSoon(resolve));
+    await new Promise(resolve => executeSoon(resolve));
 
     // Now allow a11y service to shutdown.
     canShutdown = true;
     // Remove a last reference to an accessible proxy.
     acc = null;
     ok(!acc, 'Accessible proxy is removed');
 
     // Force garbage collection that should now trigger shutdown.
     forceGC();
-    yield a11yShutdown;
+    await a11yShutdown;
   });
 
   // Unsetting e10s related preferences.
-  yield unsetE10sPrefs();
+  await unsetE10sPrefs();
 });
--- a/accessible/tests/browser/browser_shutdown_multi_reference.js
+++ b/accessible/tests/browser/browser_shutdown_multi_reference.js
@@ -1,21 +1,21 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   info('Creating a service');
   // Create a11y service.
   let a11yInit = initPromise();
   let accService1 = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
-  yield a11yInit;
+  await a11yInit;
   ok(accService1, 'Service initialized');
 
   // Add another reference to a11y service. This will not trigger
   // 'a11y-init-or-shutdown' event
   let accService2 = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
   ok(accService2, 'Service initialized');
 
@@ -30,19 +30,19 @@ add_task(function* () {
   // Remove first a11y service reference.
   accService1 = null;
   ok(!accService1, 'Service is removed');
   // Force garbage collection that should not trigger shutdown because there is
   // another reference.
   forceGC();
 
   // Have some breathing room when removing a11y service references.
-  yield new Promise(resolve => executeSoon(resolve));
+  await new Promise(resolve => executeSoon(resolve));
 
   // Now allow a11y service to shutdown.
   canShutdown = true;
   // Remove last a11y service reference.
   accService2 = null;
   ok(!accService2, 'Service is removed');
   // Force garbage collection that should trigger shutdown.
   forceGC();
-  yield a11yShutdown;
+  await a11yShutdown;
 });
--- a/accessible/tests/browser/browser_shutdown_parent_own_reference.js
+++ b/accessible/tests/browser/browser_shutdown_parent_own_reference.js
@@ -1,39 +1,39 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Making sure that the e10s is enabled on Windows for testing.
-  yield setE10sPrefs();
+  await setE10sPrefs();
 
-  yield BrowserTestUtils.withNewTab({
+  await BrowserTestUtils.withNewTab({
     gBrowser,
     url: `data:text/html,
       <html>
         <head>
           <meta charset="utf-8"/>
           <title>Accessibility Test</title>
         </head>
         <body></body>
       </html>`
-  }, function*(browser) {
+  }, async function(browser) {
     info('Creating a service in parent and waiting for service to be created ' +
       'in content');
     // Create a11y service in the main process. This will trigger creating of
     // the a11y service in parent as well.
     let parentA11yInit = initPromise();
     let contentA11yInit = initPromise(browser);
     let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
       Ci.nsIAccessibilityService);
     ok(accService, 'Service initialized in parent');
-    yield Promise.all([parentA11yInit, contentA11yInit]);
+    await Promise.all([parentA11yInit, contentA11yInit]);
 
     info('Adding additional reference to accessibility service in content ' +
       'process');
     // Add a new reference to the a11y service inside the content process.
     loadFrameScripts(browser, `let accService = Components.classes[
       '@mozilla.org/accessibilityService;1'].getService(
         Components.interfaces.nsIAccessibilityService);`);
 
@@ -47,26 +47,26 @@ add_task(function* () {
       shutdownPromise(browser).then(flag => contentCanShutdown ?
         resolve() : reject('Accessible service was shut down incorrectly')));
     // Remove a11y service reference in content and force garbage collection.
     // This should not trigger shutdown since a11y was originally initialized by
     // the main process.
     loadFrameScripts(browser, `accService = null; Components.utils.forceGC();`);
 
     // Have some breathing room between a11y service shutdowns.
-    yield new Promise(resolve => executeSoon(resolve));
+    await new Promise(resolve => executeSoon(resolve));
 
     info('Removing a service in parent');
     // Now allow a11y service to shutdown in content.
     contentCanShutdown = true;
     // Remove the a11y service reference in the main process.
     let parentA11yShutdown = shutdownPromise();
     accService = null;
     ok(!accService, 'Service is removed in parent');
     // Force garbage collection that should trigger shutdown in both parent and
     // content.
     forceGC();
-    yield Promise.all([parentA11yShutdown, contentA11yShutdown]);
+    await Promise.all([parentA11yShutdown, contentA11yShutdown]);
 
     // Unsetting e10s related preferences.
-    yield unsetE10sPrefs();
+    await unsetE10sPrefs();
   });
 });
--- a/accessible/tests/browser/browser_shutdown_proxy_acc_reference.js
+++ b/accessible/tests/browser/browser_shutdown_proxy_acc_reference.js
@@ -1,38 +1,38 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Making sure that the e10s is enabled on Windows for testing.
-  yield setE10sPrefs();
+  await setE10sPrefs();
 
   let a11yInit = initPromise();
   let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
   ok(accService, 'Service initialized');
-  yield a11yInit;
+  await a11yInit;
 
-  yield BrowserTestUtils.withNewTab({
+  await BrowserTestUtils.withNewTab({
     gBrowser,
     url: `data:text/html,
       <html>
         <head>
           <meta charset="utf-8"/>
           <title>Accessibility Test</title>
         </head>
         <body><div id="div" style="visibility: hidden;"></div></body>
       </html>`
-  }, function*(browser) {
+  }, async function(browser) {
     let onShow = waitForEvent(Ci.nsIAccessibleEvent.EVENT_SHOW, 'div');
-    yield invokeSetStyle(browser, 'div', 'visibility', 'visible');
-    let showEvent = yield onShow;
+    await invokeSetStyle(browser, 'div', 'visibility', 'visible');
+    let showEvent = await onShow;
     let divAcc = showEvent.accessible;
     ok(divAcc, 'Accessible proxy is created');
     // Remove unnecessary dangling references
     onShow = null;
     showEvent = null;
     forceGC();
 
     let canShutdown = false;
@@ -41,24 +41,24 @@ add_task(function* () {
       reject('Accessible service was shut down incorrectly')));
 
     accService = null;
     ok(!accService, 'Service is removed');
     // Force garbage collection that should not trigger shutdown because there
     // is a reference to an accessible proxy.
     forceGC();
     // Have some breathing room when removing a11y service references.
-    yield new Promise(resolve => executeSoon(resolve));
+    await new Promise(resolve => executeSoon(resolve));
 
     // Now allow a11y service to shutdown.
     canShutdown = true;
     // Remove a last reference to an accessible proxy.
     divAcc = null;
     ok(!divAcc, 'Accessible proxy is removed');
 
     // Force garbage collection that should now trigger shutdown.
     forceGC();
-    yield a11yShutdown;
+    await a11yShutdown;
   });
 
   // Unsetting e10s related preferences.
-  yield unsetE10sPrefs();
+  await unsetE10sPrefs();
 });
--- a/accessible/tests/browser/browser_shutdown_proxy_doc_acc_reference.js
+++ b/accessible/tests/browser/browser_shutdown_proxy_doc_acc_reference.js
@@ -1,38 +1,38 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Making sure that the e10s is enabled on Windows for testing.
-  yield setE10sPrefs();
+  await setE10sPrefs();
 
   let docLoaded = waitForEvent(
     Ci.nsIAccessibleEvent.EVENT_DOCUMENT_LOAD_COMPLETE, 'body');
   let a11yInit = initPromise();
   let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
   ok(accService, 'Service initialized');
-  yield a11yInit;
+  await a11yInit;
 
-  yield BrowserTestUtils.withNewTab({
+  await BrowserTestUtils.withNewTab({
     gBrowser,
     url: `data:text/html,
       <html>
         <head>
           <meta charset="utf-8"/>
           <title>Accessibility Test</title>
         </head>
         <body id="body"></body>
       </html>`
-  }, function*(browser) {
-    let docLoadedEvent = yield docLoaded;
+  }, async function(browser) {
+    let docLoadedEvent = await docLoaded;
     let docAcc = docLoadedEvent.accessibleDocument;
     ok(docAcc, 'Accessible document proxy is created');
     // Remove unnecessary dangling references
     docLoaded = null;
     docLoadedEvent = null;
     forceGC();
 
     let canShutdown = false;
@@ -41,24 +41,24 @@ add_task(function* () {
       reject('Accessible service was shut down incorrectly')));
 
     accService = null;
     ok(!accService, 'Service is removed');
     // Force garbage collection that should not trigger shutdown because there
     // is a reference to an accessible proxy.
     forceGC();
     // Have some breathing room when removing a11y service references.
-    yield new Promise(resolve => executeSoon(resolve));
+    await new Promise(resolve => executeSoon(resolve));
 
     // Now allow a11y service to shutdown.
     canShutdown = true;
     // Remove a last reference to an accessible document proxy.
     docAcc = null;
     ok(!docAcc, 'Accessible document proxy is removed');
 
     // Force garbage collection that should now trigger shutdown.
     forceGC();
-    yield a11yShutdown;
+    await a11yShutdown;
   });
 
   // Unsetting e10s related preferences.
-  yield unsetE10sPrefs();
+  await unsetE10sPrefs();
 });
--- a/accessible/tests/browser/browser_shutdown_remote_no_reference.js
+++ b/accessible/tests/browser/browser_shutdown_remote_no_reference.js
@@ -1,48 +1,48 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Making sure that the e10s is enabled on Windows for testing.
-  yield setE10sPrefs();
+  await setE10sPrefs();
 
-  yield BrowserTestUtils.withNewTab({
+  await BrowserTestUtils.withNewTab({
     gBrowser,
     url: `data:text/html,
       <html>
         <head>
           <meta charset="utf-8"/>
           <title>Accessibility Test</title>
         </head>
         <body></body>
       </html>`
-  }, function*(browser) {
+  }, async function(browser) {
     info('Creating a service in parent and waiting for service to be created ' +
       'in content');
     // Create a11y service in the main process. This will trigger creating of
     // the a11y service in parent as well.
     let parentA11yInit = initPromise();
     let contentA11yInit = initPromise(browser);
     let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
       Ci.nsIAccessibilityService);
     ok(accService, 'Service initialized in parent');
-    yield Promise.all([parentA11yInit, contentA11yInit]);
+    await Promise.all([parentA11yInit, contentA11yInit]);
 
     info('Removing a service in parent and waiting for service to be shut ' +
       'down in content');
     // Remove a11y service reference in the main process.
     let parentA11yShutdown = shutdownPromise();
     let contentA11yShutdown = shutdownPromise(browser);
     accService = null;
     ok(!accService, 'Service is removed in parent');
     // Force garbage collection that should trigger shutdown in both main and
     // content process.
     forceGC();
-    yield Promise.all([parentA11yShutdown, contentA11yShutdown]);
+    await Promise.all([parentA11yShutdown, contentA11yShutdown]);
   });
 
   // Unsetting e10s related preferences.
-  yield unsetE10sPrefs();
+  await unsetE10sPrefs();
 });
--- a/accessible/tests/browser/browser_shutdown_remote_only.js
+++ b/accessible/tests/browser/browser_shutdown_remote_only.js
@@ -1,40 +1,40 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Making sure that the e10s is enabled on Windows for testing.
-  yield setE10sPrefs();
+  await setE10sPrefs();
 
-  yield BrowserTestUtils.withNewTab({
+  await BrowserTestUtils.withNewTab({
     gBrowser,
     url: `data:text/html,
       <html>
         <head>
           <meta charset="utf-8"/>
           <title>Accessibility Test</title>
         </head>
         <body></body>
       </html>`
-  }, function*(browser) {
+  }, async function(browser) {
     info('Creating a service in content');
     // Create a11y service in the content process.
     let a11yInit = initPromise(browser);
     loadFrameScripts(browser, `let accService = Components.classes[
       '@mozilla.org/accessibilityService;1'].getService(
         Components.interfaces.nsIAccessibilityService);`);
-    yield a11yInit;
+    await a11yInit;
 
     info('Removing a service in content');
     // Remove a11y service reference from the content process.
     let a11yShutdown = shutdownPromise(browser);
     // Force garbage collection that should trigger shutdown.
     loadFrameScripts(browser, `accService = null; Components.utils.forceGC();`);
-    yield a11yShutdown;
+    await a11yShutdown;
 
     // Unsetting e10s related preferences.
-    yield unsetE10sPrefs();
+    await unsetE10sPrefs();
   });
 });
--- a/accessible/tests/browser/browser_shutdown_remote_own_reference.js
+++ b/accessible/tests/browser/browser_shutdown_remote_own_reference.js
@@ -1,39 +1,39 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Making sure that the e10s is enabled on Windows for testing.
-  yield setE10sPrefs();
+  await setE10sPrefs();
 
-  yield BrowserTestUtils.withNewTab({
+  await BrowserTestUtils.withNewTab({
     gBrowser,
     url: `data:text/html,
       <html>
         <head>
           <meta charset="utf-8"/>
           <title>Accessibility Test</title>
         </head>
         <body></body>
       </html>`
-  }, function*(browser) {
+  }, async function(browser) {
     info('Creating a service in parent and waiting for service to be created ' +
       'in content');
     // Create a11y service in the main process. This will trigger creating of
     // the a11y service in parent as well.
     let parentA11yInit = initPromise();
     let contentA11yInit = initPromise(browser);
     let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
       Ci.nsIAccessibilityService);
     ok(accService, 'Service initialized in parent');
-    yield Promise.all([parentA11yInit, contentA11yInit]);
+    await Promise.all([parentA11yInit, contentA11yInit]);
 
     info('Adding additional reference to accessibility service in content ' +
       'process');
     // Add a new reference to the a11y service inside the content process.
     loadFrameScripts(browser, `let accService = Components.classes[
       '@mozilla.org/accessibilityService;1'].getService(
         Components.interfaces.nsIAccessibilityService);`);
 
@@ -51,25 +51,25 @@ add_task(function* () {
     // collection. This should not trigger shutdown in content since a11y
     // service is used by XPCOM.
     accService = null;
     ok(!accService, 'Service is removed in parent');
     // Force garbage collection that should not trigger shutdown because there
     // is a reference in a content process.
     forceGC();
     loadFrameScripts(browser, `Components.utils.forceGC();`);
-    yield parentA11yShutdown;
+    await parentA11yShutdown;
 
     // Have some breathing room between a11y service shutdowns.
-    yield new Promise(resolve => executeSoon(resolve));
+    await new Promise(resolve => executeSoon(resolve));
 
     info('Removing a service in content');
     // Now allow a11y service to shutdown in content.
     contentCanShutdown = true;
     // Remove last reference to a11y service in content and force garbage
     // collection that should trigger shutdown.
     loadFrameScripts(browser, `accService = null; Components.utils.forceGC();`);
-    yield contentA11yShutdown;
+    await contentA11yShutdown;
 
     // Unsetting e10s related preferences.
-    yield unsetE10sPrefs();
+    await unsetE10sPrefs();
   });
 });
--- a/accessible/tests/browser/browser_shutdown_scope_lifecycle.js
+++ b/accessible/tests/browser/browser_shutdown_scope_lifecycle.js
@@ -1,21 +1,21 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   // Create a11y service inside of the function scope. Its reference should be
   // released once the anonimous function is called.
   let a11yInitThenShutdown = initPromise().then(shutdownPromise);
 
   (function() {
     let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
       Ci.nsIAccessibilityService);
     ok(accService, 'Service initialized');
   })();
 
   // Force garbage collection that should trigger shutdown.
   forceGC();
-  yield a11yInitThenShutdown;
+  await a11yInitThenShutdown;
 });
--- a/accessible/tests/browser/browser_shutdown_start_restart.js
+++ b/accessible/tests/browser/browser_shutdown_start_restart.js
@@ -1,41 +1,41 @@
 /* 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';
 
-add_task(function* () {
+add_task(async function () {
   info('Creating a service');
   // Create a11y service.
   let a11yInit = initPromise();
   let accService = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
-  yield a11yInit;
+  await a11yInit;
   ok(accService, 'Service initialized');
 
   info('Removing a service');
   // Remove the only reference to an a11y service.
   let a11yShutdown = shutdownPromise();
   accService = null;
   ok(!accService, 'Service is removed');
   // Force garbage collection that should trigger shutdown.
   forceGC();
-  yield a11yShutdown;
+  await a11yShutdown;
 
   info('Recreating a service');
   // Re-create a11y service.
   a11yInit = initPromise();
   accService = Cc['@mozilla.org/accessibilityService;1'].getService(
     Ci.nsIAccessibilityService);
-  yield a11yInit;
+  await a11yInit;
   ok(accService, 'Service initialized again');
 
   info('Removing a service again');
   // Remove the only reference to an a11y service again.
   a11yShutdown = shutdownPromise();
   accService = null;
   ok(!accService, 'Service is removed again');
   // Force garbage collection that should trigger shutdown.
   forceGC();
-  yield a11yShutdown;
+  await a11yShutdown;
 });
--- a/accessible/tests/browser/e10s/browser_caching_attributes.js
+++ b/accessible/tests/browser/e10s/browser_caching_attributes.js
@@ -20,39 +20,39 @@ const defaultAttributes = {
   'id': 'textbox',
   'tag': 'input',
   'display': 'inline'
 };
 
 /**
  * Test data has the format of:
  * {
- *   desc        {String}       description for better logging
- *   expected    {Object}       expected attributes for given accessibles
- *   unexpected  {Object}       unexpected attributes for given accessibles
+ *   desc        {String}         description for better logging
+ *   expected    {Object}         expected attributes for given accessibles
+ *   unexpected  {Object}         unexpected attributes for given accessibles
  *
- *   action      {?Function*}   an optional action that yields a change in
- *                              attributes
- *   attrs       {?Array}       an optional list of attributes to update
- *   waitFor     {?Number}      an optional event to wait for
+ *   action      {?AsyncFunction} an optional action that awaits a change in
+ *                                attributes
+ *   attrs       {?Array}         an optional list of attributes to update
+ *   waitFor     {?Number}        an optional event to wait for
  * }
  */
 const attributesTests = [{
   desc: 'Initiall accessible attributes',
   expected: defaultAttributes,
   unexpected: {
     'line-number': '1',
     'explicit-name': 'true',
     'container-live': 'polite',
     'live': 'polite'
   }
 }, {
   desc: '@line-number attribute is present when textbox is focused',
-  action: function*(browser) {
-    yield invokeFocus(browser, 'textbox');
+  action: async function(browser) {
+    await invokeFocus(browser, 'textbox');
   },
   waitFor: EVENT_FOCUS,
   expected: Object.assign({}, defaultAttributes, { 'line-number': '1' }),
   unexpected: {
     'explicit-name': 'true',
     'container-live': 'polite',
     'live': 'polite'
   }
@@ -85,32 +85,32 @@ const attributesTests = [{
   unexpected: {}
 }];
 
 /**
  * Test caching of accessible object attributes
  */
 addAccessibleTask(`
   <input id="textbox" value="hello">`,
-  function* (browser, accDoc) {
+  async function (browser, accDoc) {
     let textbox = findAccessibleChildByID(accDoc, 'textbox');
     for (let { desc, action, attrs, expected, waitFor, unexpected } of attributesTests) {
       info(desc);
       let onUpdate;
 
       if (waitFor) {
         onUpdate = waitForEvent(waitFor, 'textbox');
       }
 
       if (action) {
-        yield action(browser);
+        await action(browser);
       } else if (attrs) {
         for (let { attr, value } of attrs) {
-          yield invokeSetAttribute(browser, 'textbox', attr, value);
+          await invokeSetAttribute(browser, 'textbox', attr, value);
         }
       }
 
-      yield onUpdate;
+      await onUpdate;
       testAttrs(textbox, expected);
       testAbsentAttrs(textbox, unexpected);
     }
   }
 );
--- a/accessible/tests/browser/e10s/browser_caching_description.js
+++ b/accessible/tests/browser/e10s/browser_caching_description.js
@@ -132,31 +132,31 @@ const tests = [{
 
 /**
  * Test caching of accessible object description
  */
 addAccessibleTask(`
   <p id="description">aria description</p>
   <p id="description2">another description</p>
   <img id="image" />`,
-  function*(browser, accDoc) {
+  async function(browser, accDoc) {
     let imgAcc = findAccessibleChildByID(accDoc, 'image');
 
     for (let { desc, waitFor, attrs, expected } of tests) {
       info(desc);
       let onUpdate;
       if (waitFor) {
         onUpdate = waitForMultipleEvents(waitFor);
       }
       if (attrs) {
         for (let { attr, value } of attrs) {
-          yield invokeSetAttribute(browser, 'image', attr, value);
+          await invokeSetAttribute(browser, 'image', attr, value);
         }
       }
-      yield onUpdate;
+      await onUpdate;
       // When attribute change (alt) triggers reorder event, accessible will
       // become defunct.
       if (isDefunct(imgAcc)) {
         imgAcc = findAccessibleChildByID(accDoc, 'image');
       }
       testDescr(imgAcc, expected);
     }
   }
--- a/accessible/tests/browser/e10s/browser_caching_name.js
+++ b/accessible/tests/browser/e10s/browser_caching_name.js
@@ -313,18 +313,18 @@ const markupTests = [{
 /**
  * Wait for an accessible event to happen and, in case given accessible is
  * defunct, update it to one that is attached to the accessible event.
  * @param {Promise} onEvent      accessible event promise
  * @param {Object}  target       { acc, parent, id } structure that contains an
  *                                accessible, its parent and its content element
  *                                id.
  */
-function* updateAccessibleIfNeeded(onEvent, target) {
-  let event = yield onEvent;
+async function updateAccessibleIfNeeded(onEvent, target) {
+  let event = await onEvent;
   if (isDefunct(target.acc)) {
     target.acc = findAccessibleChildByID(event.accessible, target.id);
   }
 }
 
 /**
  * Test accessible name that is calculated from an attribute, remove the
  * attribute before proceeding to the next name test. If attribute removal
@@ -333,101 +333,101 @@ function* updateAccessibleIfNeeded(onEve
  * of the above events.
  * @param {Object} browser      current "tabbrowser" element
  * @param {Object} target       { acc, parent, id } structure that contains an
  *                               accessible, its parent and its content element
  *                               id.
  * @param {Object} rule         current attr rule for name calculation
  * @param {[type]} expected     expected name value
  */
-function* testAttrRule(browser, target, rule, expected) {
+async function testAttrRule(browser, target, rule, expected) {
   testName(target.acc, expected);
   let onEvent;
   if (rule.recreated) {
     onEvent = waitForEvent(EVENT_REORDER, target.parent);
   } else if (rule.textchanged) {
     onEvent = waitForEvent(EVENT_TEXT_INSERTED, target.id);
   }
-  yield invokeSetAttribute(browser, target.id, rule.attr);
+  await invokeSetAttribute(browser, target.id, rule.attr);
   if (onEvent) {
-    yield updateAccessibleIfNeeded(onEvent, target);
+    await updateAccessibleIfNeeded(onEvent, target);
   }
 }
 
 /**
  * Test accessible name that is calculated from an element name, remove the
  * element before proceeding to the next name test. If element removal results
  * in a reorder event - wait for it. If accessible becomes defunct, update its
  * reference using the one that is attached to a possible reorder event.
  * @param {Object} browser      current "tabbrowser" element
  * @param {Object} target       { acc, parent, id } structure that contains an
  *                               accessible, its parent and its content element
  *                               id.
  * @param {Object} rule         current elm rule for name calculation
  * @param {[type]} expected     expected name value
  */
-function* testElmRule(browser, target, rule, expected) {
+async function testElmRule(browser, target, rule, expected) {
   testName(target.acc, expected);
   let onEvent = waitForEvent(EVENT_REORDER, rule.isSibling ?
     target.parent : target.id);
-  yield ContentTask.spawn(browser, rule.elm, elm =>
+  await ContentTask.spawn(browser, rule.elm, elm =>
     content.document.querySelector(`${elm}`).remove());
-  yield updateAccessibleIfNeeded(onEvent, target);
+  await updateAccessibleIfNeeded(onEvent, target);
 }
 
 /**
  * Test accessible name that is calculated from its subtree, remove the subtree
  * and wait for a reorder event before proceeding to the next name test. If
  * accessible becomes defunct, update its reference using the one that is
  * attached to a reorder event.
  * @param {Object} browser      current "tabbrowser" element
  * @param {Object} target       { acc, parent, id } structure that contains an
  *                               accessible, its parent and its content element
  *                               id.
  * @param {Object} rule         current subtree rule for name calculation
  * @param {[type]} expected     expected name value
  */
-function* testSubtreeRule(browser, target, rule, expected) {
+async function testSubtreeRule(browser, target, rule, expected) {
   testName(target.acc, expected);
   let onEvent = waitForEvent(EVENT_REORDER, target.id);
-  yield ContentTask.spawn(browser, target.id, id => {
+  await ContentTask.spawn(browser, target.id, id => {
     let elm = content.document.getElementById(id);
     while (elm.firstChild) {
       elm.firstChild.remove();
     }
   });
-  yield updateAccessibleIfNeeded(onEvent, target);
+  await updateAccessibleIfNeeded(onEvent, target);
 }
 
 /**
  * Iterate over a list of rules and test accessible names for each one of the
  * rules.
  * @param {Object} browser      current "tabbrowser" element
  * @param {Object} target       { acc, parent, id } structure that contains an
  *                               accessible, its parent and its content element
  *                               id.
  * @param {Array}  ruleset      A list of rules to test a target with
  * @param {Array}  expected     A list of expected name value for each rule
  */
-function* testNameRule(browser, target, ruleset, expected) {
+async function testNameRule(browser, target, ruleset, expected) {
   for (let i = 0; i < ruleset.length; ++i) {
     let rule = ruleset[i];
     let testFn;
     if (rule.attr) {
       testFn = testAttrRule;
     } else if (rule.elm) {
       testFn = testElmRule;
     } else if (rule.fromsubtree) {
       testFn = testSubtreeRule;
     }
-    yield testFn(browser, target, rule, expected[i]);
+    await testFn(browser, target, rule, expected[i]);
   }
 }
 
 markupTests.forEach(({ id, ruleset, markup, expected }) =>
-  addAccessibleTask(markup, function*(browser, accDoc) {
+  addAccessibleTask(markup, async function(browser, accDoc) {
     // Find a target accessible from an accessible subtree.
     let acc = findAccessibleChildByID(accDoc, id);
     // Find target's parent accessible from an accessible subtree.
     let parent = getAccessibleDOMNodeID(acc.parent);
     let target = { id, parent, acc };
-    yield testNameRule(browser, target, rules[ruleset], expected);
+    await testNameRule(browser, target, rules[ruleset], expected);
   }));
--- a/accessible/tests/browser/e10s/browser_caching_relations.js
+++ b/accessible/tests/browser/e10s/browser_caching_relations.js
@@ -17,17 +17,17 @@ loadScripts({ name: 'relations.js', dir:
  */
 const attrRelationsSpec = [
   ['aria-labelledby', RELATION_LABELLED_BY, RELATION_LABEL_FOR],
   ['aria-describedby', RELATION_DESCRIBED_BY, RELATION_DESCRIPTION_FOR],
   ['aria-controls', RELATION_CONTROLLER_FOR, RELATION_CONTROLLED_BY],
   ['aria-flowto', RELATION_FLOWS_TO, RELATION_FLOWS_FROM]
 ];
 
-function* testRelated(browser, accDoc, attr, hostRelation, dependantRelation) {
+async function testRelated(browser, accDoc, attr, hostRelation, dependantRelation) {
   let host = findAccessibleChildByID(accDoc, 'host');
   let dependant1 = findAccessibleChildByID(accDoc, 'dependant1');
   let dependant2 = findAccessibleChildByID(accDoc, 'dependant2');
 
   /**
    * Test data has the format of:
    * {
    *   desc      {String}   description for better logging
@@ -53,31 +53,31 @@ function* testRelated(browser, accDoc, a
     expected: [ null, null, null ]
   }];
 
   for (let { desc, attrs, expected } of tests) {
     info(desc);
 
     if (attrs) {
       for (let { key, value } of attrs) {
-        yield invokeSetAttribute(browser, 'host', key, value);
+        await invokeSetAttribute(browser, 'host', key, value);
       }
     }
 
     testRelation(dependant1, dependantRelation, expected[0]);
     testRelation(dependant2, dependantRelation, expected[1]);
     testRelation(host, hostRelation, expected[2]);
   }
 }
 
 /**
  * Test caching of relations between accessible objects.
  */
 addAccessibleTask(`
   <div id="dependant1">label</div>
   <div id="dependant2">label2</div>
   <div role="checkbox" id="host"></div>`,
-  function* (browser, accDoc) {
+  async function (browser, accDoc) {
     for (let spec of attrRelationsSpec) {
-      yield testRelated(browser, accDoc, ...spec);
+      await testRelated(browser, accDoc, ...spec);
     }
   }
 );
--- a/accessible/tests/browser/e10s/browser_caching_states.js
+++ b/accessible/tests/browser/e10s/browser_caching_states.js
@@ -86,34 +86,34 @@ const extraStateTests = [{
   attrs: [{
     attr: 'aria-disabled'
   }, {
     attr: 'disabled'
   }],
   expected: [0, EXT_STATE_ENABLED]
 }];
 
-function* runStateTests(browser, accDoc, id, tests) {
+async function runStateTests(browser, accDoc, id, tests) {
   let acc = findAccessibleChildByID(accDoc, id);
   for (let { desc, attrs, expected } of tests) {
     info(desc);
     let onUpdate = waitForEvent(EVENT_STATE_CHANGE, id);
     for (let { attr, value } of attrs) {
-      yield invokeSetAttribute(browser, id, attr, value);
+      await invokeSetAttribute(browser, id, attr, value);
     }
-    yield onUpdate;
+    await onUpdate;
     testStates(acc, ...expected);
   }
 }
 
 /**
  * Test caching of accessible object states
  */
 addAccessibleTask(`
   <input id="checkbox" type="checkbox">
   <input id="file" type="file">
   <input id="text">`,
-  function* (browser, accDoc) {
-    yield runStateTests(browser, accDoc, 'checkbox', attributeTests);
-    yield runStateTests(browser, accDoc, 'file', ariaTests);
-    yield runStateTests(browser, accDoc, 'text', extraStateTests);
+  async function (browser, accDoc) {
+    await runStateTests(browser, accDoc, 'checkbox', attributeTests);
+    await runStateTests(browser, accDoc, 'file', ariaTests);
+    await runStateTests(browser, accDoc, 'text', extraStateTests);
   }
 );
--- a/accessible/tests/browser/e10s/browser_caching_value.js
+++ b/accessible/tests/browser/e10s/browser_caching_value.js
@@ -5,34 +5,34 @@
 'use strict';
 
 /* import-globals-from ../../mochitest/value.js */
 loadScripts({ name: 'value.js', dir: MOCHITESTS_DIR });
 
 /**
  * Test data has the format of:
  * {
- *   desc      {String}       description for better logging
- *   id        {String}       given accessible DOMNode ID
- *   expected  {String}       expected value for a given accessible
- *   action    {?Function*}   an optional action that yields a value change
- *   attrs     {?Array}       an optional list of attributes to update
- *   waitFor   {?Number}      an optional value change event to wait for
+ *   desc      {String}            description for better logging
+ *   id        {String}            given accessible DOMNode ID
+ *   expected  {String}            expected value for a given accessible
+ *   action    {?AsyncFunction}    an optional action that awaits a value change
+ *   attrs     {?Array}            an optional list of attributes to update
+ *   waitFor   {?Number}           an optional value change event to wait for
  * }
  */
 const valueTests = [{
   desc: 'Initially value is set to 1st element of select',
   id: 'select',
   expected: '1st'
 }, {
   desc: 'Value should update to 3rd when 3 is pressed',
   id: 'select',
-  action: function*(browser) {
-    yield invokeFocus(browser, 'select');
-    yield BrowserTestUtils.synthesizeKey('3', {}, browser);
+  action: async function(browser) {
+    await invokeFocus(browser, 'select');
+    await BrowserTestUtils.synthesizeKey('3', {}, browser);
   },
   waitFor: EVENT_TEXT_VALUE_CHANGE,
   expected: '3rd'
 }, {
   desc: 'Initially value is set to @aria-valuenow for slider',
   id: 'slider',
   expected: ['5', 5, 0, 7, 0]
 }, {
@@ -97,19 +97,19 @@ const valueTests = [{
   expected: '50%'
 }, {
   desc: 'Initially value corresponds to @value attribute for range',
   id: 'range',
   expected: '6'
 }, {
   desc: 'Value should change when slider is moved',
   id: 'range',
-  action: function*(browser) {
-    yield invokeFocus(browser, 'range');
-    yield BrowserTestUtils.synthesizeKey('VK_LEFT', {}, browser);
+  action: async function(browser) {
+    await invokeFocus(browser, 'range');
+    await BrowserTestUtils.synthesizeKey('VK_LEFT', {}, browser);
   },
   waitFor: EVENT_VALUE_CHANGE,
   expected: '5'
 }];
 
 /**
  * Test caching of accessible object values
  */
@@ -119,35 +119,35 @@ addAccessibleTask(`
   <select id="select">
     <option>1st</option>
     <option>2nd</option>
     <option>3rd</option>
   </select>
   <input id="combobox" role="combobox" aria-autocomplete="inline">
   <progress id="progress" value="22" max="100"></progress>
   <input type="range" id="range" min="0" max="10" value="6">`,
-  function* (browser, accDoc) {
+  async function (browser, accDoc) {
     for (let { desc, id, action, attrs, expected, waitFor } of valueTests) {
       info(desc);
       let acc = findAccessibleChildByID(accDoc, id);
       let onUpdate;
 
       if (waitFor) {
         onUpdate = waitForEvent(waitFor, id);
       }
 
       if (action) {
-        yield action(browser);
+        await action(browser);
       } else if (attrs) {
         for (let { attr, value } of attrs) {
-          yield invokeSetAttribute(browser, id, attr, value);
+          await invokeSetAttribute(browser, id, attr, value);
         }
       }
 
-      yield onUpdate;
+      await onUpdate;
       if (Array.isArray(expected)) {
         acc.QueryInterface(nsIAccessibleValue);
         testValue(acc, ...expected);
       } else {
         is(acc.value, expected, `Correct value for ${prettyName(acc)}`);
       }
     }
   }
--- a/accessible/tests/browser/e10s/browser_events_caretmove.js
+++ b/accessible/tests/browser/e10s/browser_events_caretmove.js
@@ -3,17 +3,17 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 'use strict';
 
 /**
  * Test caret move event and its interface:
  *   - caretOffset
  */
-addAccessibleTask('<input id="textbox" value="hello"/>', function*(browser) {
+addAccessibleTask('<input id="textbox" value="hello"/>', async function(browser) {
   let onCaretMoved = waitForEvent(EVENT_TEXT_CARET_MOVED, 'textbox');
-  yield invokeFocus(browser, 'textbox');
-  let event = yield onCaretMoved;
+  await invokeFocus(browser, 'textbox');
+  let event = await onCaretMoved;
 
   let caretMovedEvent = event.QueryInterface(nsIAccessibleCaretMoveEvent);
   is(caretMovedEvent.caretOffset, 5,
     'Correct caret offset.');
 });
--- a/accessible/tests/browser/e10s/browser_events_hide.js
+++ b/accessible/tests/browser/e10s/browser_events_hide.js
@@ -11,21 +11,21 @@
  *   - targetPrevSibling
  */
 addAccessibleTask(`
   <div id="parent">
     <div id="previous"></div>
     <div id="to-hide"></div>
     <div id="next"></div>
   </div>`,
-  function*(browser, accDoc) {
+  async function(browser, accDoc) {
     let acc = findAccessibleChildByID(accDoc, 'to-hide');
     let onHide = waitForEvent(EVENT_HIDE, acc);
-    yield invokeSetStyle(browser, 'to-hide', 'visibility', 'hidden');
-    let event = yield onHide;
+    await invokeSetStyle(browser, 'to-hide', 'visibility', 'hidden');
+    let event = await onHide;
     let hideEvent = event.QueryInterface(Ci.nsIAccessibleHideEvent);
 
     is(getAccessibleDOMNodeID(hideEvent.targetParent), 'parent',
       'Correct target parent.');
     is(getAccessibleDOMNodeID(hideEvent.targetNextSibling), 'next',
       'Correct target next sibling.');
     is(getAccessibleDOMNodeID(hideEvent.targetPrevSibling), 'previous',
       'Correct target previous sibling.');
--- a/accessible/tests/browser/e10s/browser_events_show.js
+++ b/accessible/tests/browser/e10s/browser_events_show.js
@@ -3,13 +3,13 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 'use strict';
 
 /**
  * Test show event
  */
 addAccessibleTask('<div id="div" style="visibility: hidden;"></div>',
-  function*(browser) {
+  async function(browser) {
     let onShow = waitForEvent(EVENT_SHOW, 'div');
-    yield invokeSetStyle(browser, 'div', 'visibility', 'visible');
-    yield onShow;
+    await invokeSetStyle(browser, 'div', 'visibility', 'visible');
+    await onShow;
   });
--- a/accessible/tests/browser/e10s/browser_events_statechange.js
+++ b/accessible/tests/browser/e10s/browser_events_statechange.js
@@ -31,31 +31,31 @@ let iframeSrc = `data:text/html,
 /**
  * Test state change event and its interface:
  *   - state
  *   - isExtraState
  *   - isEnabled
  */
 addAccessibleTask(`
   <iframe id="iframe" src="${iframeSrc}"></iframe>
-  <input id="checkbox" type="checkbox" />`, function*(browser) {
+  <input id="checkbox" type="checkbox" />`, async function(browser) {
   // Test state change
   let onStateChange = waitForEvent(EVENT_STATE_CHANGE, 'checkbox');
   // Set checked for a checkbox.
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     content.document.getElementById('checkbox').checked = true;
   });
-  let event = yield onStateChange;
+  let event = await onStateChange;
 
   checkStateChangeEvent(event, STATE_CHECKED, false, true);
   testStates(event.accessible, STATE_CHECKED, 0);
 
   // Test extra state
   onStateChange = waitForEvent(EVENT_STATE_CHANGE, 'iframe');
   // Set design mode on.
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     content.document.getElementById('iframe').contentDocument.designMode = 'on';
   });
-  event = yield onStateChange;
+  event = await onStateChange;
 
   checkStateChangeEvent(event, EXT_STATE_EDITABLE, true, true);
   testStates(event.accessible, 0, EXT_STATE_EDITABLE);
 });
--- a/accessible/tests/browser/e10s/browser_events_textchange.js
+++ b/accessible/tests/browser/e10s/browser_events_textchange.js
@@ -10,62 +10,62 @@ function checkTextChangeEvent(event, id,
   is(tcEvent.length, end - start, `Correct length for ${prettyName(id)}`);
   is(tcEvent.isInserted, isInserted,
     `Correct isInserted flag for ${prettyName(id)}`);
   is(tcEvent.modifiedText, text, `Correct text for ${prettyName(id)}`);
   is(tcEvent.isFromUserInput, isFromUserInput,
     `Correct value of isFromUserInput for ${prettyName(id)}`);
 }
 
-function* changeText(browser, id, value, events) {
+async function changeText(browser, id, value, events) {
   let onEvents = waitForMultipleEvents(events.map(({ isInserted }) => {
     let eventType = isInserted ? EVENT_TEXT_INSERTED : EVENT_TEXT_REMOVED;
     return { id, eventType };
   }));
   // Change text in the subtree.
-  yield ContentTask.spawn(browser, [id, value], ([contentId, contentValue]) => {
+  await ContentTask.spawn(browser, [id, value], ([contentId, contentValue]) => {
     content.document.getElementById(contentId).firstChild.textContent =
       contentValue;
   });
-  let resolvedEvents = yield onEvents;
+  let resolvedEvents = await onEvents;
 
   events.forEach(({ isInserted, str, offset }, idx) =>
     checkTextChangeEvent(resolvedEvents[idx],
       id, str, offset, offset + str.length, isInserted, false));
 }
 
-function* removeTextFromInput(browser, id, value, start, end) {
+async function removeTextFromInput(browser, id, value, start, end) {
   let onTextRemoved = waitForEvent(EVENT_TEXT_REMOVED, id);
   // Select text and delete it.
-  yield ContentTask.spawn(browser, [id, start, end], ([contentId, contentStart, contentEnd]) => {
+  await ContentTask.spawn(browser, [id, start, end], ([contentId, contentStart, contentEnd]) => {
     let el = content.document.getElementById(contentId);
     el.focus();
     el.setSelectionRange(contentStart, contentEnd);
   });
-  yield BrowserTestUtils.sendChar('VK_DELETE', browser);
+  await BrowserTestUtils.sendChar('VK_DELETE', browser);
 
-  let event = yield onTextRemoved;
+  let event = await onTextRemoved;
   checkTextChangeEvent(event, id, value, start, end, false, true);
 }
 
 /**
  * Test text change event and its interface:
  *   - start
  *   - length
  *   - isInserted
  *   - modifiedText
  *   - isFromUserInput
  */
 addAccessibleTask(`
   <p id="p">abc</p>
-  <input id="input" value="input" />`, function*(browser) {
+  <input id="input" value="input" />`, async function(browser) {
   let events = [
     { isInserted: false, str: 'abc', offset: 0 },
     { isInserted: true, str: 'def', offset: 0 }
   ];
-  yield changeText(browser, 'p', 'def', events);
+  await changeText(browser, 'p', 'def', events);
 
   events = [{ isInserted: true, str: 'DEF', offset: 2 }];
-  yield changeText(browser, 'p', 'deDEFf', events);
+  await changeText(browser, 'p', 'deDEFf', events);
 
   // Test isFromUserInput property.
-  yield removeTextFromInput(browser, 'input', 'n', 1, 2);
+  await removeTextFromInput(browser, 'input', 'n', 1, 2);
 });
--- a/accessible/tests/browser/e10s/browser_treeupdate_ariadialog.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_ariadialog.js
@@ -3,28 +3,28 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 'use strict';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
 // Test ARIA Dialog
-addAccessibleTask('doc_treeupdate_ariadialog.html', function*(browser, accDoc) {
+addAccessibleTask('doc_treeupdate_ariadialog.html', async function(browser, accDoc) {
   testAccessibleTree(accDoc, {
     role: ROLE_DOCUMENT,
     children: [ ]
   });
 
   // Make dialog visible and update its inner content.
   let onShow = waitForEvent(EVENT_SHOW, 'dialog');
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     content.document.getElementById('dialog').style.display = 'block';
   });
-  yield onShow;
+  await onShow;
 
   testAccessibleTree(accDoc, {
     role: ROLE_DOCUMENT,
     children: [
       {
         role: ROLE_DIALOG,
         children: [
           {
--- a/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_ariaowns.js
@@ -2,17 +2,17 @@
  * 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';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
-function* testContainer1(browser, accDoc) {
+async function testContainer1(browser, accDoc) {
   const id = 't1_container';
   const docID = getAccessibleDOMNodeID(accDoc);
   const acc = findAccessibleChildByID(accDoc, id);
 
   /* ================= Initial tree test ==================================== */
   // children are swapped by ARIA owns
   let tree = {
     SECTION: [
@@ -21,296 +21,296 @@ function* testContainer1(browser, accDoc
       ] },
       { PUSHBUTTON: [ ] }
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================ Change ARIA owns ====================================== */
   let onReorder = waitForEvent(EVENT_REORDER, id);
-  yield invokeSetAttribute(browser, id, 'aria-owns', 't1_button t1_subdiv');
-  yield onReorder;
+  await invokeSetAttribute(browser, id, 'aria-owns', 't1_button t1_subdiv');
+  await onReorder;
 
   // children are swapped again, button and subdiv are appended to
   // the children.
   tree = {
     SECTION: [
       { CHECKBUTTON: [ ] }, // checkbox, native order
       { PUSHBUTTON: [ ] }, // button, rearranged by ARIA own
       { SECTION: [ ] } // subdiv from the subtree, ARIA owned
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================ Remove ARIA owns ====================================== */
   onReorder = waitForEvent(EVENT_REORDER, id);
-  yield invokeSetAttribute(browser, id, 'aria-owns');
-  yield onReorder;
+  await invokeSetAttribute(browser, id, 'aria-owns');
+  await onReorder;
 
   // children follow the DOM order
   tree = {
     SECTION: [
       { PUSHBUTTON: [ ] },
       { CHECKBUTTON: [
           { SECTION: [] }
       ] }
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================ Set ARIA owns ========================================= */
   onReorder = waitForEvent(EVENT_REORDER, id);
-  yield invokeSetAttribute(browser, id, 'aria-owns', 't1_button t1_subdiv');
-  yield onReorder;
+  await invokeSetAttribute(browser, id, 'aria-owns', 't1_button t1_subdiv');
+  await onReorder;
 
   // children are swapped again, button and subdiv are appended to
   // the children.
   tree = {
     SECTION: [
       { CHECKBUTTON: [ ] }, // checkbox
       { PUSHBUTTON: [ ] }, // button, rearranged by ARIA own
       { SECTION: [ ] } // subdiv from the subtree, ARIA owned
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================ Add ID to ARIA owns =================================== */
   onReorder = waitForEvent(EVENT_REORDER, docID);
-  yield invokeSetAttribute(browser, id, 'aria-owns',
+  await invokeSetAttribute(browser, id, 'aria-owns',
     't1_button t1_subdiv t1_group');
-  yield onReorder;
+  await onReorder;
 
   // children are swapped again, button and subdiv are appended to
   // the children.
   tree = {
     SECTION: [
       { CHECKBUTTON: [ ] }, // t1_checkbox
       { PUSHBUTTON: [ ] }, // button, t1_button
       { SECTION: [ ] }, // subdiv from the subtree, t1_subdiv
       { GROUPING: [ ] } // group from outside, t1_group
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================ Append element ======================================== */
   onReorder = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, id, contentId => {
+  await ContentTask.spawn(browser, id, contentId => {
     let div = content.document.createElement('div');
     div.setAttribute('id', 't1_child3');
     div.setAttribute('role', 'radio');
     content.document.getElementById(contentId).appendChild(div);
   });
-  yield onReorder;
+  await onReorder;
 
   // children are invalidated, they includes aria-owns swapped kids and
   // newly inserted child.
   tree = {
     SECTION: [
       { CHECKBUTTON: [ ] }, // existing explicit, t1_checkbox
       { RADIOBUTTON: [ ] }, // new explicit, t1_child3
       { PUSHBUTTON: [ ] }, // ARIA owned, t1_button
       { SECTION: [ ] }, // ARIA owned, t1_subdiv
       { GROUPING: [ ] } // ARIA owned, t1_group
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================ Remove element ======================================== */
   onReorder = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, {}, () =>
+  await ContentTask.spawn(browser, {}, () =>
     content.document.getElementById('t1_span').remove());
-  yield onReorder;
+  await onReorder;
 
   // subdiv should go away
   tree = {
     SECTION: [
       { CHECKBUTTON: [ ] }, // explicit, t1_checkbox
       { RADIOBUTTON: [ ] }, // explicit, t1_child3
       { PUSHBUTTON: [ ] }, // ARIA owned, t1_button
       { GROUPING: [ ] } // ARIA owned, t1_group
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================ Remove ID ============================================= */
   onReorder = waitForEvent(EVENT_REORDER, docID);
-  yield invokeSetAttribute(browser, 't1_group', 'id');
-  yield onReorder;
+  await invokeSetAttribute(browser, 't1_group', 'id');
+  await onReorder;
 
   tree = {
     SECTION: [
       { CHECKBUTTON: [ ] },
       { RADIOBUTTON: [ ] },
       { PUSHBUTTON: [ ] } // ARIA owned, t1_button
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================ Set ID ================================================ */
   onReorder = waitForEvent(EVENT_REORDER, docID);
-  yield invokeSetAttribute(browser, 't1_grouptmp', 'id', 't1_group');
-  yield onReorder;
+  await invokeSetAttribute(browser, 't1_grouptmp', 'id', 't1_group');
+  await onReorder;
 
   tree = {
     SECTION: [
       { CHECKBUTTON: [ ] },
       { RADIOBUTTON: [ ] },
       { PUSHBUTTON: [ ] }, // ARIA owned, t1_button
       { GROUPING: [ ] } // ARIA owned, t1_group, previously t1_grouptmp
     ]
   };
   testAccessibleTree(acc, tree);
 }
 
-function* removeContainer(browser, accDoc) {
+async function removeContainer(browser, accDoc) {
   const id = 't2_container1';
   const acc = findAccessibleChildByID(accDoc, id);
 
   let tree = {
     SECTION: [
       { CHECKBUTTON: [ ] } // ARIA owned, 't2_owned'
     ]
   };
   testAccessibleTree(acc, tree);
 
   let onReorder = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, {}, () =>
+  await ContentTask.spawn(browser, {}, () =>
     content.document.getElementById('t2_container2').removeChild(
       content.document.getElementById('t2_container3')));
-  yield onReorder;
+  await onReorder;
 
   tree = {
     SECTION: [ ]
   };
   testAccessibleTree(acc, tree);
 }
 
-function* stealAndRecacheChildren(browser, accDoc) {
+async function stealAndRecacheChildren(browser, accDoc) {
   const id1 = 't3_container1';
   const id2 = 't3_container2';
   const acc1 = findAccessibleChildByID(accDoc, id1);
   const acc2 = findAccessibleChildByID(accDoc, id2);
 
   /* ================ Steal from other ARIA owns ============================ */
   let onReorder = waitForEvent(EVENT_REORDER, id2);
-  yield invokeSetAttribute(browser, id2, 'aria-owns', 't3_child');
-  yield onReorder;
+  await invokeSetAttribute(browser, id2, 'aria-owns', 't3_child');
+  await onReorder;
 
   let tree = {
     SECTION: [ ]
   };
   testAccessibleTree(acc1, tree);
 
   tree = {
     SECTION: [
       { CHECKBUTTON: [ ] }
     ]
   };
   testAccessibleTree(acc2, tree);
 
   /* ================ Append element to recache children ==================== */
   onReorder = waitForEvent(EVENT_REORDER, id2);
-  yield ContentTask.spawn(browser, id2, id => {
+  await ContentTask.spawn(browser, id2, id => {
     let div = content.document.createElement('div');
     div.setAttribute('role', 'radio');
     content.document.getElementById(id).appendChild(div);
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     SECTION: [ ]
   };
   testAccessibleTree(acc1, tree);
 
   tree = {
     SECTION: [
       { RADIOBUTTON: [ ] },
       { CHECKBUTTON: [ ] } // ARIA owned
     ]
   };
   testAccessibleTree(acc2, tree);
 }
 
-function* showHiddenElement(browser, accDoc) {
+async function showHiddenElement(browser, accDoc) {
   const id = 't4_container1';
   const acc = findAccessibleChildByID(accDoc, id);
 
   let tree = {
     SECTION: [
       { RADIOBUTTON: [] }
     ]
   };
   testAccessibleTree(acc, tree);
 
   let onReorder = waitForEvent(EVENT_REORDER, id);
-  yield invokeSetStyle(browser, 't4_child1', 'display', 'block');
-  yield onReorder;
+  await invokeSetStyle(browser, 't4_child1', 'display', 'block');
+  await onReorder;
 
   tree = {
     SECTION: [
       { CHECKBUTTON: [] },
       { RADIOBUTTON: [] }
     ]
   };
   testAccessibleTree(acc, tree);
 }
 
-function* rearrangeARIAOwns(browser, accDoc) {
+async function rearrangeARIAOwns(browser, accDoc) {
   const id = 't5_container';
   const acc = findAccessibleChildByID(accDoc, id);
   const tests = [{
     val: 't5_checkbox t5_radio t5_button',
     roleList: [ 'CHECKBUTTON', 'RADIOBUTTON', 'PUSHBUTTON' ]
   }, {
     val: 't5_radio t5_button t5_checkbox',
     roleList: [ 'RADIOBUTTON', 'PUSHBUTTON', 'CHECKBUTTON' ]
   }];
 
   for (let { val, roleList } of tests) {
     let onReorder = waitForEvent(EVENT_REORDER, id);
-    yield invokeSetAttribute(browser, id, 'aria-owns', val);
-    yield onReorder;
+    await invokeSetAttribute(browser, id, 'aria-owns', val);
+    await onReorder;
 
     let tree = { SECTION: [ ] };
     for (let role of roleList) {
       let ch = {};
       ch[role] = [];
       tree.SECTION.push(ch);
     }
     testAccessibleTree(acc, tree);
   }
 }
 
-function* removeNotARIAOwnedEl(browser, accDoc) {
+async function removeNotARIAOwnedEl(browser, accDoc) {
   const id = 't6_container';
   const acc = findAccessibleChildByID(accDoc, id);
 
   let tree = {
     SECTION: [
       { TEXT_LEAF: [ ] },
       { GROUPING: [ ] }
     ]
   };
   testAccessibleTree(acc, tree);
 
   let onReorder = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, id, contentId => {
+  await ContentTask.spawn(browser, id, contentId => {
     content.document.getElementById(contentId).removeChild(
       content.document.getElementById('t6_span'));
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     SECTION: [
       { GROUPING: [ ] }
     ]
   };
   testAccessibleTree(acc, tree);
 }
 
-addAccessibleTask('doc_treeupdate_ariaowns.html', function*(browser, accDoc) {
-  yield testContainer1(browser, accDoc);
-  yield removeContainer(browser, accDoc);
-  yield stealAndRecacheChildren(browser, accDoc);
-  yield showHiddenElement(browser, accDoc);
-  yield rearrangeARIAOwns(browser, accDoc);
-  yield removeNotARIAOwnedEl(browser, accDoc);
+addAccessibleTask('doc_treeupdate_ariaowns.html', async function(browser, accDoc) {
+  await testContainer1(browser, accDoc);
+  await removeContainer(browser, accDoc);
+  await stealAndRecacheChildren(browser, accDoc);
+  await showHiddenElement(browser, accDoc);
+  await rearrangeARIAOwns(browser, accDoc);
+  await removeNotARIAOwnedEl(browser, accDoc);
 });
--- a/accessible/tests/browser/e10s/browser_treeupdate_canvas.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_canvas.js
@@ -5,20 +5,20 @@
 'use strict';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
 addAccessibleTask(`
   <canvas id="canvas">
     <div id="dialog" role="dialog" style="display: none;"></div>
-  </canvas>`, function*(browser, accDoc) {
+  </canvas>`, async function(browser, accDoc) {
   let canvas = findAccessibleChildByID(accDoc, 'canvas');
   let dialog = findAccessibleChildByID(accDoc, 'dialog');
 
   testAccessibleTree(canvas, { CANVAS: [] });
 
   let onShow = waitForEvent(EVENT_SHOW, 'dialog');
-  yield invokeSetStyle(browser, 'dialog', 'display', 'block');
-  yield onShow;
+  await invokeSetStyle(browser, 'dialog', 'display', 'block');
+  await onShow;
 
   testAccessibleTree(dialog, { DIALOG: [] });
 });
--- a/accessible/tests/browser/e10s/browser_treeupdate_cssoverflow.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_cssoverflow.js
@@ -6,39 +6,39 @@
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
 addAccessibleTask(`
   <div id="container"><div id="scrollarea" style="overflow:auto;"><input>
   </div></div>
   <div id="container2"><div id="scrollarea2" style="overflow:hidden;">
-  </div></div>`, function*(browser, accDoc) {
+  </div></div>`, async function(browser, accDoc) {
   const id1 = 'container';
   const id2 = 'container2';
   const container = findAccessibleChildByID(accDoc, id1);
   const container2 = findAccessibleChildByID(accDoc, id2);
 
   /* ================= Change scroll range ================================== */
   let tree = {
     SECTION: [ {// container
       SECTION: [ {// scroll area
         ENTRY: [ ] // child content
       } ]
     } ]
   };
   testAccessibleTree(container, tree);
 
   let onReorder = waitForEvent(EVENT_REORDER, id1);
-  yield ContentTask.spawn(browser, id1, id => {
+  await ContentTask.spawn(browser, id1, id => {
     let doc = content.document;
     doc.getElementById('scrollarea').style.width = '20px';
     doc.getElementById(id).appendChild(doc.createElement('input'));
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     SECTION: [ {// container
       SECTION: [ {// scroll area
         ENTRY: [ ] // child content
       } ]
     }, {
       ENTRY: [ ] // inserted input
@@ -46,18 +46,18 @@ addAccessibleTask(`
   };
   testAccessibleTree(container, tree);
 
   /* ================= Change scrollbar styles ============================== */
   tree = { SECTION: [ ] };
   testAccessibleTree(container2, tree);
 
   onReorder = waitForEvent(EVENT_REORDER, id2);
-  yield invokeSetStyle(browser, 'scrollarea2', 'overflow', 'auto');
-  yield onReorder;
+  await invokeSetStyle(browser, 'scrollarea2', 'overflow', 'auto');
+  await onReorder;
 
   tree = {
     SECTION: [ // container
       { SECTION: [] } // scroll area
     ]
   };
   testAccessibleTree(container2, tree);
 });
--- a/accessible/tests/browser/e10s/browser_treeupdate_doc.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_doc.js
@@ -12,295 +12,295 @@ const iframeSrc = `data:text/html,
     <head>
       <meta charset='utf-8'/>
       <title>Inner Iframe</title>
     </head>
     <body id='inner-iframe'></body>
   </html>`;
 
 addAccessibleTask(`
-  <iframe id="iframe" src="${iframeSrc}"></iframe>`, function*(browser, accDoc) {
+  <iframe id="iframe" src="${iframeSrc}"></iframe>`, async function(browser, accDoc) {
   // ID of the iframe that is being tested
   const id = 'inner-iframe';
 
   let iframe = findAccessibleChildByID(accDoc, id);
 
   /* ================= Initial tree check =================================== */
   let tree = {
     role: ROLE_DOCUMENT,
     children: [ ]
   };
   testAccessibleTree(iframe, tree);
 
   /* ================= Write iframe document ================================ */
   let reorderEventPromise = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, id, contentId => {
+  await ContentTask.spawn(browser, id, contentId => {
     let docNode = content.document.getElementById('iframe').contentDocument;
     let newHTMLNode = docNode.createElement('html');
     let newBodyNode = docNode.createElement('body');
     let newTextNode = docNode.createTextNode('New Wave');
     newBodyNode.id = contentId;
     newBodyNode.appendChild(newTextNode);
     newHTMLNode.appendChild(newBodyNode);
     docNode.replaceChild(newHTMLNode, docNode.documentElement);
   });
-  yield reorderEventPromise;
+  await reorderEventPromise;
 
   tree = {
     role: ROLE_DOCUMENT,
     children: [
       {
         role: ROLE_TEXT_LEAF,
         name: 'New Wave'
       }
     ]
   };
   testAccessibleTree(iframe, tree);
 
   /* ================= Replace iframe HTML element ========================== */
   reorderEventPromise = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, id, contentId => {
+  await ContentTask.spawn(browser, id, contentId => {
     let docNode = content.document.getElementById('iframe').contentDocument;
     // We can't use open/write/close outside of iframe document because of
     // security error.
     let script = docNode.createElement('script');
     script.textContent = `
       document.open();
       document.write('<body id="${contentId}">hello</body>');
       document.close();`;
     docNode.body.appendChild(script);
   });
-  yield reorderEventPromise;
+  await reorderEventPromise;
 
   tree = {
     role: ROLE_DOCUMENT,
     children: [
       {
         role: ROLE_TEXT_LEAF,
         name: 'hello'
       }
     ]
   };
   testAccessibleTree(iframe, tree);
 
   /* ================= Replace iframe body ================================== */
   reorderEventPromise = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, id, contentId => {
+  await ContentTask.spawn(browser, id, contentId => {
     let docNode = content.document.getElementById('iframe').contentDocument;
     let newBodyNode = docNode.createElement('body');
     let newTextNode = docNode.createTextNode('New Hello');
     newBodyNode.id = contentId;
     newBodyNode.appendChild(newTextNode);
     newBodyNode.setAttribute('role', 'button');
     docNode.documentElement.replaceChild(newBodyNode, docNode.body);
   });
-  yield reorderEventPromise;
+  await reorderEventPromise;
 
   tree = {
     role: ROLE_PUSHBUTTON,
     children: [
       {
         role: ROLE_TEXT_LEAF,
         name: 'New Hello'
       }
     ]
   };
   testAccessibleTree(iframe, tree);
 
   /* ================= Open iframe document ================================= */
   reorderEventPromise = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, id, contentId => {
+  await ContentTask.spawn(browser, id, contentId => {
     // Open document.
     let docNode = content.document.getElementById('iframe').contentDocument;
     let script = docNode.createElement('script');
     script.textContent = `
       function closeMe() {
         document.write('Works?');
         document.close();
       }
       window.closeMe = closeMe;
       document.open();
       document.write('<body id="${contentId}"></body>');`;
     docNode.body.appendChild(script);
   });
-  yield reorderEventPromise;
+  await reorderEventPromise;
 
   tree = {
     role: ROLE_DOCUMENT,
     children: [ ]
   };
   testAccessibleTree(iframe, tree);
 
   /* ================= Close iframe document ================================ */
   reorderEventPromise = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     // Write and close document.
     let docNode = content.document.getElementById('iframe').contentDocument;
     docNode.write('Works?');
     docNode.close();
   });
-  yield reorderEventPromise;
+  await reorderEventPromise;
 
   tree = {
     role: ROLE_DOCUMENT,
     children: [
       {
         role: ROLE_TEXT_LEAF,
         name: 'Works?'
       }
     ]
   };
   testAccessibleTree(iframe, tree);
 
   /* ================= Remove HTML from iframe document ===================== */
   reorderEventPromise = waitForEvent(EVENT_REORDER, iframe);
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     // Remove HTML element.
     let docNode = content.document.getElementById('iframe').contentDocument;
     docNode.firstChild.remove();
   });
-  let event = yield reorderEventPromise;
+  let event = await reorderEventPromise;
 
   ok(event.accessible instanceof nsIAccessibleDocument,
     'Reorder should happen on the document');
   tree = {
     role: ROLE_DOCUMENT,
     children: [ ]
   };
   testAccessibleTree(iframe, tree);
 
   /* ================= Insert HTML to iframe document ======================= */
   reorderEventPromise = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, id, contentId => {
+  await ContentTask.spawn(browser, id, contentId => {
     // Insert HTML element.
     let docNode = content.document.getElementById('iframe').contentDocument;
     let html = docNode.createElement('html');
     let body = docNode.createElement('body');
     let text = docNode.createTextNode('Haha');
     body.appendChild(text);
     body.id = contentId;
     html.appendChild(body);
     docNode.appendChild(html);
   });
-  yield reorderEventPromise;
+  await reorderEventPromise;
 
   tree = {
     role: ROLE_DOCUMENT,
     children: [
       {
         role: ROLE_TEXT_LEAF,
         name: 'Haha'
       }
     ]
   };
   testAccessibleTree(iframe, tree);
 
   /* ================= Remove body from iframe document ===================== */
   reorderEventPromise = waitForEvent(EVENT_REORDER, iframe);
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     // Remove body element.
     let docNode = content.document.getElementById('iframe').contentDocument;
     docNode.documentElement.removeChild(docNode.body);
   });
-  event = yield reorderEventPromise;
+  event = await reorderEventPromise;
 
   ok(event.accessible instanceof nsIAccessibleDocument,
     'Reorder should happen on the document');
   tree = {
     role: ROLE_DOCUMENT,
     children: [ ]
   };
   testAccessibleTree(iframe, tree);
 
   /* ================ Insert element under document element while body missed */
   reorderEventPromise = waitForEvent(EVENT_REORDER, iframe);
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let docNode = content.document.getElementById('iframe').contentDocument;
     let inputNode = content.window.inputNode = docNode.createElement('input');
     docNode.documentElement.appendChild(inputNode);
   });
-  event = yield reorderEventPromise;
+  event = await reorderEventPromise;
 
   ok(event.accessible instanceof nsIAccessibleDocument,
     'Reorder should happen on the document');
   tree = {
     DOCUMENT: [
       { ENTRY: [ ] }
     ]
   };
   testAccessibleTree(iframe, tree);
 
   reorderEventPromise = waitForEvent(EVENT_REORDER, iframe);
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let docEl =
       content.document.getElementById('iframe').contentDocument.documentElement;
     // Remove aftermath of this test before next test starts.
     docEl.firstChild.remove();
   });
   // Make sure reorder event was fired and that the input was removed.
-  yield reorderEventPromise;
+  await reorderEventPromise;
   tree = {
     role: ROLE_DOCUMENT,
     children: [ ]
   };
   testAccessibleTree(iframe, tree);
 
   /* ================= Insert body to iframe document ======================= */
   reorderEventPromise = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, id, contentId => {
+  await ContentTask.spawn(browser, id, contentId => {
     // Write and close document.
     let docNode = content.document.getElementById('iframe').contentDocument;
     // Insert body element.
     let body = docNode.createElement('body');
     let text = docNode.createTextNode('Yo ho ho i butylka roma!');
     body.appendChild(text);
     body.id = contentId;
     docNode.documentElement.appendChild(body);
   });
-  yield reorderEventPromise;
+  await reorderEventPromise;
 
   tree = {
     role: ROLE_DOCUMENT,
     children: [
       {
         role: ROLE_TEXT_LEAF,
         name: 'Yo ho ho i butylka roma!'
       }
     ]
   };
   testAccessibleTree(iframe, tree);
 
   /* ================= Change source ======================================== */
   reorderEventPromise = waitForEvent(EVENT_REORDER, 'iframe');
-  yield invokeSetAttribute(browser, 'iframe', 'src',
+  await invokeSetAttribute(browser, 'iframe', 'src',
     `data:text/html,<html><body id="${id}"><input></body></html>`);
-  event = yield reorderEventPromise;
+  event = await reorderEventPromise;
 
   tree = {
     INTERNAL_FRAME: [
       { DOCUMENT: [
         { ENTRY: [ ] }
       ] }
     ]
   };
   testAccessibleTree(event.accessible, tree);
   iframe = findAccessibleChildByID(event.accessible, id);
 
   /* ================= Replace iframe body on ARIA role body ================ */
   reorderEventPromise = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, id, contentId => {
+  await ContentTask.spawn(browser, id, contentId => {
     let docNode = content.document.getElementById('iframe').contentDocument;
     let newBodyNode = docNode.createElement('body');
     let newTextNode = docNode.createTextNode('New Hello');
     newBodyNode.appendChild(newTextNode);
     newBodyNode.setAttribute('role', 'button');
     newBodyNode.id = contentId;
     docNode.documentElement.replaceChild(newBodyNode, docNode.body);
   });
-  yield reorderEventPromise;
+  await reorderEventPromise;
 
   tree = {
     role: ROLE_PUSHBUTTON,
     children: [
       {
         role: ROLE_TEXT_LEAF,
         name: 'New Hello'
       }
--- a/accessible/tests/browser/e10s/browser_treeupdate_gencontent.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_gencontent.js
@@ -13,17 +13,17 @@ addAccessibleTask(`
       content: "START"
     }
     .gentext:after {
       content: "END"
     }
   </style>
   <div id="container1"></div>
   <div id="container2"><div id="container2_child">text</div></div>`,
-  function*(browser, accDoc) {
+  async function(browser, accDoc) {
     const id1 = 'container1';
     const id2 = 'container2';
     let container1 = findAccessibleChildByID(accDoc, id1);
     let container2 = findAccessibleChildByID(accDoc, id2);
 
     let tree = {
       SECTION: [ ] // container
     };
@@ -35,39 +35,39 @@ addAccessibleTask(`
           TEXT_LEAF: [ ] // primary text
         } ]
       } ]
     };
     testAccessibleTree(container2, tree);
 
     let onReorder = waitForEvent(EVENT_REORDER, id1);
     // Create and add an element with CSS generated content to container1
-    yield ContentTask.spawn(browser, id1, id => {
+    await ContentTask.spawn(browser, id1, id => {
       let node = content.document.createElement('div');
       node.textContent = 'text';
       node.setAttribute('class', 'gentext');
       content.document.getElementById(id).appendChild(node);
     });
-    yield onReorder;
+    await onReorder;
 
     tree = {
       SECTION: [ // container
         { SECTION: [ // inserted node
           { STATICTEXT: [] }, // :before
           { TEXT_LEAF: [] }, // primary text
           { STATICTEXT: [] } // :after
         ] }
       ]
     };
     testAccessibleTree(container1, tree);
 
     onReorder = waitForEvent(EVENT_REORDER, id2);
     // Add CSS generated content to an element in container2's subtree
-    yield invokeSetAttribute(browser, 'container2_child', 'class', 'gentext');
-    yield onReorder;
+    await invokeSetAttribute(browser, 'container2_child', 'class', 'gentext');
+    await onReorder;
 
     tree = {
       SECTION: [ // container2
         { SECTION: [ // container2 child
           { STATICTEXT: [] }, // :before
           { TEXT_LEAF: [] }, // primary text
           { STATICTEXT: [] } // :after
         ] }
--- a/accessible/tests/browser/e10s/browser_treeupdate_hidden.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_hidden.js
@@ -2,28 +2,28 @@
  * 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';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
-function* setHidden(browser, value) {
+async function setHidden(browser, value) {
   let onReorder = waitForEvent(EVENT_REORDER, 'container');
-  yield invokeSetAttribute(browser, 'child', 'hidden', value);
-  yield onReorder;
+  await invokeSetAttribute(browser, 'child', 'hidden', value);
+  await onReorder;
 }
 
 addAccessibleTask('<div id="container"><input id="child"></div>',
-  function*(browser, accDoc) {
+  async function(browser, accDoc) {
     let container = findAccessibleChildByID(accDoc, 'container');
 
     testAccessibleTree(container, { SECTION: [ { ENTRY: [ ] } ] });
 
     // Set @hidden attribute
-    yield setHidden(browser, 'true');
+    await setHidden(browser, 'true');
     testAccessibleTree(container, { SECTION: [ ] });
 
     // Remove @hidden attribute
-    yield setHidden(browser);
+    await setHidden(browser);
     testAccessibleTree(container, { SECTION: [ { ENTRY: [ ] } ] });
   });
--- a/accessible/tests/browser/e10s/browser_treeupdate_imagemap.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_imagemap.js
@@ -2,189 +2,189 @@
  * 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';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
-function* testImageMap(browser, accDoc) {
+async function testImageMap(browser, accDoc) {
   const id = 'imgmap';
   const acc = findAccessibleChildByID(accDoc, id);
 
   /* ================= Initial tree test ==================================== */
   let tree = {
     IMAGE_MAP: [
       { role: ROLE_LINK, name: 'b', children: [ ] }
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================= Insert area ========================================== */
   let onReorder = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let areaElm = content.document.createElement('area');
     let mapNode = content.document.getElementById('map');
     areaElm.setAttribute('href',
                          'http://www.bbc.co.uk/radio4/atoz/index.shtml#a');
     areaElm.setAttribute('coords', '0,0,13,14');
     areaElm.setAttribute('alt', 'a');
     areaElm.setAttribute('shape', 'rect');
     mapNode.insertBefore(areaElm, mapNode.firstChild);
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     IMAGE_MAP: [
       { role: ROLE_LINK, name: 'a', children: [ ] },
       { role: ROLE_LINK, name: 'b', children: [ ] }
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================= Append area ========================================== */
   onReorder = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let areaElm = content.document.createElement('area');
     let mapNode = content.document.getElementById('map');
     areaElm.setAttribute('href',
                          'http://www.bbc.co.uk/radio4/atoz/index.shtml#c');
     areaElm.setAttribute('coords', '34,0,47,14');
     areaElm.setAttribute('alt', 'c');
     areaElm.setAttribute('shape', 'rect');
     mapNode.appendChild(areaElm);
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     IMAGE_MAP: [
       { role: ROLE_LINK, name: 'a', children: [ ] },
       { role: ROLE_LINK, name: 'b', children: [ ] },
       { role: ROLE_LINK, name: 'c', children: [ ] }
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================= Remove area ========================================== */
   onReorder = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let mapNode = content.document.getElementById('map');
     mapNode.removeChild(mapNode.firstElementChild);
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     IMAGE_MAP: [
       { role: ROLE_LINK, name: 'b', children: [ ] },
       { role: ROLE_LINK, name: 'c', children: [ ] }
     ]
   };
   testAccessibleTree(acc, tree);
 }
 
-function* testContainer(browser) {
+async function testContainer(browser) {
   const id = 'container';
   /* ================= Remove name on map =================================== */
   let onReorder = waitForEvent(EVENT_REORDER, id);
-  yield invokeSetAttribute(browser, 'map', 'name');
-  let event = yield onReorder;
+  await invokeSetAttribute(browser, 'map', 'name');
+  let event = await onReorder;
   const acc = event.accessible;
 
   let tree = {
     SECTION: [
       { GRAPHIC: [ ] }
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================= Restore name on map ================================== */
   onReorder = waitForEvent(EVENT_REORDER, id);
-  yield invokeSetAttribute(browser, 'map', 'name', 'atoz_map');
+  await invokeSetAttribute(browser, 'map', 'name', 'atoz_map');
   // XXX: force repainting of the image (see bug 745788 for details).
-  yield BrowserTestUtils.synthesizeMouse('#imgmap', 10, 10,
+  await BrowserTestUtils.synthesizeMouse('#imgmap', 10, 10,
     { type: 'mousemove' }, browser);
-  yield onReorder;
+  await onReorder;
 
   tree = {
     SECTION: [ {
       IMAGE_MAP: [
         { LINK: [ ] },
         { LINK: [ ] }
       ]
     } ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================= Remove map =========================================== */
   onReorder = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let mapNode = content.document.getElementById('map');
     mapNode.remove();
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     SECTION: [
       { GRAPHIC: [ ] }
     ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================= Insert map =========================================== */
   onReorder = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, id, contentId => {
+  await ContentTask.spawn(browser, id, contentId => {
     let map = content.document.createElement('map');
     let area = content.document.createElement('area');
 
     map.setAttribute('name', 'atoz_map');
     map.setAttribute('id', 'map');
 
     area.setAttribute('href',
                       'http://www.bbc.co.uk/radio4/atoz/index.shtml#b');
     area.setAttribute('coords', '17,0,30,14');
     area.setAttribute('alt', 'b');
     area.setAttribute('shape', 'rect');
 
     map.appendChild(area);
     content.document.getElementById(contentId).appendChild(map);
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     SECTION: [ {
       IMAGE_MAP: [
         { LINK: [ ] }
       ]
     } ]
   };
   testAccessibleTree(acc, tree);
 
   /* ================= Hide image map ======================================= */
   onReorder = waitForEvent(EVENT_REORDER, id);
-  yield invokeSetStyle(browser, 'imgmap', 'display', 'none');
-  yield onReorder;
+  await invokeSetStyle(browser, 'imgmap', 'display', 'none');
+  await onReorder;
 
   tree = {
     SECTION: [ ]
   };
   testAccessibleTree(acc, tree);
 }
 
-function* waitForImageMap(browser, accDoc) {
+async function waitForImageMap(browser, accDoc) {
   const id = 'imgmap';
   const acc = findAccessibleChildByID(accDoc, id);
   if (acc.firstChild) {
     return;
   }
 
   const onReorder = waitForEvent(EVENT_REORDER, id);
   // Wave over image map
-  yield BrowserTestUtils.synthesizeMouse(`#${id}`, 10, 10,
+  await BrowserTestUtils.synthesizeMouse(`#${id}`, 10, 10,
                                          { type: 'mousemove' }, browser);
-  yield onReorder;
+  await onReorder;
 }
 
-addAccessibleTask('doc_treeupdate_imagemap.html', function*(browser, accDoc) {
-  yield waitForImageMap(browser, accDoc);
-  yield testImageMap(browser, accDoc);
-  yield testContainer(browser);
+addAccessibleTask('doc_treeupdate_imagemap.html', async function(browser, accDoc) {
+  await waitForImageMap(browser, accDoc);
+  await testImageMap(browser, accDoc);
+  await testContainer(browser);
 });
--- a/accessible/tests/browser/e10s/browser_treeupdate_list.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_list.js
@@ -2,41 +2,41 @@
  * 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';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
-function* setDisplayAndWaitForReorder(browser, value) {
+async function setDisplayAndWaitForReorder(browser, value) {
   let onReorder = waitForEvent(EVENT_REORDER, 'ul');
-  yield invokeSetStyle(browser, 'li', 'display', value);
-  return yield onReorder;
+  await invokeSetStyle(browser, 'li', 'display', value);
+  return await onReorder;
 }
 
 addAccessibleTask(`
   <ul id="ul">
     <li id="li">item1</li>
-  </ul>`, function*(browser, accDoc) {
+  </ul>`, async function(browser, accDoc) {
   let li = findAccessibleChildByID(accDoc, 'li');
   let bullet = li.firstChild;
   let accTree = {
     role: ROLE_LISTITEM,
     children: [ {
       role: ROLE_STATICTEXT,
       children: []
     }, {
       role: ROLE_TEXT_LEAF,
       children: []
     } ]
   };
   testAccessibleTree(li, accTree);
 
-  yield setDisplayAndWaitForReorder(browser, 'none');
+  await setDisplayAndWaitForReorder(browser, 'none');
 
   ok(isDefunct(li), 'Check that li is defunct.');
   ok(isDefunct(bullet), 'Check that bullet is defunct.');
 
-  let event = yield setDisplayAndWaitForReorder(browser, 'list-item');
+  let event = await setDisplayAndWaitForReorder(browser, 'list-item');
 
   testAccessibleTree(findAccessibleChildByID(event.accessible, 'li'), accTree);
 });
--- a/accessible/tests/browser/e10s/browser_treeupdate_list_editabledoc.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_list_editabledoc.js
@@ -2,32 +2,32 @@
  * 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';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
-addAccessibleTask('<ol id="list"></ol>', function*(browser, accDoc) {
+addAccessibleTask('<ol id="list"></ol>', async function(browser, accDoc) {
   let list = findAccessibleChildByID(accDoc, 'list');
 
   testAccessibleTree(list, {
     role: ROLE_LIST,
     children: [ ]
   });
 
-  yield invokeSetAttribute(browser, 'body', 'contentEditable', 'true');
+  await invokeSetAttribute(browser, 'body', 'contentEditable', 'true');
   let onReorder = waitForEvent(EVENT_REORDER, 'list');
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let li = content.document.createElement('li');
     li.textContent = 'item';
     content.document.getElementById('list').appendChild(li);
   });
-  yield onReorder;
+  await onReorder;
 
   testAccessibleTree(list, {
     role: ROLE_LIST,
     children: [ {
       role: ROLE_LISTITEM,
       children: [
         { role: ROLE_STATICTEXT, name: "1. ", children: [] },
         { role: ROLE_TEXT_LEAF, children: [] }
--- a/accessible/tests/browser/e10s/browser_treeupdate_listener.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_listener.js
@@ -3,26 +3,26 @@
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 'use strict';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
 addAccessibleTask('<span id="parent"><span id="child"></span></span>',
-  function*(browser, accDoc) {
+  async function(browser, accDoc) {
     is(findAccessibleChildByID(accDoc, 'parent'), null,
       'Check that parent is not accessible.');
     is(findAccessibleChildByID(accDoc, 'child'), null,
       'Check that child is not accessible.');
 
     let onReorder = waitForEvent(EVENT_REORDER, 'body');
     // Add an event listener to parent.
-    yield ContentTask.spawn(browser, {}, () => {
+    await ContentTask.spawn(browser, {}, () => {
       content.window.dummyListener = () => {};
       content.document.getElementById('parent').addEventListener(
         'click', content.window.dummyListener);
     });
-    yield onReorder;
+    await onReorder;
 
     let tree = { TEXT: [] };
     testAccessibleTree(findAccessibleChildByID(accDoc, 'parent'), tree);
   });
--- a/accessible/tests/browser/e10s/browser_treeupdate_optgroup.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_optgroup.js
@@ -2,22 +2,22 @@
  * 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';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
-addAccessibleTask('<select id="select"></select>', function*(browser, accDoc) {
+addAccessibleTask('<select id="select"></select>', async function(browser, accDoc) {
   let select = findAccessibleChildByID(accDoc, 'select');
 
   let onEvent = waitForEvent(EVENT_REORDER, 'select');
   // Create a combobox with grouping and 2 standalone options
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let doc = content.document;
     let contentSelect = doc.getElementById('select');
     let optGroup = doc.createElement('optgroup');
 
     for (let i = 0; i < 2; i++) {
       let opt = doc.createElement('option');
       opt.value = i;
       opt.text = 'Option: Value ' + i;
@@ -26,17 +26,17 @@ addAccessibleTask('<select id="select"><
     contentSelect.add(optGroup, null);
 
     for (let i = 0; i < 2; i++) {
       let opt = doc.createElement('option');
       contentSelect.add(opt, null);
     }
     contentSelect.firstChild.firstChild.id = 'option1Node';
   });
-  let event = yield onEvent;
+  let event = await onEvent;
   let option1Node = findAccessibleChildByID(event.accessible, 'option1Node');
 
   let tree = {
     COMBOBOX: [ {
       COMBOBOX_LIST: [ {
         GROUPING: [
           { COMBOBOX_OPTION: [ { TEXT_LEAF: [] } ] },
           { COMBOBOX_OPTION: [ { TEXT_LEAF: [] } ] }
@@ -48,43 +48,43 @@ addAccessibleTask('<select id="select"><
       } ]
     } ]
   };
   testAccessibleTree(select, tree);
   ok(!isDefunct(option1Node), 'option shouldn\'t be defunct');
 
   onEvent = waitForEvent(EVENT_REORDER, 'select');
   // Remove grouping from combobox
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let contentSelect = content.document.getElementById('select');
     contentSelect.firstChild.remove();
   });
-  yield onEvent;
+  await onEvent;
 
   tree = {
     COMBOBOX: [ {
       COMBOBOX_LIST: [
         { COMBOBOX_OPTION: [] },
         { COMBOBOX_OPTION: [] }
       ]
     } ]
   };
   testAccessibleTree(select, tree);
   ok(isDefunct(option1Node),
     'removed option shouldn\'t be accessible anymore!');
 
   onEvent = waitForEvent(EVENT_REORDER, 'select');
   // Remove all options from combobox
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let contentSelect = content.document.getElementById('select');
     while (contentSelect.length) {
       contentSelect.remove(0);
     }
   });
-  yield onEvent;
+  await onEvent;
 
   tree = {
     COMBOBOX: [ {
       COMBOBOX_LIST: [ ]
     } ]
   };
   testAccessibleTree(select, tree);
 });
--- a/accessible/tests/browser/e10s/browser_treeupdate_removal.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_removal.js
@@ -2,34 +2,34 @@
  * 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';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
-addAccessibleTask('doc_treeupdate_removal.xhtml', function*(browser, accDoc) {
+addAccessibleTask('doc_treeupdate_removal.xhtml', async function(browser, accDoc) {
   ok(isAccessible(findAccessibleChildByID(accDoc, 'the_table')),
     'table should be accessible');
 
   // Move the_table element into hidden subtree.
   let onReorder = waitForEvent(EVENT_REORDER, 'body');
-  yield ContentTask.spawn(browser, {}, () => content.document.getElementById(
+  await ContentTask.spawn(browser, {}, () => content.document.getElementById(
     'the_displaynone').appendChild(content.document.getElementById(
       'the_table')));
-  yield onReorder;
+  await onReorder;
 
   ok(!isAccessible(findAccessibleChildByID(accDoc, 'the_table')),
     'table in display none tree shouldn\'t be accessible');
   ok(!isAccessible(findAccessibleChildByID(accDoc, 'the_row')),
     'row shouldn\'t be accessible');
 
   // Remove the_row element (since it did not have accessible, no event needed).
-  yield ContentTask.spawn(browser, {}, () =>
+  await ContentTask.spawn(browser, {}, () =>
     content.document.body.removeChild(
       content.document.getElementById('the_row')));
 
   // make sure no accessibles have stuck around.
   ok(!isAccessible(findAccessibleChildByID(accDoc, 'the_row')),
     'row shouldn\'t be accessible');
   ok(!isAccessible(findAccessibleChildByID(accDoc, 'the_table')),
     'table shouldn\'t be accessible');
--- a/accessible/tests/browser/e10s/browser_treeupdate_table.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_table.js
@@ -8,39 +8,39 @@
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
 addAccessibleTask(`
   <table id="table">
     <tr>
       <td>cell1</td>
       <td>cell2</td>
     </tr>
-  </table>`, function*(browser, accDoc) {
+  </table>`, async function(browser, accDoc) {
   let table = findAccessibleChildByID(accDoc, 'table');
 
   let tree = {
     TABLE: [
       { ROW: [
         { CELL: [ {TEXT_LEAF: [] }]},
         { CELL: [ {TEXT_LEAF: [] }]}
       ] }
     ]
   };
   testAccessibleTree(table, tree);
 
   let onReorder = waitForEvent(EVENT_REORDER, 'table');
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     // append a caption, it should appear as a first element in the
     // accessible tree.
     let doc = content.document;
     let caption = doc.createElement('caption');
     caption.textContent = 'table caption';
     doc.getElementById('table').appendChild(caption);
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     TABLE: [
       { CAPTION: [ { TEXT_LEAF: [] } ] },
       { ROW: [
         { CELL: [ {TEXT_LEAF: [] }]},
         { CELL: [ {TEXT_LEAF: [] }]}
       ] }
--- a/accessible/tests/browser/e10s/browser_treeupdate_textleaf.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_textleaf.js
@@ -2,33 +2,33 @@
  * 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';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
-function* removeTextData(browser, accessible, id, role) {
+async function removeTextData(browser, accessible, id, role) {
   let tree = {
     role: role,
     children: [ { role: ROLE_TEXT_LEAF, name: "text" } ]
   };
   testAccessibleTree(accessible, tree);
 
   let onReorder = waitForEvent(EVENT_REORDER, id);
-  yield ContentTask.spawn(browser, id, contentId => {
+  await ContentTask.spawn(browser, id, contentId => {
     content.document.getElementById(contentId).firstChild.textContent = '';
   });
-  yield onReorder;
+  await onReorder;
 
   tree = { role: role, children: [] };
   testAccessibleTree(accessible, tree);
 }
 
 addAccessibleTask(`
   <p id="p">text</p>
-  <pre id="pre">text</pre>`, function*(browser, accDoc) {
+  <pre id="pre">text</pre>`, async function(browser, accDoc) {
   let p = findAccessibleChildByID(accDoc, 'p');
   let pre = findAccessibleChildByID(accDoc, 'pre');
-  yield removeTextData(browser, p, 'p', ROLE_PARAGRAPH);
-  yield removeTextData(browser, pre, 'pre', ROLE_TEXT_CONTAINER);
+  await removeTextData(browser, p, 'p', ROLE_PARAGRAPH);
+  await removeTextData(browser, pre, 'pre', ROLE_TEXT_CONTAINER);
 });
--- a/accessible/tests/browser/e10s/browser_treeupdate_visibility.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_visibility.js
@@ -2,82 +2,82 @@
  * 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';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
-function* testTreeOnHide(browser, accDoc, containerID, id, before, after) {
+async function testTreeOnHide(browser, accDoc, containerID, id, before, after) {
   let acc = findAccessibleChildByID(accDoc, containerID);
   testAccessibleTree(acc, before);
 
   let onReorder = waitForEvent(EVENT_REORDER, containerID);
-  yield invokeSetStyle(browser, id, 'visibility', 'hidden');
-  yield onReorder;
+  await invokeSetStyle(browser, id, 'visibility', 'hidden');
+  await onReorder;
 
   testAccessibleTree(acc, after);
 }
 
-function* test3(browser, accessible) {
+async function test3(browser, accessible) {
   let tree = {
     SECTION: [ // container
       { SECTION: [ // parent
         { SECTION: [ // child
           { TEXT_LEAF: [] }
         ] }
       ] },
       { SECTION: [ // parent2
         { SECTION: [ // child2
           { TEXT_LEAF: [] }
         ] }
       ] }
     ] };
   testAccessibleTree(accessible, tree);
 
   let onReorder = waitForEvent(EVENT_REORDER, 't3_container');
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let doc = content.document;
     doc.getElementById('t3_container').style.color = 'red';
     doc.getElementById('t3_parent').style.visibility = 'hidden';
     doc.getElementById('t3_parent2').style.visibility = 'hidden';
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     SECTION: [ // container
       { SECTION: [ // child
         { TEXT_LEAF: [] }
       ] },
       { SECTION: [ // child2
         { TEXT_LEAF: [] }
       ] }
     ] };
   testAccessibleTree(accessible, tree);
 }
 
-function* test4(browser, accessible) {
+async function test4(browser, accessible) {
   let tree = {
     SECTION: [
       { TABLE: [
         { ROW: [
           { CELL: [ ] }
         ] }
       ] }
     ] };
   testAccessibleTree(accessible, tree);
 
   let onReorder = waitForEvent(EVENT_REORDER, 't4_parent');
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let doc = content.document;
     doc.getElementById('t4_container').style.color = 'red';
     doc.getElementById('t4_child').style.visibility = 'visible';
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     SECTION: [{
       TABLE: [{
         ROW: [{
           CELL: [{
             SECTION: [{
               TEXT_LEAF: []
@@ -85,33 +85,33 @@ function* test4(browser, accessible) {
           }]
         }]
       }]
     }]
   };
   testAccessibleTree(accessible, tree);
 }
 
-addAccessibleTask('doc_treeupdate_visibility.html', function*(browser, accDoc) {
+addAccessibleTask('doc_treeupdate_visibility.html', async function(browser, accDoc) {
   let t3Container = findAccessibleChildByID(accDoc, 't3_container');
   let t4Container = findAccessibleChildByID(accDoc, 't4_container');
 
-  yield testTreeOnHide(browser, accDoc, 't1_container', 't1_parent', {
+  await testTreeOnHide(browser, accDoc, 't1_container', 't1_parent', {
     SECTION: [{
       SECTION: [{
         SECTION: [ { TEXT_LEAF: [] } ]
       }]
     }]
   }, {
     SECTION: [ {
       SECTION: [ { TEXT_LEAF: [] } ]
     } ]
   });
 
-  yield testTreeOnHide(browser, accDoc, 't2_container', 't2_grandparent', {
+  await testTreeOnHide(browser, accDoc, 't2_container', 't2_grandparent', {
     SECTION: [{ // container
       SECTION: [{ // grand parent
         SECTION: [{
           SECTION: [{ // child
             TEXT_LEAF: []
           }]
         }, {
           SECTION: [{ // child2
@@ -127,20 +127,20 @@ addAccessibleTask('doc_treeupdate_visibi
       }]
     }, {
       SECTION: [{ // child2
         TEXT_LEAF: []
       }]
     }]
   });
 
-  yield test3(browser, t3Container);
-  yield test4(browser, t4Container);
+  await test3(browser, t3Container);
+  await test4(browser, t4Container);
 
-  yield testTreeOnHide(browser, accDoc, 't5_container', 't5_subcontainer', {
+  await testTreeOnHide(browser, accDoc, 't5_container', 't5_subcontainer', {
     SECTION: [{ // container
       SECTION: [{ // subcontainer
         TABLE: [{
           ROW: [{
             CELL: [{
               SECTION: [{ // child
                 TEXT_LEAF: []
               }]
@@ -152,17 +152,17 @@ addAccessibleTask('doc_treeupdate_visibi
   }, {
     SECTION: [{ // container
       SECTION: [{ // child
         TEXT_LEAF: []
       }]
     }]
   });
 
-  yield testTreeOnHide(browser, accDoc, 't6_container', 't6_subcontainer', {
+  await testTreeOnHide(browser, accDoc, 't6_container', 't6_subcontainer', {
     SECTION: [{ // container
       SECTION: [{ // subcontainer
         TABLE: [{
           ROW: [{
             CELL: [{
               TABLE: [{ // nested table
                 ROW: [{
                   CELL: [{
--- a/accessible/tests/browser/e10s/browser_treeupdate_whitespace.js
+++ b/accessible/tests/browser/e10s/browser_treeupdate_whitespace.js
@@ -2,39 +2,39 @@
  * 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';
 
 /* import-globals-from ../../mochitest/role.js */
 loadScripts({ name: 'role.js', dir: MOCHITESTS_DIR });
 
-addAccessibleTask('doc_treeupdate_whitespace.html', function*(browser, accDoc) {
+addAccessibleTask('doc_treeupdate_whitespace.html', async function(browser, accDoc) {
   let container1 = findAccessibleChildByID(accDoc, 'container1');
   let container2Parent = findAccessibleChildByID(accDoc, 'container2-parent');
 
   let tree = {
     SECTION: [
       { GRAPHIC: [] },
       { TEXT_LEAF: [] },
       { GRAPHIC: [] },
       { TEXT_LEAF: [] },
       { GRAPHIC: [] }
     ]
   };
   testAccessibleTree(container1, tree);
 
   let onReorder = waitForEvent(EVENT_REORDER, 'container1');
   // Remove img1 from container1
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let doc = content.document;
     doc.getElementById('container1').removeChild(
       doc.getElementById('img1'));
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     SECTION: [
       { GRAPHIC: [] },
       { TEXT_LEAF: [] },
       { GRAPHIC: [] }
     ]
   };
@@ -45,24 +45,24 @@ addAccessibleTask('doc_treeupdate_whites
       { LINK: [] },
       { LINK: [ { GRAPHIC: [] } ] }
     ]
   };
   testAccessibleTree(container2Parent, tree);
 
   onReorder = waitForEvent(EVENT_REORDER, 'container2-parent');
   // Append an img with valid src to container2
-  yield ContentTask.spawn(browser, {}, () => {
+  await ContentTask.spawn(browser, {}, () => {
     let doc = content.document;
     let img = doc.createElement('img');
     img.setAttribute('src',
       'http://example.com/a11y/accessible/tests/mochitest/moz.png');
     doc.getElementById('container2').appendChild(img);
   });
-  yield onReorder;
+  await onReorder;
 
   tree = {
     SECTION: [
       { LINK: [ { GRAPHIC: [ ] } ] },
       { TEXT_LEAF: [ ] },
       { LINK: [ { GRAPHIC: [ ] } ] }
     ]
   };
--- a/accessible/tests/browser/e10s/head.js
+++ b/accessible/tests/browser/e10s/head.js
@@ -10,24 +10,24 @@
 /* import-globals-from ../shared-head.js */
 Services.scriptloader.loadSubScript(
   'chrome://mochitests/content/browser/accessible/tests/browser/shared-head.js',
   this);
 
 /**
  * A wrapper around browser test add_task that triggers an accessible test task
  * as a new browser test task with given document, data URL or markup snippet.
- * @param  {String}             doc    URL (relative to current directory) or
- *                                     data URL or markup snippet that is used
- *                                     to test content with
- * @param  {Function|Function*} task   a generator or a function with tests to
- *                                     run
+ * @param  {String}                 doc  URL (relative to current directory) or
+ *                                       data URL or markup snippet that is used
+ *                                       to test content with
+ * @param  {Function|AsyncFunction} task a generator or a function with tests to
+ *                                       run
  */
 function addAccessibleTask(doc, task) {
-  add_task(function*() {
+  add_task(async function() {
     let url;
     if (doc.includes('doc_')) {
       url = `${CURRENT_CONTENT_DIR}e10s/${doc}`;
     } else {
       // Assume it's a markup snippet.
       url = `data:text/html,
         <html>
           <head>
@@ -44,41 +44,41 @@ function addAccessibleTask(doc, task) {
         Services.obs.removeObserver(
           observers.getNext().QueryInterface(Ci.nsIObserver),
           'accessible-event');
       }
     });
 
     let onDocLoad = waitForEvent(EVENT_DOCUMENT_LOAD_COMPLETE, 'body');
 
-    yield BrowserTestUtils.withNewTab({
+    await BrowserTestUtils.withNewTab({
       gBrowser,
       url: url
-    }, function*(browser) {
+    }, async function(browser) {
       registerCleanupFunction(() => {
         if (browser) {
           let tab = gBrowser.getTabForBrowser(browser);
           if (tab && !tab.closing && tab.linkedBrowser) {
             gBrowser.removeTab(tab);
           }
         }
       });
 
-      yield SimpleTest.promiseFocus(browser);
+      await SimpleTest.promiseFocus(browser);
 
       loadFrameScripts(browser,
         'let { document, window, navigator } = content;',
         { name: 'common.js', dir: MOCHITESTS_DIR });
 
       Logger.log(
         `e10s enabled: ${Services.appinfo.browserTabsRemoteAutostart}`);
       Logger.log(`Actually remote browser: ${browser.isRemoteBrowser}`);
 
-      let event = yield onDocLoad;
-      yield task(browser, event.accessible);
+      let event = await onDocLoad;
+      await task(browser, event.accessible);
     });
   });
 }
 
 /**
  * Check if an accessible object has a defunct test.
  * @param  {nsIAccessible}  accessible object to test defunct state for
  * @return {Boolean}        flag indicating defunct state
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -197,17 +197,17 @@ pref("extensions.dss.switchPending", fal
 
 pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.name", "chrome://browser/locale/browser.properties");
 pref("extensions.{972ce4c6-7e08-4474-a285-3208198ce6fd}.description", "chrome://browser/locale/browser.properties");
 
 pref("extensions.webextensions.themes.icons.buttons", "back,forward,reload,stop,bookmark_star,bookmark_menu,downloads,home,app_menu,cut,copy,paste,new_window,new_private_window,save_page,print,history,full_screen,find,options,addons,developer,synced_tabs,open_file,sidebars,share_page,subscribe,text_encoding,email_link,forget,pocket");
 
 pref("lightweightThemes.update.enabled", true);
 pref("lightweightThemes.getMoreURL", "https://addons.mozilla.org/%LOCALE%/firefox/themes");
-pref("lightweightThemes.recommendedThemes", "[{\"id\":\"recommended-1\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/a-web-browser-renaissance/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.header.jpg\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.footer.jpg\",\"textcolor\":\"#000000\",\"accentcolor\":\"#f2d9b1\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.preview.jpg\",\"author\":\"Sean.Martell\",\"version\":\"0\"},{\"id\":\"recommended-2\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/space-fantasy/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.header.jpg\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.footer.jpg\",\"textcolor\":\"#ffffff\",\"accentcolor\":\"#d9d9d9\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.preview.jpg\",\"author\":\"fx5800p\",\"version\":\"1.0\"},{\"id\":\"recommended-4\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/pastel-gradient/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.header.png\",\"footerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.footer.png\",\"textcolor\":\"#000000\",\"accentcolor\":\"#000000\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.icon.png\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.preview.png\",\"author\":\"darrinhenein\",\"version\":\"1.0\"}]");
+pref("lightweightThemes.recommendedThemes", "[{\"id\":\"recommended-1\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/a-web-browser-renaissance/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.header.jpg\",\"textcolor\":\"#000000\",\"accentcolor\":\"#f2d9b1\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/1.preview.jpg\",\"author\":\"Sean.Martell\",\"version\":\"0\"},{\"id\":\"recommended-2\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/space-fantasy/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.header.jpg\",\"textcolor\":\"#ffffff\",\"accentcolor\":\"#d9d9d9\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.icon.jpg\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/2.preview.jpg\",\"author\":\"fx5800p\",\"version\":\"1.0\"},{\"id\":\"recommended-4\",\"homepageURL\":\"https://addons.mozilla.org/firefox/addon/pastel-gradient/\",\"headerURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.header.png\",\"textcolor\":\"#000000\",\"accentcolor\":\"#000000\",\"iconURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.icon.png\",\"previewURL\":\"resource:///chrome/browser/content/browser/defaultthemes/4.preview.png\",\"author\":\"darrinhenein\",\"version\":\"1.0\"}]");
 
 #if defined(MOZ_WIDEVINE_EME)
 pref("browser.eme.ui.enabled", true);
 #else
 pref("browser.eme.ui.enabled", false);
 #endif
 
 // UI tour experience.
@@ -542,20 +542,16 @@ pref("privacy.history.custom",          
 // 6 - Last 24 hours
 pref("privacy.sanitize.timeSpan", 1);
 pref("privacy.sanitize.sanitizeOnShutdown", false);
 
 pref("privacy.sanitize.migrateFx3Prefs",    false);
 
 pref("privacy.panicButton.enabled",         true);
 
-pref("privacy.firstparty.isolate",                        false);
-pref("privacy.firstparty.isolate.restrict_opener_access", true);
-pref("privacy.resistFingerprinting", false);
-
 // Time until temporary permissions expire, in ms
 pref("privacy.temporary_permission_expire_time_ms",  3600000);
 
 pref("network.proxy.share_proxy_settings",  false); // use the same proxy settings for all protocols
 
 // simple gestures support
 pref("browser.gesture.swipe.left", "Browser:BackOrBackDuplicate");
 pref("browser.gesture.swipe.right", "Browser:ForwardOrForwardDuplicate");
@@ -1271,16 +1267,19 @@ pref("pdfjs.firstRun", true);
 pref("pdfjs.previousHandler.preferredAction", 0);
 pref("pdfjs.previousHandler.alwaysAskBeforeHandling", false);
 
 // The maximum amount of decoded image data we'll willingly keep around (we
 // might keep around more than this, but we'll try to get down to this value).
 // (This is intentionally on the high side; see bug 746055.)
 pref("image.mem.max_decoded_image_kb", 256000);
 
+// Is the sidebar positioned ahead of the content browser
+pref("sidebar.position_start", true);
+
 // Activation from inside of share panel is possible if activationPanelEnabled
 // is true. Pref'd off for release while usage testing is done through beta.
 pref("social.share.activationPanelEnabled", true);
 pref("social.shareDirectory", "https://activations.cdn.mozilla.net/sharePanel.html");
 
 // Block insecure active content on https pages
 pref("security.mixed_content.block_active_content", true);
 
--- a/browser/base/content/browser-sidebar.js
+++ b/browser/base/content/browser-sidebar.js
@@ -16,27 +16,34 @@
  *                 display on the sidebar.
  *  - checked      indicates whether the sidebar is currently displayed.
  *                 Note that toggleSidebar updates this attribute when
  *                 it changes the sidebar's visibility.
  *  - group        this attribute must be set to "sidebar".
  */
 var SidebarUI = {
   browser: null,
+  POSITION_START_PREF: "sidebar.position_start",
 
   _box: null,
   _title: null,
   _splitter: null,
+  _icon: null,
+  _reversePositionButton: null,
+  _switcherPanel: null,
+  _switcherTarget: null,
+  _switcherArrow: null,
 
   init() {
     this._box = document.getElementById("sidebar-box");
     this.browser = document.getElementById("sidebar");
     this._title = document.getElementById("sidebar-title");
     this._splitter = document.getElementById("sidebar-splitter");
     this._icon = document.getElementById("sidebar-icon");
+    this._reversePositionButton = document.getElementById("sidebar-reverse-position");
     this._switcherPanel = document.getElementById("sidebarMenu-popup");
     this._switcherTarget = document.getElementById("sidebar-switcher-target");
     this._switcherArrow = document.getElementById("sidebar-switcher-arrow");
 
     this._switcherTarget.addEventListener("command", () => {
       this.toggleSwitcherPanel();
     });
   },
@@ -67,16 +74,23 @@ var SidebarUI = {
     this._switcherPanel.hidePopup();
   },
 
   showSwitcherPanel() {
     this._ensureShortcutsShown();
     this._switcherPanel.addEventListener("popuphiding", () => {
       this._switcherTarget.classList.remove("active");
     }, {once: true});
+
+    // Combine start/end position with ltr/rtl to set the label in the popup appropriately.
+    let label = this._positionStart == this.isRTL ?
+                  gNavigatorBundle.getString("sidebar.moveToLeft") :
+                  gNavigatorBundle.getString("sidebar.moveToRight");
+    this._reversePositionButton.setAttribute("label", label);
+
     this._switcherPanel.hidden = false;
     this._switcherPanel.openPopup(this._icon);
     this._switcherTarget.classList.add("active");
   },
 
   _addedShortcuts: false,
   _ensureShortcutsShown() {
     if (this._addedShortcuts) {
@@ -89,16 +103,47 @@ var SidebarUI = {
       if (!key) {
         continue;
       }
       button.setAttribute("shortcut", ShortcutUtils.prettifyShortcut(key));
     }
   },
 
   /**
+   * Change the pref that will trigger a call to setPosition
+   */
+  reversePosition() {
+    Services.prefs.setBoolPref(this.POSITION_START_PREF, !this._positionStart);
+  },
+
+  /**
+   * Read the positioning pref and position the sidebar and the splitter
+   * appropriately within the browser container.
+   */
+  setPosition() {
+    // First reset all ordinals to match DOM ordering.
+    let browser = document.getElementById("browser");
+    [...browser.childNodes].forEach((node, i) => {
+      node.ordinal = i + 1;
+    });
+
+    if (!this._positionStart) {
+      // DOM ordering is:     |  sidebar-box  | splitter |   appcontent  |
+      // Want to display as:  |   appcontent  | splitter |  sidebar-box  |
+      // So we just swap box and appcontent ordering
+      let appcontent = document.getElementById("appcontent");
+      let boxOrdinal = this._box.ordinal;
+      this._box.ordinal = appcontent.ordinal;
+      appcontent.ordinal = boxOrdinal;
+    }
+
+    this.hideSwitcherPanel();
+  },
+
+  /**
    * Try and adopt the status of the sidebar from another window.
    * @param {Window} sourceWindow - Window to use as a source for sidebar status.
    * @return true if we adopted the state, or false if the caller should
    * initialize the state itself.
    */
   adoptFromWindow(sourceWindow) {
     // If the opener had a sidebar, open the same sidebar in our window.
     // The opener can be the hidden window too, if we're coming from the state
@@ -127,18 +172,17 @@ var SidebarUI = {
     this._box.setAttribute("width", sourceUI._box.boxObject.width);
 
     this._box.setAttribute("sidebarcommand", commandID);
     // Note: we're setting 'src' on this._box, which is a <vbox>, not on
     // the <browser id="sidebar">. This lets us delay the actual load until
     // delayedStartup().
     this._box.setAttribute("src", sourceUI.browser.getAttribute("src"));
 
-    this._box.hidden = false;
-    this._splitter.hidden = false;
+    this._setVisibility(true);
     commandElem.setAttribute("checked", "true");
     this.browser.setAttribute("src", this._box.getAttribute("src"));
     return true;
   },
 
   windowPrivacyMatches(w1, w2) {
     return PrivateBrowsingUtils.isWindowPrivate(w1) === PrivateBrowsingUtils.isWindowPrivate(w2);
   },
@@ -165,18 +209,17 @@ var SidebarUI = {
     // If we're not adopting settings from a parent window, set them now.
     let commandID = this._box.getAttribute("sidebarcommand");
     if (!commandID) {
       return;
     }
 
     let command = document.getElementById(commandID);
     if (command) {
-      this._box.hidden = false;
-      this._splitter.hidden = false;
+      this._setVisibility(true);
       command.setAttribute("checked", "true");
       this.browser.setAttribute("src", this._box.getAttribute("src"));
     } else {
       // Remove the |sidebarcommand| attribute, because the element it
       // refers to no longer exists, so we should assume this sidebar
       // panel has been uninstalled. (249883)
       this._box.removeAttribute("sidebarcommand");
     }
@@ -215,16 +258,29 @@ var SidebarUI = {
     return this._title.value;
   },
 
   set title(value) {
     this._title.value = value;
   },
 
   /**
+   * Internal helper to show/hide the box and splitter elements.
+   *
+   * @param {bool} visible
+   */
+  _setVisibility(visible) {
+    this._box.hidden = !visible;
+    this._splitter.hidden = !visible;
+    if (visible) {
+      this.setPosition();
+    }
+  },
+
+  /**
    * Toggle the visibility of the sidebar. If the sidebar is hidden or is open
    * with a different commandID, then the sidebar will be opened using the
    * specified commandID. Otherwise the sidebar will be hidden.
    *
    * @param {string} commandID ID of the xul:broadcaster element to use.
    * @return {Promise}
    */
   toggle(commandID = this.currentID) {
@@ -263,18 +319,17 @@ var SidebarUI = {
 
         if (broadcaster != sidebarBroadcaster) {
           broadcaster.removeAttribute("checked");
         } else {
           sidebarBroadcaster.setAttribute("checked", "true");
         }
       }
 
-      this._box.hidden = false;
-      this._splitter.hidden = false;
+      this._setVisibility(true);
 
       this.hideSwitcherPanel();
 
       this._box.setAttribute("sidebarcommand", sidebarBroadcaster.id);
       this.lastOpenedId = sidebarBroadcaster.id;
 
       let title = sidebarBroadcaster.getAttribute("sidebartitle");
       if (!title) {
@@ -342,28 +397,35 @@ var SidebarUI = {
     // until about:blank has loaded (which does not happen as long as the
     // element is hidden).
     this.browser.setAttribute("src", "about:blank");
     this.browser.docShell.createAboutBlankContentViewer(null);
 
     sidebarBroadcaster.removeAttribute("checked");
     this._box.setAttribute("sidebarcommand", "");
     this._title.value = "";
-    this._box.hidden = true;
-    this._splitter.hidden = true;
+    this._setVisibility(false);
 
     let selBrowser = gBrowser.selectedBrowser;
     selBrowser.focus();
     selBrowser.messageManager.sendAsyncMessage("Sidebar:VisibilityChange",
       {commandID, isOpen: false}
     );
     BrowserUITelemetry.countSidebarEvent(commandID, "hide");
   },
 };
 
+// Add getters related to the position here, since we will want them
+// available for both startDelayedLoad and init.
+XPCOMUtils.defineLazyPreferenceGetter(SidebarUI, "_positionStart",
+  SidebarUI.POSITION_START_PREF, true, SidebarUI.setPosition.bind(SidebarUI));
+XPCOMUtils.defineLazyGetter(SidebarUI, "isRTL", () => {
+  return getComputedStyle(document.documentElement).direction == "rtl";
+});
+
 /**
  * This exists for backwards compatibility - it will be called once a sidebar is
  * ready, following any request to show it.
  *
  * @deprecated
  */
 function fireSidebarFocusedEvent() {}
 
--- a/browser/base/content/browser-sync.js
+++ b/browser/base/content/browser-sync.js
@@ -275,52 +275,64 @@ var gSync = {
       replaceQueryString: true
     });
   },
 
   sendTabToDevice(url, clientId, title) {
     Weave.Service.clientsEngine.sendURIToClientForDisplay(url, clientId, title);
   },
 
-  populateSendTabToDevicesMenu(devicesPopup, url, title) {
+  populateSendTabToDevicesMenu(devicesPopup, url, title, createDeviceNodeFn) {
+    if (!createDeviceNodeFn) {
+      createDeviceNodeFn = (clientId, name, clientType) => {
+        let eltName = name ? "menuitem" : "menuseparator";
+        return document.createElement(eltName);
+      };
+    }
+
     // remove existing menu items
-    while (devicesPopup.hasChildNodes()) {
-      devicesPopup.firstChild.remove();
+    for (let i = devicesPopup.childNodes.length - 1; i >= 0; --i) {
+      let child = devicesPopup.childNodes[i];
+      if (child.classList.contains("sync-menuitem")) {
+        child.remove();
+      }
     }
 
     const fragment = document.createDocumentFragment();
 
     const onTargetDeviceCommand = (event) => {
       let clients = event.target.getAttribute("clientId") ?
         [event.target.getAttribute("clientId")] :
         this.remoteClients.map(client => client.id);
 
       clients.forEach(clientId => this.sendTabToDevice(url, clientId, title));
     }
 
-    function addTargetDevice(clientId, name) {
-      const targetDevice = document.createElement("menuitem");
+    function addTargetDevice(clientId, name, clientType) {
+      const targetDevice = createDeviceNodeFn(clientId, name, clientType);
       targetDevice.addEventListener("command", onTargetDeviceCommand, true);
-      targetDevice.setAttribute("class", "sendtab-target");
+      targetDevice.classList.add("sync-menuitem", "sendtab-target");
       targetDevice.setAttribute("clientId", clientId);
+      targetDevice.setAttribute("clientType", clientType);
       targetDevice.setAttribute("label", name);
       fragment.appendChild(targetDevice);
     }
 
     const clients = this.remoteClients;
     for (let client of clients) {
-      addTargetDevice(client.id, client.name);
+      addTargetDevice(client.id, client.name, client.type);
     }
 
     // "All devices" menu item
     if (clients.length > 1) {
-      const separator = document.createElement("menuseparator");
+      const separator = createDeviceNodeFn();
+      separator.classList.add("sync-menuitem");
       fragment.appendChild(separator);
       const allDevicesLabel = this.fxaStrings.GetStringFromName("sendTabToAllDevices.menuitem");
-      addTargetDevice("", allDevicesLabel);
+      addTargetDevice("", allDevicesLabel, "");
     }
 
     devicesPopup.appendChild(fragment);
   },
 
   isSendableURI(aURISpec) {
     if (!aURISpec) {
       return false;
--- a/browser/base/content/browser.css
+++ b/browser/base/content/browser.css
@@ -1128,16 +1128,39 @@ toolbarpaletteitem[place="palette"] > #d
   #PanelUI-remotetabs-tabslist > toolbarbutton > .toolbarbutton-icon,
   #PanelUI-recentlyClosedWindows > toolbarbutton > .toolbarbutton-icon,
   #PanelUI-recentlyClosedTabs > toolbarbutton > .toolbarbutton-icon,
   #PanelUI-historyItems > toolbarbutton > .toolbarbutton-icon {
     image-rendering: -moz-crisp-edges;
   }
 }
 
+#customization-container {
+  -moz-box-orient: horizontal;
+}
+
+#customization-container[photon] {
+  display: flex;
+  flex-direction: column;
+}
+
+#customization-container[photon] > #customization-content-container {
+  display: flex;
+  flex-grow: 1; /* Grow so there isn't empty space below the footer */
+  min-height: 0; /* Allow this to shrink so the footer doesn't get pushed out. */
+}
+
+#customization-container[photon] > #customization-content-container > #customization-palette-container {
+  flex-grow: 1;
+}
+
+#customization-panelHolder > #widget-overflow-fixed-list {
+  padding-bottom: 50px; /* Make sure there's always space to drop stuff. */
+}
+
 #customization-panelHolder {
   overflow-y: hidden;
 }
 
 #customization-panelWrapper,
 #customization-panelWrapper > .panel-arrowcontent {
   -moz-box-flex: 1;
 }
@@ -1305,9 +1328,16 @@ toolbarpaletteitem[place="palette"][hidd
 }
 
 .dragfeedback-tab {
   -moz-appearance: none;
   opacity: 0.65;
   -moz-window-shadow: none;
 }
 
+/* Page action menu */
+#page-action-sendToDeviceView-body[signedin] > #page-action-sendToDevice-fxa-button,
+#page-action-sendToDeviceView-body:not([signedin]) > #page-action-no-devices-button,
+#page-action-sendToDeviceView-body[hasdevices] > #page-action-no-devices-button {
+  display: none;
+}
+
 %include theme-vars.inc.css
--- a/browser/base/content/browser.js
+++ b/browser/base/content/browser.js
@@ -7107,17 +7107,18 @@ var gIdentityHandler = {
     if (sharing)
       this._identityBox.setAttribute("sharing", sharing);
     else
       this._identityBox.removeAttribute("sharing");
 
     this._sharingState = tab._sharingState;
 
     if (this._identityPopup.state == "open") {
-      this._handleHeightChange(() => this.updateSitePermissions());
+      this.updateSitePermissions();
+      this._identityPopupMultiView.descriptionHeightWorkaround();
     }
   },
 
   /**
    * Attempt to provide proper IDN treatment for host names
    */
   getEffectiveHost() {
     if (!this._IDNService)
@@ -7618,30 +7619,16 @@ var gIdentityHandler = {
     if (!this._permissionList.hasChildNodes() &&
         this._permissionReloadHint.hasAttribute("hidden")) {
       this._permissionEmptyHint.removeAttribute("hidden");
     } else {
       this._permissionEmptyHint.setAttribute("hidden", "true");
     }
   },
 
-  _handleHeightChange(aFunction, aWillShowReloadHint) {
-    let heightBefore = getComputedStyle(this._permissionList).height;
-    aFunction();
-    let heightAfter = getComputedStyle(this._permissionList).height;
-    // Showing the reload hint increases the height, we need to account for it.
-    if (aWillShowReloadHint) {
-      heightAfter = parseInt(heightAfter) +
-                    parseInt(getComputedStyle(this._permissionList.nextSibling).height);
-    }
-    let heightChange = parseInt(heightAfter) - parseInt(heightBefore);
-    if (heightChange)
-      this._identityPopupMultiView.setHeightToFit(heightChange);
-  },
-
   _createPermissionItem(aPermission) {
     let container = document.createElement("hbox");
     container.setAttribute("class", "identity-popup-permission-item");
     container.setAttribute("align", "center");
 
     let img = document.createElement("image");
     let classes = "identity-popup-permission-icon " + aPermission.id + "-icon";
     if (aPermission.state == SitePermissions.BLOCK)
@@ -7668,19 +7655,17 @@ var gIdentityHandler = {
     stateLabel.textContent = SitePermissions.getCurrentStateLabel(state, scope);
 
     let button = document.createElement("button");
     button.setAttribute("class", "identity-popup-permission-remove-button");
     let tooltiptext = gNavigatorBundle.getString("permissions.remove.tooltip");
     button.setAttribute("tooltiptext", tooltiptext);
     button.addEventListener("command", () => {
       let browser = gBrowser.selectedBrowser;
-      // Only resize the window if the reload hint was previously hidden.
-      this._handleHeightChange(() => this._permissionList.removeChild(container),
-                               this._permissionReloadHint.hasAttribute("hidden"));
+      this._permissionList.removeChild(container);
       if (aPermission.inUse &&
           ["camera", "microphone", "screen"].includes(aPermission.id)) {
         let windowId = this._sharingState.windowId;
         if (aPermission.id == "screen") {
           windowId = "screen:" + windowId;
         } else {
           // If we set persistent permissions or the sharing has
           // started due to existing persistent permissions, we need
@@ -7701,16 +7686,17 @@ var gIdentityHandler = {
           }
         }
         browser.messageManager.sendAsyncMessage("webrtc:StopSharing", windowId);
         webrtcUI.forgetActivePermissionsFromBrowser(gBrowser.selectedBrowser);
       }
       SitePermissions.remove(gBrowser.currentURI, aPermission.id, browser);
 
       this._permissionReloadHint.removeAttribute("hidden");
+      this._identityPopupMultiView.descriptionHeightWorkaround();
 
       // Set telemetry values for clearing a permission
       let histogram = Services.telemetry.getKeyedHistogramById("WEB_PERMISSION_CLEARED");
 
       let permissionType = 0;
       if (aPermission.state == SitePermissions.ALLOW &&
           aPermission.scope == SitePermissions.SCOPE_PERSISTENT) {
         // 1 : clear permanently allowed permission
@@ -7746,46 +7732,99 @@ var gPageActionButton = {
     return this.button = document.getElementById("urlbar-page-action-button");
   },
 
   get panel() {
     delete this.panel;
     return this.panel = document.getElementById("page-action-panel");
   },
 
+  get sendToDeviceBody() {
+    delete this.sendToDeviceBody;
+    return this.sendToDeviceBody = document.getElementById("page-action-sendToDeviceView-body");
+  },
+
   init() {
     if (getBoolPref("browser.photon.structure.enabled")) {
       this.button.hidden = false;
     }
   },
 
   onEvent(event) {
     event.stopPropagation();
 
     if ((event.type == "click" && event.button != 0) ||
         (event.type == "keypress" && event.charCode != KeyEvent.DOM_VK_SPACE &&
          event.keyCode != KeyEvent.DOM_VK_RETURN)) {
       return; // Left click, space or enter only
     }
 
+    this._preparePanelToBeShown();
     this.panel.hidden = false;
     this.panel.openPopup(this.button, "bottomcenter topright");
   },
 
+  _preparePanelToBeShown() {
+    let browser = gBrowser.selectedBrowser;
+    let url = browser.currentURI.spec;
+
+    let sendToDeviceItem =
+      document.getElementById("page-action-send-to-device-button");
+    sendToDeviceItem.disabled = !gSync.isSendableURI(url);
+  },
+
   copyURL() {
     this.panel.hidePopup();
     Cc["@mozilla.org/widget/clipboardhelper;1"]
       .getService(Ci.nsIClipboardHelper)
       .copyString(gBrowser.selectedBrowser.currentURI.spec);
   },
 
   emailLink() {
     this.panel.hidePopup();
     MailIntegration.sendLinkForBrowser(gBrowser.selectedBrowser);
   },
+
+  showSendToDeviceView(subviewButton) {
+    let browser = gBrowser.selectedBrowser;
+    let url = browser.currentURI.spec;
+    let title = browser.contentTitle;
+    let body = this.sendToDeviceBody;
+
+    gSync.populateSendTabToDevicesMenu(body, url, title, (clientId, name, clientType) => {
+      if (!name) {
+        return document.createElement("toolbarseparator");
+      }
+      let item = document.createElement("toolbarbutton");
+      item.classList.add("page-action-sendToDevice-device", "subviewbutton");
+      if (clientId) {
+        item.classList.add("subviewbutton-iconic");
+      }
+      return item;
+    });
+
+    if (gSync.remoteClients.length) {
+      body.setAttribute("hasdevices", "true");
+    } else {
+      body.removeAttribute("hasdevices");
+    }
+
+    if (UIState.get().status == UIState.STATUS_SIGNED_IN) {
+      body.setAttribute("signedin", "true");
+    } else {
+      body.removeAttribute("signedin");
+    }
+
+    PanelUI.showSubView("page-action-sendToDeviceView", subviewButton);
+  },
+
+  fxaButtonClicked() {
+    this.panel.hidePopup();
+    gSync.openPrefs();
+  },
 };
 
 /**
  * Fired on the "marionette-remote-control" system notification,
  * indicating if the browser session is under remote control.
  */
 const gRemoteControl = {
   observe(subject, topic, data) {
--- a/browser/base/content/browser.xul
+++ b/browser/base/content/browser.xul
@@ -316,16 +316,20 @@
       <toolbarbutton id="sidebar-switcher-tabs"
                      label="&syncedTabs.sidebar.label;"
                      class="subviewbutton subviewbutton-iconic"
                      observes="viewTabsSidebar"
                      oncommand="SidebarUI.show('viewTabsSidebar');">
          <observes element="viewTabsSidebar" attribute="checked"/>
        </toolbarbutton>
       <toolbarseparator/>
+      <toolbarbutton id="sidebar-reverse-position"
+                     class="subviewbutton"
+                     oncommand="SidebarUI.reversePosition()"/>
+      <toolbarseparator/>
       <toolbarbutton label="&sidebarMenuClose.label;"
                      class="subviewbutton"
                      oncommand="SidebarUI.hide()"/>
     </panel>
 
     <menupopup id="toolbar-context-menu"
                onpopupshowing="onViewToolbarsPopupShowing(event, document.getElementById('viewToolbarsMenuSeparator'));">
       <menuitem oncommand="gCustomizeMode.addToPanel(document.popupNode)"
@@ -456,16 +460,36 @@
             <toolbarbutton id="page-action-copy-url-button"
                            class="subviewbutton subviewbutton-iconic"
                            label="&copyURLCmd.label;"
                            command="PageAction:copyURL"/>
             <toolbarbutton id="page-action-email-link-button"
                            class="subviewbutton subviewbutton-iconic"
                            label="&emailPageCmd.label;"
                            command="PageAction:emailLink"/>
+            <toolbarbutton id="page-action-send-to-device-button"
+                           class="subviewbutton subviewbutton-iconic subviewbutton-nav"
+                           label="&sendToDevice.label;"
+                           closemenu="none"
+                           oncommand="gPageActionButton.showSendToDeviceView(this);"/>
+          </vbox>
+        </panelview>
+        <panelview id="page-action-sendToDeviceView"
+                   class="PanelUI-subView"
+                   title="&sendToDevice.viewTitle;">
+          <vbox id="page-action-sendToDeviceView-body" class="panel-subview-body">
+            <toolbarbutton id="page-action-sendToDevice-fxa-button"
+                           class="subviewbutton subviewbutton-iconic"
+                           label="&syncBrand.fxAccount.label;"
+                           shortcut="&sendToDevice.fxaRequired.label;"
+                           oncommand="gPageActionButton.fxaButtonClicked();"/>
+            <toolbarbutton id="page-action-no-devices-button"
+                           class="subviewbutton"
+                           label="&sendToDevice.noDevices.label;"
+                           disabled="true"/>
           </vbox>
         </panelview>
       </photonpanelmultiview>
     </panel>
 
     <!-- Bookmarks and history tooltip -->
     <tooltip id="bhTooltip"/>
 
deleted file mode 100644
index cb5ff2705c4bb2ad5ad898439e59ef4190410cdc..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index a8cce0ef8cd545da35b0b201446e834bb934e721..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 235a5ad54a4c654f8503ed07ec7105f9d3282beb..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index bd944d58bc31095c60812ce2eff07c8e5b8fec6a..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 8e87c69a0fb05c78b9ae8e588f0d4bcc7ca66ae8..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..80ccf783577b136c2ff80a7687d419e93e33a1c1
GIT binary patch
literal 398
zc%17D@N?(olHy`uVBq!ia0vp^0wB!61|;P_|4#%`Y)RhkE)4%caKYZ?lYt_f1s;*b
z3=G`DAk4@xYmNj^kiEpy*OmPtt2mE>>fws+00ss|X-^l&5R22j!5gy<8;ID<<YDcP
zvt`R~TjXR|!V_uzjNL?pKX#Vm{RfJ{?3WMPPuQ6KcB6t<HrGuT@#cEP3%;>hir$Xj
ze5;n1FJG>1%fucUs>yP|QoU?X(a|2mGY&V^j)<yzHtl=g%$Iw6mX}g_vEQ3R#sW?W
zHM^Pxluk%C>zz~g_3p2}WB*^t_MM~VR}1ObIoj)+3d;|?ek^+IuHp&bxP{%tUw`_G
zxH5{o_gK5cd(Ju=F4GK8=kVE|J8#rR?7x%nyOx`wV)s9W2G2jAKcpT3in~-T^qjlq
zdR|WV-uWv6ubVP71X=BLi<}m>&T^*VvQ0YCUn-YO$(Yq9!EEagbjp?Om%=$q#VWS8
n#1BGuwPR*+8kz4a{=wW5Q+M;Yo8v!V$T4`j`njxgN@xNAb;p?m
--- a/browser/base/content/test/general/bug592338.html
+++ b/browser/base/content/test/general/bug592338.html
@@ -1,16 +1,15 @@
 <html>
 <head>
 <script type="text/javascript">
 var theme = {
   id: "test",
   name: "Test Background",
   headerURL: "http://example.com/firefox/personas/01/header.jpg",
-  footerURL: "http://example.com/firefox/personas/01/footer.jpg",
   textcolor: "#fff",
   accentcolor: "#6b6b6b"
 };
 
 function setTheme(node) {
   node.setAttribute("data-browsertheme", JSON.stringify(theme));
   var event = document.createEvent("Events");
   event.initEvent("InstallBrowserTheme", true, false);
--- a/browser/base/content/test/general/contextmenu_common.js
+++ b/browser/base/content/test/general/contextmenu_common.js
@@ -43,18 +43,18 @@ function getVisibleMenuItems(aMenu, aDat
 
         var key = item.accessKey;
         if (key)
             key = key.toLowerCase();
 
         var isPageMenuItem = item.hasAttribute("generateditemid");
 
         if (item.nodeName == "menuitem") {
-            var isGenerated = item.className == "spell-suggestion"
-                              || item.className == "sendtab-target";
+            var isGenerated = item.classList.contains("spell-suggestion")
+                              || item.classList.contains("sendtab-target");
             if (isGenerated) {
               is(item.id, "", "child menuitem #" + i + " is generated");
             } else if (isPageMenuItem) {
               is(item.id, "", "child menuitem #" + i + " is a generated page menu item");
             } else {
               ok(item.id, "child menuitem #" + i + " has an ID");
             }
             var label = item.getAttribute("label");
--- a/browser/base/content/test/sidebar/browser.ini
+++ b/browser/base/content/test/sidebar/browser.ini
@@ -1,4 +1,5 @@
 [DEFAULT]
 
 [browser_bug409481.js]
+[browser_sidebar_move.js]
 [browser_sidebar_switcher.js]
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/sidebar/browser_sidebar_move.js
@@ -0,0 +1,54 @@
+
+registerCleanupFunction(() => {
+  Services.prefs.clearUserPref("sidebar.position_start");
+  SidebarUI.hide();
+});
+
+const EXPECTED_START_ORDINALS = [
+  ["browser-border-start", 1],
+  ["sidebar-box", 2],
+  ["sidebar-splitter", 3],
+  ["appcontent", 4],
+  ["browser-border-end", 5],
+];
+
+const EXPECTED_END_ORDINALS = [
+  ["browser-border-start", 1],
+  ["sidebar-box", 4],
+  ["sidebar-splitter", 3],
+  ["appcontent", 2],
+  ["browser-border-end", 5],
+];
+
+function getBrowserChildrenWithOrdinals() {
+  let browser = document.getElementById("browser");
+  return [...browser.childNodes].map(node => {
+    return [node.id, node.ordinal];
+  });
+}
+
+add_task(function* () {
+  yield SidebarUI.show("viewBookmarksSidebar");
+  SidebarUI.showSwitcherPanel();
+
+  let reversePositionButton = document.getElementById("sidebar-reverse-position");
+  let originalLabel = reversePositionButton.getAttribute("label");
+
+  // Default (position: left)
+  Assert.deepEqual(getBrowserChildrenWithOrdinals(),
+    EXPECTED_START_ORDINALS, "Correct ordinal (start)");
+
+  // Moved to right
+  SidebarUI.reversePosition();
+  SidebarUI.showSwitcherPanel();
+  Assert.deepEqual(getBrowserChildrenWithOrdinals(),
+    EXPECTED_END_ORDINALS, "Correct ordinal (end)");
+  isnot(reversePositionButton.getAttribute("label"), originalLabel, "Label changed");
+
+  // Moved to back to left
+  SidebarUI.reversePosition();
+  SidebarUI.showSwitcherPanel();
+  Assert.deepEqual(getBrowserChildrenWithOrdinals(),
+    EXPECTED_START_ORDINALS, "Correct ordinal (start)");
+  is(reversePositionButton.getAttribute("label"), originalLabel, "Label is back to normal");
+});
--- a/browser/base/content/test/sidebar/browser_sidebar_switcher.js
+++ b/browser/base/content/test/sidebar/browser_sidebar_switcher.js
@@ -1,8 +1,12 @@
+
+registerCleanupFunction(() => {
+  SidebarUI.hide();
+});
 
 function showSwitcherPanelPromise() {
   return new Promise(resolve => {
     SidebarUI._switcherPanel.addEventListener("popupshown", () => {
       resolve();
     }, {once: true});
     SidebarUI.showSwitcherPanel();
   });
--- a/browser/base/content/test/urlbar/browser.ini
+++ b/browser/base/content/test/urlbar/browser.ini
@@ -109,8 +109,10 @@ support-files =
   slow-page.sjs
 [browser_urlbar_remoteness_switch.js]
 run-if = e10s
 [browser_urlHighlight.js]
 [browser_wyciwyg_urlbarCopying.js]
 subsuite = clipboard
 support-files =
   test_wyciwyg_copying.html
+[browser_page_action_menu.js]
+run-if = nightly_build # Photon only
new file mode 100644
--- /dev/null
+++ b/browser/base/content/test/urlbar/browser_page_action_menu.js
@@ -0,0 +1,317 @@
+"use strict";
+
+let gPanel = document.getElementById("page-action-panel");
+
+add_task(async function copyURL() {
+  // Open the panel.
+  await promisePanelOpen();
+
+  // Click Copy URL.
+  let copyURLButton = document.getElementById("page-action-copy-url-button");
+  let hiddenPromise = promisePanelHidden();
+  EventUtils.synthesizeMouseAtCenter(copyURLButton, {});
+  await hiddenPromise;
+
+  // Check the clipboard.
+  let transferable = Cc["@mozilla.org/widget/transferable;1"]
+                       .createInstance(Ci.nsITransferable);
+  transferable.init(null);
+  let flavor = "text/unicode";
+  transferable.addDataFlavor(flavor);
+  Services.clipboard.getData(transferable, Services.clipboard.kGlobalClipboard);
+  let strObj = {};
+  transferable.getTransferData(flavor, strObj, {});
+  Assert.ok(!!strObj.value);
+  strObj.value.QueryInterface(Ci.nsISupportsString);
+  Assert.equal(strObj.value.data, gBrowser.selectedBrowser.currentURI.spec);
+});
+
+add_task(async function emailLink() {
+  // Replace the email-link entry point to check whether it's called.
+  let originalFn = MailIntegration.sendLinkForBrowser;
+  let fnCalled = false;
+  MailIntegration.sendLinkForBrowser = () => {
+    fnCalled = true;
+  };
+  registerCleanupFunction(() => {
+    MailIntegration.sendLinkForBrowser = originalFn;
+  });
+
+  // Open the panel and click Email Link.
+  await promisePanelOpen();
+  let emailLinkButton =
+    document.getElementById("page-action-email-link-button");
+  let hiddenPromise = promisePanelHidden();
+  EventUtils.synthesizeMouseAtCenter(emailLinkButton, {});
+  await hiddenPromise;
+
+  Assert.ok(fnCalled);
+});
+
+add_task(async function sendToDevice_nonSendable() {
+  // Open a tab that's not sendable.
+  await BrowserTestUtils.withNewTab("about:blank", async () => {
+    // Open the panel.  Send to Device should be disabled.
+    await promisePanelOpen();
+    let sendToDeviceButton =
+      document.getElementById("page-action-send-to-device-button");
+    Assert.ok(sendToDeviceButton.disabled);
+    let hiddenPromise = promisePanelHidden();
+    gPanel.hidePopup();
+    await hiddenPromise;
+  });
+});
+
+add_task(async function sendToDevice_notSignedIn() {
+  // Open a tab that's sendable.
+  await BrowserTestUtils.withNewTab("http://example.com/", async () => {
+    await promiseSyncReady();
+
+    // Open the panel.
+    await promisePanelOpen();
+    let sendToDeviceButton =
+      document.getElementById("page-action-send-to-device-button");
+    Assert.ok(!sendToDeviceButton.disabled);
+
+    // Click Send to Device.
+    let viewPromise = promiseViewShown();
+    EventUtils.synthesizeMouseAtCenter(sendToDeviceButton, {});
+    let view = await viewPromise;
+    Assert.equal(view.id, "page-action-sendToDeviceView");
+
+    // The Fxa button should be shown.
+    checkSendToDeviceItems([
+      {
+        id: "page-action-sendToDevice-fxa-button",
+      },
+      {
+        id: "page-action-no-devices-button",
+        display: "none",
+        disabled: true,
+      },
+    ]);
+
+    // Click the Fxa button.
+    let body = view.firstChild;
+    let fxaButton = body.childNodes[0];
+    Assert.equal(fxaButton.id, "page-action-sendToDevice-fxa-button");
+    let prefsTabPromise = BrowserTestUtils.waitForNewTab(gBrowser);
+    let hiddenPromise = promisePanelHidden();
+    EventUtils.synthesizeMouseAtCenter(fxaButton, {});
+    let values = await Promise.all([prefsTabPromise, hiddenPromise]);
+    let tab = values[0];
+
+    // The Fxa prefs pane should open.  The full URL is something like:
+    //   about:preferences?entrypoint=syncbutton#sync
+    // Just make sure it's about:preferences#sync.
+    let urlObj = new URL(gBrowser.selectedBrowser.currentURI.spec);
+    let url = urlObj.protocol + urlObj.pathname + urlObj.hash;
+    Assert.equal(url, "about:preferences#sync");
+
+    await BrowserTestUtils.removeTab(tab);
+  });
+});
+
+add_task(async function sendToDevice_noDevices() {
+  // Open a tab that's sendable.
+  await BrowserTestUtils.withNewTab("http://example.com/", async () => {
+    await promiseSyncReady();
+    UIState._internal._state = { status: UIState.STATUS_SIGNED_IN };
+
+    // Open the panel.
+    await promisePanelOpen();
+    let sendToDeviceButton =
+      document.getElementById("page-action-send-to-device-button");
+    Assert.ok(!sendToDeviceButton.disabled);
+
+    // Click Send to Device.
+    let viewPromise = promiseViewShown();
+    EventUtils.synthesizeMouseAtCenter(sendToDeviceButton, {});
+    let view = await viewPromise;
+    Assert.equal(view.id, "page-action-sendToDeviceView");
+
+    // The no-devices item should be shown.
+    checkSendToDeviceItems([
+      {
+        id: "page-action-sendToDevice-fxa-button",
+        display: "none",
+      },
+      {
+        id: "page-action-no-devices-button",
+        disabled: true,
+      },
+    ]);
+
+    // Done, hide the panel.
+    let hiddenPromise = promisePanelHidden();
+    gPanel.hidePopup();
+    await hiddenPromise;
+
+    await UIState.reset();
+  });
+});
+
+add_task(async function sendToDevice_devices() {
+  // Open a tab that's sendable.
+  await BrowserTestUtils.withNewTab("http://example.com/", async () => {
+    await promiseSyncReady();
+    UIState._internal._state = { status: UIState.STATUS_SIGNED_IN };
+
+    // Set up mock remote clients.
+    let mockRemoteClients = [
+      { id: "0", name: "foo", type: "mobile" },
+      { id: "1", name: "bar", type: "desktop" },
+      { id: "2", name: "baz", type: "mobile" },
+    ];
+    let originalGetter =
+      Object.getOwnPropertyDescriptor(gSync, "remoteClients").get;
+    Object.defineProperty(gSync, "remoteClients", {
+      get() { return mockRemoteClients; }
+    });
+    let cleanUp = () => {
+      Object.defineProperty(gSync, "remoteClients", {
+        get: originalGetter
+      });
+    };
+    registerCleanupFunction(cleanUp);
+
+    // Open the panel.
+    await promisePanelOpen();
+    let sendToDeviceButton =
+      document.getElementById("page-action-send-to-device-button");
+    Assert.ok(!sendToDeviceButton.disabled);
+
+    // Click Send to Device.
+    let viewPromise = promiseViewShown();
+    EventUtils.synthesizeMouseAtCenter(sendToDeviceButton, {});
+    let view = await viewPromise;
+    Assert.equal(view.id, "page-action-sendToDeviceView");
+
+    // The devices should be shown in the subview.
+    let expectedItems = [
+      {
+        id: "page-action-sendToDevice-fxa-button",
+        display: "none",
+      },
+      {
+        id: "page-action-no-devices-button",
+        display: "none",
+        disabled: true,
+      },
+    ];
+    for (let client of mockRemoteClients) {
+      expectedItems.push({
+        attrs: {
+          clientId: client.id,
+          label: client.name,
+          clientType: client.type,
+        },
+      });
+    }
+    expectedItems.push(
+      null,
+      {
+        label: "All Devices",
+      }
+    );
+    checkSendToDeviceItems(expectedItems);
+
+    // Done, hide the panel.
+    let hiddenPromise = promisePanelHidden();
+    gPanel.hidePopup();
+    await hiddenPromise;
+
+    cleanUp();
+    await UIState.reset();
+  });
+});
+
+function promisePanelOpen() {
+  let button = document.getElementById("urlbar-page-action-button");
+  let shownPromise = promisePanelShown();
+  EventUtils.synthesizeMouseAtCenter(button, {});
+  return shownPromise;
+}
+
+function promisePanelShown() {
+  return promisePanelEvent("popupshown");
+}
+
+function promisePanelHidden() {
+  return promisePanelEvent("popuphidden");
+}
+
+function promisePanelEvent(name) {
+  return new Promise(resolve => {
+    gPanel.addEventListener(name, () => {
+      setTimeout(() => {
+        resolve();
+      });
+    }, { once: true });
+  });
+}
+
+function promiseViewShown() {
+  return Promise.all([
+    promiseViewShowing(),
+    promiseTransitionEnd(),
+  ]).then(values => {
+    return new Promise(resolve => {
+      setTimeout(() => {
+        resolve(values[0]);
+      });
+    });
+  });
+}
+
+function promiseViewShowing() {
+  return new Promise(resolve => {
+    gPanel.addEventListener("ViewShowing", (event) => {
+      resolve(event.target);
+    }, { once: true });
+  });
+}
+
+function promiseTransitionEnd() {
+  return new Promise(resolve => {
+    gPanel.addEventListener("transitionend", (event) => {
+      resolve(event.target);
+    }, { once: true });
+  });
+}
+
+function promiseSyncReady() {
+  let service = Cc["@mozilla.org/weave/service;1"]
+                  .getService(Components.interfaces.nsISupports)
+                  .wrappedJSObject;
+  return service.whenLoaded().then(() => {
+    UIState.isReady();
+    return UIState.refresh();
+  });
+}
+
+function checkSendToDeviceItems(expectedItems) {
+  let body = document.getElementById("page-action-sendToDeviceView-body");
+  Assert.equal(body.childNodes.length, expectedItems.length);
+  for (let i = 0; i < expectedItems.length; i++) {
+    let expected = expectedItems[i];
+    let actual = body.childNodes[i];
+    if (!expected) {
+      Assert.equal(actual.localName, "toolbarseparator");
+      continue;
+    }
+    if ("id" in expected) {
+      Assert.equal(actual.id, expected.id);
+    }
+    let display = "display" in expected ? expected.display : "-moz-box";
+    Assert.equal(getComputedStyle(actual).display, display);
+    let disabled = "disabled" in expected ? expected.disabled : false;
+    Assert.equal(actual.disabled, disabled);
+    if ("attrs" in expected) {
+      for (let name in expected.attrs) {
+        Assert.ok(actual.hasAttribute(name));
+        Assert.equal(actual.getAttribute(name), expected.attrs[name]);
+      }
+    }
+  }
+}
--- a/browser/base/content/test/urlbar/browser_urlbarSearchSuggestions_opt-out.js
+++ b/browser/base/content/test/urlbar/browser_urlbarSearchSuggestions_opt-out.js
@@ -1,58 +1,63 @@
 // The order of the tests here matters!
 
 const SUGGEST_ALL_PREF = "browser.search.suggest.enabled";
 const SUGGEST_URLBAR_PREF = "browser.urlbar.suggest.searches";
 const CHOICE_PREF = "browser.urlbar.userMadeSearchSuggestionsChoice";
 const TIMES_PREF = "browser.urlbar.timesBeforeHidingSuggestionsHint";
 const TEST_ENGINE_BASENAME = "searchSuggestionEngine.xml";
+const ONEOFF_PREF = "browser.urlbar.oneOffSearches";
 
 add_task(async function prepare() {
   let engine = await promiseNewSearchEngine(TEST_ENGINE_BASENAME);
   let oldCurrentEngine = Services.search.currentEngine;
   Services.search.currentEngine = engine;
   let suggestionsEnabled = Services.prefs.getBoolPref(SUGGEST_URLBAR_PREF);
   let defaults = Services.prefs.getDefaultBranch("browser.urlbar.");
   let searchSuggestionsDefault = defaults.getBoolPref("suggest.searches");
   defaults.setBoolPref("suggest.searches", true);
   let suggestionsChoice = Services.prefs.getBoolPref(CHOICE_PREF);
   Services.prefs.setBoolPref(CHOICE_PREF, false);
+  let oneOffs = Services.prefs.getBoolPref(ONEOFF_PREF);
+  Services.prefs.setBoolPref(ONEOFF_PREF, true);
   registerCleanupFunction(async function() {
     defaults.setBoolPref("suggest.searches", searchSuggestionsDefault);
     Services.search.currentEngine = oldCurrentEngine;
     Services.prefs.clearUserPref(SUGGEST_ALL_PREF);
     Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, suggestionsEnabled);
     Services.prefs.setBoolPref(CHOICE_PREF, suggestionsChoice);
-
+    Services.prefs.setBoolPref(ONEOFF_PREF, oneOffs);
     // Make sure the popup is closed for the next test.
     gURLBar.blur();
     Assert.ok(!gURLBar.popup.popupOpen, "popup should be closed");
   });
 });
 
 add_task(async function focus() {
   // Focusing the urlbar should open the popup in order to show the
   // notification.
   setupVisibleHint();
   gURLBar.blur();
   let popupPromise = promisePopupShown(gURLBar.popup);
   gURLBar.focus();
   await popupPromise;
   Assert.ok(gURLBar.popup.popupOpen, "popup should be open");
   assertVisible(true);
+  assertFooterVisible(false);
   Assert.equal(gURLBar.popup._matchCount, 0, "popup should have no results");
 
   // Start searching.
   EventUtils.synthesizeKey("r", {});
   EventUtils.synthesizeKey("n", {});
   EventUtils.synthesizeKey("d", {});
   await promiseSearchComplete();
   Assert.ok(suggestionsPresent());
   assertVisible(true);
+  assertFooterVisible(true);
 
   // Check the Change Options link.
   let changeOptionsLink = document.getElementById("search-suggestions-change-settings");
   let prefsPromise = BrowserTestUtils.waitForLocationChange(gBrowser, "about:preferences#general-search");
   changeOptionsLink.click();
   await prefsPromise;
   Assert.ok(!gURLBar.popup.popupOpen, "popup should be closed");
 });
@@ -60,35 +65,38 @@ add_task(async function focus() {
 
 add_task(async function privateWindow() {
   // Since suggestions are disabled in private windows, the notification should
   // not appear even when suggestions are otherwise enabled.
   setupVisibleHint();
   let win = await BrowserTestUtils.openNewBrowserWindow({ private: true });
   await promiseAutocompleteResultPopup("foo", win);
   assertVisible(false, win);
+  assertFooterVisible(true, win);
   win.gURLBar.blur();
   await BrowserTestUtils.closeWindow(win);
 });
 
 add_task(async function enableOutsideNotification() {
   // Setting the suggest.searches pref outside the notification (e.g., by
   // ticking the checkbox in the preferences window) should hide it.
   setupVisibleHint();
   Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, false);
   await promiseAutocompleteResultPopup("foo");
   assertVisible(false);
+  assertFooterVisible(true);
 });
 
 add_task(async function userMadeChoice() {
   // If the user made a choice already, he should not see the hint.
   setupVisibleHint();
   Services.prefs.setBoolPref(CHOICE_PREF, true);
   await promiseAutocompleteResultPopup("foo");
   assertVisible(false);
+  assertFooterVisible(true);
 });
 
 function setupVisibleHint() {
   Services.prefs.clearUserPref(TIMES_PREF);
   Services.prefs.setBoolPref(SUGGEST_ALL_PREF, true);
   // Toggle to reset the whichNotification cache.
   Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, false);
   Services.prefs.setBoolPref(SUGGEST_URLBAR_PREF, true);
@@ -111,8 +119,12 @@ function suggestionsPresent() {
   return false;
 }
 
 function assertVisible(visible, win = window) {
   let style =
     win.getComputedStyle(win.gURLBar.popup.searchSuggestionsNotification);
   Assert.equal(style.visibility, visible ? "visible" : "collapse");
 }
+function assertFooterVisible(visible, win = window) {
+  let style = win.getComputedStyle(win.gURLBar.popup.footer);
+  Assert.equal(style.visibility, visible ? "visible" : "collapse");
+}
--- a/browser/base/content/urlbarBindings.xml
+++ b/browser/base/content/urlbarBindings.xml
@@ -1340,19 +1340,16 @@ file, You can obtain one at http://mozil
           // If available, use the cached value, rather than running all of the
           // checks again at every locationbar focus.
           if (this._whichSearchSuggestionsNotification) {
             return this._whichSearchSuggestionsNotification;
           }
 
           if (Services.prefs.getBoolPref("browser.search.suggest.enabled") &&
               !this.inPrivateContext &&
-              // When _urlbarFocused is true, tabbrowser would close the
-              // popup if it's opened here, so don't show the notification.
-              !gBrowser.selectedBrowser._urlbarFocused &&
               // In any case, if the user made a choice we should not nag him.
               !this._userMadeSearchSuggestionsChoice) {
             let enabledByDefault = this._defaultPrefs.getBoolPref("suggest.searches");
             if (!enabledByDefault &&
                 this._prefs.getIntPref("daysBeforeHidingSuggestionsPrompt")) {
               return "opt-in";
             }
             if (enabledByDefault &&
@@ -1418,44 +1415,41 @@ file, You can obtain one at http://mozil
       <handler event="focus"><![CDATA[
         if (event.originalTarget == this.inputField) {
           this._hideURLTooltip();
           this.formatValue();
           if (this.getAttribute("pageproxystate") != "valid") {
             UpdatePopupNotificationsVisibility();
           }
 
-          // We may want to show the search suggestions hint.
-          if (!gBrowser.selectedBrowser._urlbarFocused) {
-            // We show the opt-out notification on every kind of focus to the urlbar
-            // included opening a new tab, but we want to enforce at least one
-            // notification when the user focuses it with the mouse.
-            let whichNotification = this.whichSearchSuggestionsNotification;
-            if (whichNotification == "opt-out" &&
-                this._showSearchSuggestionNotificationOnMouseFocus === undefined) {
-              this._showSearchSuggestionNotificationOnMouseFocus = true;
-            }
+          // We show the opt-out notification on every kind of focus to the urlbar
+          // included opening a new tab, but we want to enforce at least one
+          // notification when the user focuses it with the mouse.
+          let whichNotification = this.whichSearchSuggestionsNotification;
+          if (whichNotification == "opt-out" &&
+              this._showSearchSuggestionNotificationOnMouseFocus === undefined) {
+            this._showSearchSuggestionNotificationOnMouseFocus = true;
+          }
 
-            // Check whether the focus change came from a user mouse action.
-            let focusMethod = Services.focus.getLastFocusMethod(window);
-            let mouseFocused = !!(focusMethod & Services.focus.FLAG_BYMOUSE);
-            if (this._showSearchSuggestionNotificationOnMouseFocus &&
-                mouseFocused) {
-              // Force showing the opt-out notification.
-              this._whichSearchSuggestionsNotification = whichNotification = "opt-out";
-            }
+          // Check whether the focus change came from a user mouse action.
+          let focusMethod = Services.focus.getLastFocusMethod(window);
+          let mouseFocused = !!(focusMethod & Services.focus.FLAG_BYMOUSE);
+          if (this._showSearchSuggestionNotificationOnMouseFocus &&
+              mouseFocused) {
+            // Force showing the opt-out notification.
+            this._whichSearchSuggestionsNotification = whichNotification = "opt-out";
+          }
 
-            if (whichNotification == "opt-out") {
-              try {
-                this.popup.openAutocompletePopup(this, this);
-              } finally {
-                if (mouseFocused) {
-                  delete this._whichSearchSuggestionsNotification;
-                  this._showSearchSuggestionNotificationOnMouseFocus = false;
-                }
+          if (whichNotification == "opt-out") {
+            try {
+              this.popup.openAutocompletePopup(this, this);
+            } finally {
+              if (mouseFocused) {
+                delete this._whichSearchSuggestionsNotification;
+                this._showSearchSuggestionNotificationOnMouseFocus = false;
               }
             }
           }
         }
       ]]></handler>
 
       <handler event="blur"><![CDATA[
         if (event.originalTarget == this.inputField) {
@@ -1866,24 +1860,16 @@ file, You can obtain one at http://mozil
           // bottom of the navbar from the buttom of the input.
           let yOffset =
             this.DOMWindowUtils.getBoundsWithoutFlushing(document.getElementById("nav-bar")).bottom -
             this.DOMWindowUtils.getBoundsWithoutFlushing(aInput).bottom;
           this.openPopup(aElement, "after_start", 0, yOffset, false, false);
         ]]></body>
       </method>
 
-      <method name="_updateFooterVisibility">
-        <body>
-          <![CDATA[
-          this.footer.collapsed = this._matchCount == 0;
-          ]]>
-        </body>
-      </method>
-
       <method name="_showSearchSuggestionsNotification">
         <parameter name="whichNotification"/>
         <parameter name="popupDirection"/>
         <body>
           <![CDATA[
           let deckIndex = 0;
           if (whichNotification == "opt-out") {
             deckIndex = 1;
@@ -1918,17 +1904,19 @@ file, You can obtain one at http://mozil
           //
           // But without flexing the listbox, the listbox's height animation
           // sometimes fails to complete, leaving the popup too tall.  Work
           // around that problem by disabling the listbox animation.
           this.richlistbox.flex = 0;
           this.setAttribute("dontanimate", "true");
 
           this.classList.add("showSearchSuggestionsNotification");
-          this._updateFooterVisibility();
+          // Don't show the one-off buttons if we are showing onboarding and
+          // there's no result, since it would be ugly and pointless.
+          this.footer.collapsed = this._matchCount == 0;
 
           // This event allows accessibility APIs to see the notification.
           if (!this.popupOpen) {
             let event = document.createEvent("Events");
             event.initEvent("AlertActive", true, true);
             this.searchSuggestionsNotification.dispatchEvent(event);
           }
           ]]>
@@ -2097,16 +2085,19 @@ file, You can obtain one at http://mozil
             if (this.selectedIndex == -1 && this._isFirstResultHeuristic) {
               // Don't fire DOMMenuItemActive so that screen readers still see
               // the input as being focused.
               this.richlistbox.suppressMenuItemEvent = true;
               this.input.controller.setInitiallySelectedIndex(0);
               this.richlistbox.suppressMenuItemEvent = false;
             }
 
+            // When a result is present the footer should always be visible.
+            this.footer.collapsed = false;
+
             this.input.gotResultForCurrentQuery = true;
             this.input.maybeReplayDeferredKeyEvents();
           ]]>
         </body>
       </method>
 
       <method name="_onSearchBegin">
         <body><![CDATA[
--- a/browser/base/jar.mn
+++ b/browser/base/jar.mn
@@ -88,33 +88,28 @@ browser.jar:
         content/browser/browser-tabsintitlebar.js       (content/browser-tabsintitlebar-stub.js)
 #endif
         content/browser/browser-thumbnails.js         (content/browser-thumbnails.js)
         content/browser/browser-trackingprotection.js (content/browser-trackingprotection.js)
         content/browser/tab-content.js                (content/tab-content.js)
         content/browser/content.js                    (content/content.js)
         content/browser/social-content.js             (content/social-content.js)
         content/browser/default-theme-icon.svg        (content/default-theme-icon.svg)
-        content/browser/defaultthemes/1.footer.jpg    (content/defaultthemes/1.footer.jpg)
         content/browser/defaultthemes/1.header.jpg    (content/defaultthemes/1.header.jpg)
         content/browser/defaultthemes/1.icon.jpg      (content/defaultthemes/1.icon.jpg)
         content/browser/defaultthemes/1.preview.jpg   (content/defaultthemes/1.preview.jpg)
-        content/browser/defaultthemes/2.footer.jpg    (content/defaultthemes/2.footer.jpg)
         content/browser/defaultthemes/2.header.jpg    (content/defaultthemes/2.header.jpg)
         content/browser/defaultthemes/2.icon.jpg      (content/defaultthemes/2.icon.jpg)
         content/browser/defaultthemes/2.preview.jpg   (content/defaultthemes/2.preview.jpg)
-        content/browser/defaultthemes/3.footer.png    (content/defaultthemes/3.footer.png)
         content/browser/defaultthemes/3.header.png    (content/defaultthemes/3.header.png)
         content/browser/defaultthemes/3.icon.png      (content/defaultthemes/3.icon.png)
         content/browser/defaultthemes/3.preview.png   (content/defaultthemes/3.preview.png)
-        content/browser/defaultthemes/4.footer.png    (content/defaultthemes/4.footer.png)
         content/browser/defaultthemes/4.header.png    (content/defaultthemes/4.header.png)
         content/browser/defaultthemes/4.icon.png      (content/defaultthemes/4.icon.png)
         content/browser/defaultthemes/4.preview.png   (content/defaultthemes/4.preview.png)
-        content/browser/defaultthemes/5.footer.png    (content/defaultthemes/5.footer.png)
         content/browser/defaultthemes/5.header.png    (content/defaultthemes/5.header.png)
         content/browser/defaultthemes/5.icon.jpg      (content/defaultthemes/5.icon.jpg)
         content/browser/defaultthemes/5.preview.jpg   (content/defaultthemes/5.preview.jpg)
         content/browser/defaultthemes/compact.header.png    (content/defaultthemes/compact.header.png)
         content/browser/defaultthemes/compactdark.icon.svg  (content/defaultthemes/compactdark.icon.svg)
         content/browser/defaultthemes/compactlight.icon.svg (content/defaultthemes/compactlight.icon.svg)
         content/browser/newtab/newTab.xhtml           (content/newtab/newTab.xhtml)
 *       content/browser/newtab/newTab.js              (content/newtab/newTab.js)
@@ -124,16 +119,17 @@ browser.jar:
         content/browser/pageinfo/pageInfo.js          (content/pageinfo/pageInfo.js)
         content/browser/pageinfo/pageInfo.css         (content/pageinfo/pageInfo.css)
         content/browser/pageinfo/pageInfo.xml         (content/pageinfo/pageInfo.xml)
         content/browser/pageinfo/feeds.js             (content/pageinfo/feeds.js)
         content/browser/pageinfo/feeds.xml            (content/pageinfo/feeds.xml)
         content/browser/pageinfo/permissions.js       (content/pageinfo/permissions.js)
         content/browser/pageinfo/security.js          (content/pageinfo/security.js)
         content/browser/robot.ico                     (content/robot.ico)
+        content/browser/static-robot.png              (content/static-robot.png)
         content/browser/safeMode.css                  (content/safeMode.css)
         content/browser/safeMode.js                   (content/safeMode.js)
         content/browser/safeMode.xul                  (content/safeMode.xul)
         content/browser/sanitize.js                   (content/sanitize.js)
         content/browser/sanitize.xul                  (content/sanitize.xul)
         content/browser/sanitizeDialog.js             (content/sanitizeDialog.js)
         content/browser/sanitizeDialog.css            (content/sanitizeDialog.css)
         content/browser/contentSearchUI.js            (content/contentSearchUI.js)
--- a/browser/branding/nightly/pref/firefox-branding.js
+++ b/browser/branding/nightly/pref/firefox-branding.js
@@ -10,20 +10,22 @@ pref("app.update.interval", 7200); // 2 
 // The time interval between the downloading of mar file chunks in the
 // background (in seconds)
 // 0 means "download everything at once"
 pref("app.update.download.backgroundInterval", 0);
 // Give the user x seconds to react before showing the big UI. default=12 hours
 pref("app.update.promptWaitTime", 43200);
 // URL user can browse to manually if for some reason all update installation
 // attempts fail.
-pref("app.update.url.manual", "https://nightly.mozilla.org");
+pref("app.update.url.manual", "https://www.mozilla.org/%LOCALE%/firefox/nightly/");
 // A default value for the "More information about this update" link
 // supplied in the "An update is available" page of the update wizard.
-pref("app.update.url.details", "https://nightly.mozilla.org");
+pref("app.update.url.details", "https://www.mozilla.org/%LOCALE%/firefox/nightly/notes/");
+
+pref("app.releaseNotesURL", "https://www.mozilla.org/%LOCALE%/firefox/%VERSION%/releasenotes/?utm_source=firefox-browser&utm_medium=firefox-browser&utm_campaign=whatsnew");
 
 // The number of days a binary is permitted to be old
 // without checking for an update.  This assumes that
 // app.update.checkInstallTime is true.
 pref("app.update.checkInstallTime.days", 2);
 
 // Give the user x seconds to reboot before showing a badge on the hamburger
 // button. default=immediately
--- a/browser/components/controlcenter/content/panel.inc.xul
+++ b/browser/components/controlcenter/content/panel.inc.xul
@@ -11,17 +11,18 @@
        orient="vertical">
 
   <broadcasterset>
     <broadcaster id="identity-popup-mcb-learn-more" class="text-link plain" value="&identity.learnMore;"/>
     <broadcaster id="identity-popup-insecure-login-forms-learn-more" class="text-link plain" value="&identity.learnMore;"/>
   </broadcasterset>
 
   <panelmultiview id="identity-popup-multiView"
-                  mainViewId="identity-popup-mainView">
+                  mainViewId="identity-popup-mainView"
+                  descriptionheightworkaround="true">
     <panelview id="identity-popup-mainView" flex="1">
 
       <!-- Security Section -->
       <hbox id="identity-popup-security" class="identity-popup-section">
         <vbox id="identity-popup-security-content" flex="1">
           <label class="plain">
             <label class="identity-popup-headline identity-popup-host"></label>
             <label class="identity-popup-headline identity-popup-hostless" crop="end"/>
@@ -91,29 +92,29 @@
           <vbox id="identity-popup-permission-list"/>
           <description id="identity-popup-permission-reload-hint">&identity.permissionsReloadHint;</description>
           <description id="identity-popup-permission-empty-hint">&identity.permissionsEmpty;</description>
         </vbox>
       </hbox>
     </panelview>
 
     <!-- Security SubView -->
-    <panelview id="identity-popup-securityView" flex="1">
+    <panelview id="identity-popup-securityView">
       <vbox id="identity-popup-securityView-header">
         <label class="plain">
           <label class="identity-popup-headline identity-popup-host"></label>
           <label class="identity-popup-headline identity-popup-hostless" crop="end"/>
         </label>
         <description class="identity-popup-connection-not-secure"
                      when-connection="not-secure secure-cert-user-overridden">&identity.connectionNotSecure;</description>
         <description class="identity-popup-connection-secure"
                      when-connection="secure secure-ev">&identity.connectionSecure;</description>
       </vbox>
 
-      <vbox id="identity-popup-securityView-body" flex="1">
+      <vbox id="identity-popup-securityView-body" class="panel-view-body-unscrollable">
         <!-- (EV) Certificate Information -->
         <description id="identity-popup-content-verified-by"
                      when-connection="secure-ev">&identity.connectionVerified2;</description>
         <description id="identity-popup-content-owner"
                      when-connection="secure-ev"
                      class="header"/>
         <description id="identity-popup-content-supplemental"
                      when-connection="secure-ev"/>
--- a/browser/components/customizableui/CustomizeMode.jsm
+++ b/browser/components/customizableui/CustomizeMode.jsm
@@ -105,17 +105,17 @@ function CustomizeMode(aWindow) {
   this.visiblePalette = this.document.getElementById(kPaletteId);
   this.paletteEmptyNotice = this.document.getElementById("customization-empty");
   this.tipPanel = this.document.getElementById("customization-tipPanel");
   if (Services.prefs.getCharPref("general.skins.selectedSkin") != "classic/1.0") {
     let lwthemeButton = this.document.getElementById("customization-lwtheme-button");
     lwthemeButton.setAttribute("hidden", "true");
   }
   if (AppConstants.CAN_DRAW_IN_TITLEBAR) {
-    this._updateTitlebarButton();
+    this._updateTitlebarCheckbox();
     Services.prefs.addObserver(kDrawInTitlebarPref, this);
   }
   this.window.addEventListener("unload", this);
 }
 
 CustomizeMode.prototype = {
   _changed: false,
   _transitioning: false,
@@ -277,22 +277,42 @@ CustomizeMode.prototype = {
       // customization mode when pressing ESC.
       document.addEventListener("keypress", this);
 
       // Same goes for the menu button - if we're customizing, a click on the
       // menu button means a quick exit from customization mode.
       window.PanelUI.hide();
 
       let panelHolder = document.getElementById("customization-panelHolder");
+      let panelContainer = document.getElementById("customization-panel-container");
+      let customizationContainer = document.getElementById("customization-container");
+      let paletteContainer = document.getElementById("customization-palette-container");
+      let contentContainer = document.getElementById("customization-content-container");
+      let footer = document.getElementById("customization-footer");
+      let doneButton = document.getElementById("customization-done-button");
       if (gPhotonStructure) {
+        if (!customizationContainer.hasAttribute("photon")) {
+          contentContainer.appendChild(paletteContainer);
+          contentContainer.appendChild(panelContainer);
+          customizationContainer.appendChild(footer);
+          customizationContainer.setAttribute("photon", "true");
+          doneButton.hidden = false;
+        }
         panelHolder.appendChild(window.PanelUI.overflowFixedList);
         window.PanelUI.overflowFixedList.setAttribute("customizing", true);
         window.PanelUI.menuButton.disabled = true;
         document.getElementById("nav-bar-overflow-button").disabled = true;
       } else {
+        if (customizationContainer.hasAttribute("photon")) {
+          customizationContainer.insertBefore(paletteContainer, contentContainer);
+          customizationContainer.appendChild(panelContainer);
+          paletteContainer.appendChild(footer);
+          customizationContainer.removeAttribute("photon");
+          doneButton.hidden = true;
+        }
         window.PanelUI.menuButton.addEventListener("command", this);
         window.PanelUI.menuButton.open = true;
         window.PanelUI.beginBatchUpdate();
 
         // The menu panel is lazy, and registers itself when the popup shows. We
         // need to force the menu panel to register itself, or else customization
         // is really not going to work. We pass "true" to ensureReady to
         // indicate that we're handling calling startBatchUpdate and
@@ -1523,39 +1543,41 @@ CustomizeMode.prototype = {
   },
 
   observe(aSubject, aTopic, aData) {
     switch (aTopic) {
       case "nsPref:changed":
         this._updateResetButton();
         this._updateUndoResetButton();
         if (AppConstants.CAN_DRAW_IN_TITLEBAR) {
-          this._updateTitlebarButton();
+          this._updateTitlebarCheckbox();
         }
         break;
       case "lightweight-theme-window-updated":
         if (aSubject == this.window) {
           aData = JSON.parse(aData);
           this.updateLWTStyling(aData);
         }
         break;
     }
   },
 
-  _updateTitlebarButton() {
+  _updateTitlebarCheckbox() {
     if (!AppConstants.CAN_DRAW_IN_TITLEBAR) {
       return;
     }
     let drawInTitlebar = Services.prefs.getBoolPref(kDrawInTitlebarPref, true);
-    let button = this.document.getElementById("customization-titlebar-visibility-button");
-    // Drawing in the titlebar means 'hiding' the titlebar:
+    let checkbox = this.document.getElementById("customization-titlebar-visibility-checkbox");
+    // Drawing in the titlebar means 'hiding' the titlebar.
+    // We use the attribute rather than a property because if we're not in
+    // customize mode the button is hidden and properties don't work.
     if (drawInTitlebar) {
-      button.removeAttribute("checked");
+      checkbox.removeAttribute("checked");
     } else {
-      button.setAttribute("checked", "true");
+      checkbox.setAttribute("checked", "true");
     }
   },
 
   toggleTitlebar(aShouldShowTitlebar) {
     if (!AppConstants.CAN_DRAW_IN_TITLEBAR) {
       return;
     }
     // Drawing in the titlebar means not showing the titlebar, hence the negation:
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -166,30 +166,16 @@ this.PanelMultiView = class {
   }
   get _mainView() {
     return this._mainViewId ? this.document.getElementById(this._mainViewId) : null;
   }
   get showingSubViewAsMainView() {
     return this.node.getAttribute("mainViewIsSubView") == "true";
   }
 
-  get ignoreMutations() {
-    return this._ignoreMutations;
-  }
-  set ignoreMutations(val) {
-    this._ignoreMutations = val;
-    if (!val && this._panel.state == "open") {
-      if (this.showingSubView) {
-        this._syncContainerWithSubView();
-      } else {
-        this._syncContainerWithMainView();
-      }
-    }
-  }
-
   get _transitioning() {
     return this.__transitioning;
   }
   set _transitioning(val) {
     this.__transitioning = val;
     if (val) {
       this.node.setAttribute("transitioning", "true");
     } else {
@@ -259,23 +245,16 @@ this.PanelMultiView = class {
       // Set CSS-determined attributes now to prevent a layout flush when we do
       // it when transitioning between panels.
       this._dir = cs.direction;
       this.setMainView(this.panelViews.currentView);
       this.showMainView();
     } else {
       this._panel.addEventListener("popupshown", this);
       this._clickCapturer.addEventListener("click", this);
-      this._subViews.addEventListener("overflow", this);
-      this._mainViewContainer.addEventListener("overflow", this);
-
-      // Get a MutationObserver ready to react to subview size changes. We
-      // only attach this MutationObserver when a subview is being displayed.
-      this._subViewObserver = new window.MutationObserver(this._syncContainerWithSubView.bind(this));
-      this._mainViewObserver = new window.MutationObserver(this._syncContainerWithMainView.bind(this));
 
       this._mainViewContainer.setAttribute("panelid", this._panel.id);
 
       if (this._mainView) {
         this.setMainView(this._mainView);
       }
     }
 
@@ -285,35 +264,32 @@ this.PanelMultiView = class {
     // parts of the browser, to this instance.
     ["_mainView", "ignoreMutations", "showingSubView"].forEach(property => {
       Object.defineProperty(this.node, property, {
         enumerable: true,
         get: () => this[property],
         set: (val) => this[property] = val
       });
     });
-    ["goBack", "setHeightToFit", "setMainView", "showMainView", "showSubView"].forEach(method => {
+    ["goBack", "descriptionHeightWorkaround", "setMainView", "showMainView",
+     "showSubView"].forEach(method => {
       Object.defineProperty(this.node, method, {
         enumerable: true,
         value: (...args) => this[method](...args)
       });
     });
   }
 
   destructor() {
     if (this._mainView) {
       this._mainView.removeAttribute("mainview");
     }
     if (this.panelViews) {
       this.panelViews.clear();
     } else {
-      this._mainViewObserver.disconnect();
-      this._subViewObserver.disconnect();
-      this._subViews.removeEventListener("overflow", this);
-      this._mainViewContainer.removeEventListener("overflow", this);
       this._clickCapturer.removeEventListener("click", this);
     }
     this._panel.removeEventListener("popupshowing", this);
     this._panel.removeEventListener("popupshown", this);
     this._panel.removeEventListener("popuphidden", this);
     this.node = this._clickCapturer = this._viewContainer = this._mainViewContainer =
       this._subViews = this._viewStack = this.__dwu = null;
   }
@@ -340,17 +316,16 @@ this.PanelMultiView = class {
     if (this.panelViews) {
       // If the new main view is not yet in the zeroth position, make sure it's
       // inserted there.
       if (aNewMainView.parentNode != this._viewStack && this._viewStack.firstChild != aNewMainView) {
         this._viewStack.insertBefore(aNewMainView, this._viewStack.firstChild);
       }
     } else {
       if (this._mainView) {
-        this._mainViewObserver.disconnect();
         this._subViews.appendChild(this._mainView);
         this._mainView.removeAttribute("mainview");
       }
       this._mainViewId = aNewMainView.id;
       aNewMainView.setAttribute("mainview", "true");
       this._mainViewContainer.appendChild(aNewMainView);
     }
   }
@@ -359,24 +334,21 @@ this.PanelMultiView = class {
     if (this.panelViews) {
       this.showSubView(this._mainViewId);
     } else {
       if (this.showingSubView) {
         let viewNode = this._currentSubView;
         let evt = new this.window.CustomEvent("ViewHiding", { bubbles: true, cancelable: true });
         viewNode.dispatchEvent(evt);
 
-        viewNode.removeAttribute("current");
-        this._currentSubView = null;
-
-        this._subViewObserver.disconnect();
-
-        this._setViewContainerHeight(this._mainViewHeight);
-
-        this.node.setAttribute("viewtype", "main");
+        this._transitionHeight(() => {
+          viewNode.removeAttribute("current");
+          this._currentSubView = null;
+          this.node.setAttribute("viewtype", "main");
+        });
       }
 
       this._shiftMainView();
     }
   }
 
   showSubView(aViewId, aAnchor, aPreviousView, aAdopted = false) {
     const {document, window} = this;
@@ -474,19 +446,19 @@ this.PanelMultiView = class {
       //    node is at the left-most edge of the panel.
       // 2) The subview deck slides in so that it takes up almost all of the
       //    panel.
       // 3) If the subview is taller then the main panel contents, then the panel
       //    must grow to meet that new height. Otherwise, it must shrink.
       //
       // All three of these actions make use of CSS transformations, so they
       // should all occur simultaneously.
-      this.node.setAttribute("viewtype", "subview");
+      if (this.panelViews && playTransition) {
+        this.node.setAttribute("viewtype", "subview");
 
-      if (this.panelViews && playTransition) {
         // Sliding the next subview in means that the previous panelview stays
         // where it is and the active panelview slides in from the left in LTR
         // mode, right in RTL mode.
         let onTransitionEnd = () => {
           evt = new window.CustomEvent("ViewHiding", { bubbles: true, cancelable: true });
           previousViewNode.dispatchEvent(evt);
           previousViewNode.removeAttribute("current");
         };
@@ -599,44 +571,96 @@ this.PanelMultiView = class {
               if (aAnchor)
                 aAnchor.removeAttribute("open");
 
               this._viewContainer.removeAttribute("transition-reverse");
             }, { once: true });
           });
         }, { once: true });
       } else if (!this.panelViews) {
+        this._transitionHeight(() => {
+          viewNode.setAttribute("current", true);
+          this.node.setAttribute("viewtype", "subview");
+          // Now that the subview is visible, we can check the height of the
+          // description elements it contains.
+          this.descriptionHeightWorkaround(viewNode);
+        });
         this._shiftMainView(aAnchor);
-
-        this._mainViewHeight = this._viewStack.clientHeight;
-
-        let newHeight = this._heightOfSubview(viewNode, this._subViews);
-        this._setViewContainerHeight(newHeight);
-
-        this._subViewObserver.observe(viewNode, {
-          attributes: true,
-          characterData: true,
-          childList: true,
-          subtree: true
-        });
       }
     })();
   }
 
-  _setViewContainerHeight(aHeight) {
-    let container = this._viewContainer;
-    this._transitioning = true;
+  /**
+   * Applies the height transition for which <panelmultiview> is designed.
+   *
+   * The height transition involves two elements, the viewContainer and its only
+   * immediate child the viewStack. In order for this to work correctly, the
+   * viewContainer must have "overflow: hidden;" and the two elements must have
+   * no margins or padding. This means that the height of the viewStack is never
+   * limited by the viewContainer, but when the height of the container is not
+   * constrained it matches the height of the viewStack.
+   *
+   * @param changeFn
+   *        This synchronous function is called to make the DOM changes
+   *        that will result in a new height of the viewStack.
+   */
+  _transitionHeight(changeFn) {
+    if (this._panel.state != "open") {
+      changeFn();
+      return;
+    }
+
+    // Lock the dimensions of the window that hosts the popup panel. This
+    // in turn constrains the height of the viewContainer.
+    let rect = this._panel.popupBoxObject.getOuterScreenRect();
+    this._panel.setAttribute("width", rect.width);
+    this._panel.setAttribute("height", rect.height);
+
+    // Read the current height of the viewStack. If we are in the middle
+    // of a transition, this is the actual height of the element at this
+    // point in time.
+    let oldHeight = this._dwu.getBoundsWithoutFlushing(this._viewStack).height;
 
-    let onTransitionEnd = () => {
-      container.removeEventListener("transitionend", onTransitionEnd);
-      this._transitioning = false;
-    };
+    // Make the necessary DOM changes, and remove the "height" property of the
+    // viewStack to ensure that we read its final value even if we are in the
+    // middle of a transition. To avoid flickering, we have to prevent the panel
+    // from being painted in this temporary state, which requires a synchronous
+    // layout when reading the new height.
+    this._viewStack.style.removeProperty("height");
+    changeFn();
+    let newHeight = this._viewStack.getBoundingClientRect().height;
+
+    // Now we can allow the popup panel to resize again. This must occur
+    // in the same tick as the code below, but we can do this before
+    // setting the starting height in case the transition is not needed.
+    this._panel.removeAttribute("width");
+    this._panel.removeAttribute("height");
 
-    container.addEventListener("transitionend", onTransitionEnd);
-    container.style.height = `${aHeight}px`;
+    if (oldHeight != newHeight) {
+      // Height transitions can only occur between two numeric values, and
+      // cannot start if the height is not set. In case a transition is
+      // needed, we have to set the height to the old value, then force a
+      // synchronous layout so the panel won't resize unexpectedly.
+      this._viewStack.style.height = oldHeight + "px";
+      this._viewStack.getBoundingClientRect().height;
+
+      // We can now set the new height to start the transition, but
+      // before doing that we set up a listener to reset the height to
+      // "auto" at the end, so that DOM changes made after the
+      // transition ends are still reflected by the height of the panel.
+      let onTransitionEnd = event => {
+        if (event.target != this._viewStack) {
+          return;
+        }
+        this._viewStack.removeEventListener("transitionend", onTransitionEnd);
+        this._viewStack.style.removeProperty("height");
+      };
+      this._viewStack.addEventListener("transitionend", onTransitionEnd);
+      this._viewStack.style.height = newHeight + "px";
+    }
   }
 
   _shiftMainView(aAnchor) {
     if (aAnchor) {
       // We need to find the edge of the anchor, relative to the main panel.
       // Then we need to add half the width of the anchor. This is the target
       // that we need to transition to.
       let anchorRect = aAnchor.getBoundingClientRect();
@@ -682,58 +706,64 @@ this.PanelMultiView = class {
         }
         break;
       case "keydown":
         this._keyNavigation(aEvent);
         break;
       case "mousemove":
         this._resetKeyNavigation();
         break;
-      case "overflow":
-        if (!this.panelViews && aEvent.target.localName == "vbox") {
-          // Resize the right view on the next tick.
-          if (this.showingSubView) {
-            this.window.setTimeout(this._syncContainerWithSubView.bind(this), 0);
-          } else if (!this.transitioning) {
-            this.window.setTimeout(this._syncContainerWithMainView.bind(this), 0);
-          }
-        }
-        break;
       case "popupshowing":
         this.node.setAttribute("panelopen", "true");
         // Bug 941196 - The panel can get taller when opening a subview. Disabling
         // autoPositioning means that the panel won't jump around if an opened
         // subview causes the panel to exceed the dimensions of the screen in the
         // direction that the panel originally opened in. This property resets
         // every time the popup closes, which is why we have to set it each time.
         this._panel.autoPosition = false;
-
-        if (!this.panelViews) {
-          this._syncContainerWithMainView();
-          this._mainViewObserver.observe(this._mainView, {
-            attributes: true,
-            characterData: true,
-            childList: true,
-            subtree: true
-          });
-        } else {
+        if (this.panelViews) {
           this.window.addEventListener("keydown", this);
           this._panel.addEventListener("mousemove", this);
         }
         break;
       case "popupshown":
-        this._setMaxHeight();
+        // Now that the main view is visible, we can check the height of the
+        // description elements it contains.
+        this.descriptionHeightWorkaround();
+        // Now that the panel has opened, we can compute the distance from its
+        // anchor to the available margin of the screen, based on whether the
+        // panel actually opened towards the top or the bottom. We use this to
+        // limit its maximum height, which is relevant when opening a subview.
+        let maxHeight;
+        if (this._panel.alignmentPosition.startsWith("before_")) {
+          maxHeight = this._panel.getOuterScreenRect().bottom -
+                      this.window.screen.availTop;
+        } else {
+          maxHeight = this.window.screen.availTop +
+                      this.window.screen.availHeight -
+                      this._panel.getOuterScreenRect().top;
+        }
+        // To go from the maximum height of the panel to the maximum height of
+        // the view stack, we start by subtracting the height of the arrow box.
+        // We don't need to trigger a new layout because this does not change.
+        let arrowBox = this.document.getAnonymousElementByAttribute(
+                                        this._panel, "anonid", "arrowbox");
+        maxHeight -= this._dwu.getBoundsWithoutFlushing(arrowBox).height;
+        // We subtract a fixed margin to account for variable borders. We don't
+        // try to measure this accurately so it's faster, we don't depend on
+        // the arrowpanel structure, and we don't hit rounding errors. Instead,
+        // we use a value that is much greater than the typical borders and
+        // makes sense visually.
+        const EXTRA_MARGIN_PX = 8;
+        this._viewStack.style.maxHeight = (maxHeight - EXTRA_MARGIN_PX) + "px";
         break;
       case "popuphidden":
         this.node.removeAttribute("panelopen");
-        this._mainView.style.removeProperty("height");
         this.showMainView();
-        if (!this.panelViews) {
-          this._mainViewObserver.disconnect();
-        } else {
+        if (this.panelViews) {
           this.window.removeEventListener("keydown", this);
           this._panel.removeEventListener("mousemove", this);
           this._resetKeyNavigation();
           this._mainViewHeight = 0;
         }
         break;
     }
   }
@@ -867,138 +897,52 @@ this.PanelMultiView = class {
    */
   _getNavigableElements(view) {
     let buttons = Array.from(view.querySelectorAll(".subviewbutton:not([disabled])"));
     if (this._canGoBack(view))
       buttons.unshift(view.backButton);
     return buttons;
   }
 
-  _shouldSetPosition() {
-    return this.node.getAttribute("nosubviews") == "true";
-  }
-
-  _shouldSetHeight() {
-    return this.node.getAttribute("nosubviews") != "true";
-  }
-
-  _setMaxHeight() {
-    if (!this._shouldSetHeight())
-      return;
-
-    // Ignore the mutation that'll fire when we set the height of
-    // the main view.
-    this.ignoreMutations = true;
-    this._mainView.style.height = this.node.getBoundingClientRect().height + "px";
-    this.ignoreMutations = false;
-  }
-
-  _adjustContainerHeight() {
-    if (!this.ignoreMutations && !this.showingSubView && !this._transitioning) {
-      let height;
-      if (this.showingSubViewAsMainView) {
-        height = this._heightOfSubview(this._mainView);
-      } else {
-        height = this._mainView.scrollHeight;
-      }
-      this._viewContainer.style.height = height + "px";
-    }
-  }
-
-  _syncContainerWithSubView() {
-    // Check that this panel is still alive:
-    if (!this._panel || !this._panel.parentNode) {
-      return;
-    }
-
-    if (!this.ignoreMutations && this.showingSubView) {
-      let newHeight = this._heightOfSubview(this._currentSubView, this._subViews);
-      this._viewContainer.style.height = newHeight + "px";
-    }
-  }
-
-  _syncContainerWithMainView() {
-    // Check that this panel is still alive:
-    if (!this._panel || !this._panel.parentNode) {
+  /**
+   * If the main view or a subview contains wrapping elements, the attribute
+   * "descriptionheightworkaround" should be set on the view to force all the
+   * "description" elements to a fixed height. If the attribute is set and the
+   * visibility, contents, or width of any of these elements changes, this
+   * function should be called to refresh the calculated heights.
+   *
+   * @note While both "label" and "description" elements may contain wrapping
+   *       text, only "description" elements are used that way in panels.
+   *
+   * @param viewNode
+   *        Indicates the node to scan for descendant elements. This is the main
+   *        view if omitted.
+   */
+  descriptionHeightWorkaround(viewNode = this._mainView) {
+    if (!this.node.hasAttribute("descriptionheightworkaround")) {
+      // This view does not require the workaround.
       return;
     }
 
-    if (this._shouldSetPosition()) {
-      this._panel.adjustArrowPosition();
+    // We batch DOM changes together in order to reduce synchronous layouts.
+    // First we reset any change we may have made previously. The first time
+    // this is called, and in the best case scenario, this has no effect.
+    let items = [];
+    for (let element of viewNode.getElementsByTagName("description")) {
+      element.style.removeProperty("height");
+      items.push({ element });
     }
-
-    if (this._shouldSetHeight()) {
-      this._adjustContainerHeight();
+    // We now read the computed style to store the height of any element that
+    // may contain wrapping text, which will be zero if the element is hidden.
+    // This might trigger a synchronous layout, but if this function was called
+    // from a _transitionHeight callback and there are no description elements
+    // visible, then _transitionHeight will not trigger a layout again.
+    for (let item of items) {
+      item.height = item.element.getBoundingClientRect().height;
+    }
+    // Now we can make all the necessary DOM changes at once.
+    for (let item of items) {
+      if (item.height) {
+        item.element.style.height = item.height + "px";
+      }
     }
   }
-
-  /**
-   * Call this when the height of one of your views (the main view or a
-   * subview) changes and you want the heights of the multiview and panel
-   * to be the same as the view's height.
-   * If the caller can give a hint of the expected height change with the
-   * optional aExpectedChange parameter, it prevents flicker.
-   */
-  setHeightToFit(aExpectedChange) {
-    // Set the max-height to zero, wait until the height is actually
-    // updated, and then remove it.  If it's not removed, weird things can
-    // happen, like widgets in the panel won't respond to clicks even
-    // though they're visible.
-    const {window} = this;
-    let count = 5;
-    let height = window.getComputedStyle(this.node).height;
-    if (aExpectedChange)
-      this.node.style.maxHeight = (parseInt(height, 10) + aExpectedChange) + "px";
-    else
-      this.node.style.maxHeight = "0";
-    let interval = window.setInterval(() => {
-      if (height != window.getComputedStyle(this.node).height || --count == 0) {
-        window.clearInterval(interval);
-        this.node.style.removeProperty("max-height");
-      }
-    }, 0);
-  }
-
-  _heightOfSubview(aSubview, aContainerToCheck) {
-    function getFullHeight(element) {
-      // XXXgijs: unfortunately, scrollHeight rounds values, and there's no alternative
-      // that works with overflow: auto elements. Fortunately for us,
-      // we have exactly 1 (potentially) scrolling element in here (the subview body),
-      // and rounding 1 value is OK - rounding more than 1 and adding them means we get
-      // off-by-1 errors. Now we might be off by a subpixel, but we care less about that.
-      // So, use scrollHeight *only* if the element is vertically scrollable.
-      let height;
-      let elementCS;
-      if (element.scrollTopMax) {
-        height = element.scrollHeight;
-        // Bounding client rects include borders, scrollHeight doesn't:
-        elementCS = win.getComputedStyle(element);
-        height += parseFloat(elementCS.borderTopWidth) +
-                  parseFloat(elementCS.borderBottomWidth);
-      } else {
-        height = element.getBoundingClientRect().height;
-        if (height > 0) {
-          elementCS = win.getComputedStyle(element);
-        }
-      }
-      if (elementCS) {
-        // Include margins - but not borders or paddings because they
-        // were dealt with above.
-        height += parseFloat(elementCS.marginTop) + parseFloat(elementCS.marginBottom);
-      }
-      return height;
-    }
-    let win = aSubview.ownerGlobal;
-    let body = aSubview.querySelector(".panel-subview-body");
-    let height = getFullHeight(body || aSubview);
-    if (body) {
-      let header = aSubview.querySelector(".panel-subview-header");
-      let footer = aSubview.querySelector(".panel-subview-footer");
-      height += (header ? getFullHeight(header) : 0) +
-                (footer ? getFullHeight(footer) : 0);
-    }
-    if (aContainerToCheck) {
-      let containerCS = win.getComputedStyle(aContainerToCheck);
-      height += parseFloat(containerCS.paddingTop) + parseFloat(containerCS.paddingBottom);
-    }
-    return Math.ceil(height);
-  }
 }
--- a/browser/components/customizableui/content/customizeMode.inc.xul
+++ b/browser/components/customizableui/content/customizeMode.inc.xul
@@ -1,37 +1,37 @@
 <!-- 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/. -->
 
-<hbox id="customization-container" flex="1" hidden="true">
-  <vbox flex="1" id="customization-palette-container">
+<box id="customization-container" flex="1" hidden="true">
+  <box flex="1" id="customization-palette-container">
     <label id="customization-header">
       &customizeMode.menuAndToolbars.header2;
     </label>
     <hbox id="customization-empty" hidden="true">
       <label>&customizeMode.menuAndToolbars.empty;</label>
       <label onclick="BrowserOpenAddonsMgr('addons://discover/');"
              onkeypress="BrowserOpenAddonsMgr('addons://discover/');"
              id="customization-more-tools"
              class="text-link">
         &customizeMode.menuAndToolbars.emptyLink;
       </label>
     </hbox>
     <vbox id="customization-palette" class="customization-palette"/>
     <spacer id="customization-spacer"/>
     <hbox id="customization-footer">
 #ifdef CAN_DRAW_IN_TITLEBAR
-      <button id="customization-titlebar-visibility-button" class="customizationmode-button"
-              label="&customizeMode.titlebar;" type="checkbox"
+      <checkbox id="customization-titlebar-visibility-checkbox" class="customizationmode-checkbox"
+                label="&customizeMode.titlebar;"
 #NB: because oncommand fires after click, by the time we've fired, the checkbox binding
 #    will already have switched the button's state, so this is correct:
-              oncommand="gCustomizeMode.toggleTitlebar(this.hasAttribute('checked'))"/>
+                oncommand="gCustomizeMode.toggleTitlebar(this.checked)"/>
 #endif
-      <button id="customization-toolbar-visibility-button" label="&customizeMode.toolbars;" class="customizationmode-button" type="menu">
+      <button id="customization-toolbar-visibility-button" label="&customizeMode.toolbars2;" class="customizationmode-button" type="menu">
         <menupopup id="customization-toolbar-menu" onpopupshowing="onViewToolbarsPopupShowing(event)"/>
       </button>
       <button id="customization-lwtheme-button" label="&customizeMode.lwthemes;" class="customizationmode-button" type="menu">
         <panel type="arrow" id="customization-lwtheme-menu"
                onpopupshowing="gCustomizeMode.onLWThemesMenuShowing(event);"
                position="topcenter bottomleft"
                flip="none"
                role="menu">
@@ -57,26 +57,32 @@
               class="customizationmode-button"
               hidden="true"
               oncommand="gCustomizeMode.undoReset();"
               label="&undoCmd.label;"/>
       <button id="customization-reset-button"
               oncommand="gCustomizeMode.reset();"
               label="&customizeMode.restoreDefaults;"
               class="customizationmode-button"/>
+      <button id="customization-done-button"
+              hidden="true"
+              oncommand="gCustomizeMode.exit();"
+              label="&customizeMode.done;"
+              class="customizationmode-button"/>
     </hbox>
-  </vbox>
+  </box>
+  <box id="customization-content-container"/>
   <vbox id="customization-panel-container">
     <vbox id="customization-panelWrapper">
       <html:style html:type="text/html" scoped="scoped">
         @import url(chrome://global/skin/popup.css);
       </html:style>
       <box class="panel-arrowbox">
         <box flex="1"/>
         <image class="panel-arrow" side="top"/>
       </box>
       <box class="panel-arrowcontent" side="top" flex="1">
         <hbox id="customization-panelHolder"/>
         <box class="panel-inner-arrowcontentfooter" hidden="true"/>
       </box>
     </vbox>
   </vbox>
-</hbox>
+</box>
--- a/browser/components/customizableui/content/panelUI.css
+++ b/browser/components/customizableui/content/panelUI.css
@@ -1,30 +1,31 @@
 /* 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/. */
 
 .panel-viewstack[viewtype="main"] > .panel-clickcapturer {
   pointer-events: none;
 }
 
-.panel-mainview,
-.panel-viewcontainer,
-.panel-viewstack {
+.panel-viewcontainer {
   overflow: hidden;
 }
 
 .panel-viewstack {
-  position: relative;
+  transition: height var(--panelui-subview-transition-duration);
 }
 
 .panel-subviews {
-  -moz-stack-sizing: ignore;
+  -moz-stack-sizing: ignore-horizontal;
   transform: translateX(0);
-  overflow-y: auto;
+}
+
+.panel-viewstack[viewtype="main"] > .panel-subviews {
+  -moz-stack-sizing: ignore;
 }
 
 .panel-subviews[panelopen] {
   transition: transform var(--panelui-subview-transition-duration);
 }
 
 .panel-viewcontainer[panelopen]:-moz-any(:not([viewtype="main"]),[transitioning]) {
   transition-property: height;
--- a/browser/components/customizableui/content/panelUI.inc.xul
+++ b/browser/components/customizableui/content/panelUI.inc.xul
@@ -15,17 +15,17 @@
         <vbox id="PanelUI-contents" class="panelUI-grid"/>
       </vbox>
 
       <footer id="PanelUI-footer">
         <vbox id="PanelUI-footer-addons"></vbox>
         <toolbarbutton class="panel-banner-item"
                        label-update-available="&updateAvailable.panelUI.label;"
                        label-update-manual="&updateManual.panelUI.label;"
-                       label-update-restart="&updateRestart.panelUI.label;"
+                       label-update-restart="&updateRestart.panelUI.label2;"
                        oncommand="PanelUI._onBannerItemSelected(event)"
                        wrap="true"
                        hidden="true"/>
         <hbox id="PanelUI-fxa-container">
           <hbox id="PanelUI-fxa-status"
                 label="&fxaSignedIn.tooltip;"
                 defaultlabel="&fxaSignIn.label;"
                 signedinTooltiptext="&fxaSignedIn.tooltip;"
@@ -499,17 +499,17 @@
        noautofocus="true">
   <photonpanelmultiview id="appMenu-multiView" mainViewId="appMenu-mainView">
     <panelview id="appMenu-mainView" class="PanelUI-subView">
       <vbox class="panel-subview-body">
         <vbox id="appMenu-addon-banners"/>
         <toolbarbutton class="panel-banner-item"
                        label-update-available="&updateAvailable.panelUI.label;"
                        label-update-manual="&updateManual.panelUI.label;"
-                       label-update-restart="&updateRestart.panelUI.label;"
+                       label-update-restart="&updateRestart.panelUI.label2;"
                        oncommand="PanelUI._onBannerItemSelected(event)"
                        wrap="true"
                        hidden="true"/>
         <toolbaritem id="appMenu-fxa-container">
           <hbox id="appMenu-fxa-status"
                 flex="1"
                 defaultlabel="&fxaSignIn.label;"
                 signedinTooltiptext="&fxaSignedIn.tooltip;"
--- a/browser/components/customizableui/content/panelUI.xml
+++ b/browser/components/customizableui/content/panelUI.xml
@@ -13,17 +13,17 @@
           xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
           xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="panelmultiview">
     <resources>
       <stylesheet src="chrome://browser/content/customizableui/panelUI.css"/>
     </resources>
     <content>
-      <xul:box anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen,viewtype,transitioning">
+      <xul:vbox anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen,viewtype,transitioning">
         <xul:stack anonid="viewStack" xbl:inherits="viewtype,transitioning" class="panel-viewstack">
           <xul:vbox anonid="mainViewContainer" class="panel-mainview" xbl:inherits="viewtype"/>
 
           <!-- Used to capture click events over the PanelUI-mainView if we're in
                subview mode. That way, any click on the PanelUI-mainView causes us
                to revert to the mainView mode, whereupon PanelUI-click-capture then
                allows click events to go through it. -->
           <xul:vbox anonid="clickCapturer" class="panel-clickcapturer"/>
@@ -32,28 +32,28 @@
                subviews that are not being displayed. We're using this over a deck
                because a deck assumes the size of its largest child, regardless of
                whether or not it is shown. That's not good for our case, since we
                want to allow each subview to be uniquely sized. -->
           <xul:vbox anonid="subViews" class="panel-subviews" xbl:inherits="panelopen">
             <children includes="panelview"/>
           </xul:vbox>
         </xul:stack>
-      </xul:box>
+      </xul:vbox>
     </content>
     <implementation>
       <constructor><![CDATA[
         const {PanelMultiView} = Components.utils.import("resource:///modules/PanelMultiView.jsm", {});
         this.instance = new PanelMultiView(this);
-       ]]></constructor>
- 
-       <destructor><![CDATA[
+      ]]></constructor>
+
+      <destructor><![CDATA[
         this.instance.destructor();
-       ]]></destructor>
-     </implementation>
+      ]]></destructor>
+    </implementation>
   </binding>
 
   <binding id="photonpanelmultiview" extends="chrome://browser/content/customizableui/panelUI.xml#panelmultiview">
     <content>
       <xul:box anonid="viewContainer" class="panel-viewcontainer" xbl:inherits="panelopen,transitioning">
         <xul:stack anonid="viewStack" xbl:inherits="transitioning" class="panel-viewstack">
           <children includes="panelview"/>
         </xul:stack>
--- a/browser/components/customizableui/test/browser_970511_undo_restore_default.js
+++ b/browser/components/customizableui/test/browser_970511_undo_restore_default.js
@@ -85,40 +85,40 @@ add_task(async function() {
 add_task(async function() {
   if (Services.appinfo.OS != "WINNT" &&
       Services.appinfo.OS != "Darwin") {
     return;
   }
   let prefName = "browser.tabs.drawInTitlebar";
   let defaultValue = Services.prefs.getBoolPref(prefName);
   let restoreDefaultsButton = document.getElementById("customization-reset-button");
-  let titleBarButton = document.getElementById("customization-titlebar-visibility-button");
+  let titlebarCheckbox = document.getElementById("customization-titlebar-visibility-checkbox");
   let undoResetButton = document.getElementById("customization-undo-reset-button");
   ok(CustomizableUI.inDefaultState, "Should be in default state at start of test");
   ok(restoreDefaultsButton.disabled, "Restore defaults button should be disabled when in default state");
-  is(titleBarButton.hasAttribute("checked"), !defaultValue, "Title bar button should reflect pref value");
+  is(titlebarCheckbox.hasAttribute("checked"), !defaultValue, "Title bar checkbox should reflect pref value");
   is(undoResetButton.hidden, true, "Undo reset button should be hidden at start of test");
 
   Services.prefs.setBoolPref(prefName, !defaultValue);
   ok(!restoreDefaultsButton.disabled, "Restore defaults button should be enabled when pref changed");
-  is(titleBarButton.hasAttribute("checked"), defaultValue, "Title bar button should reflect changed pref value");
+  is(titlebarCheckbox.hasAttribute("checked"), defaultValue, "Title bar checkbox should reflect changed pref value");
   ok(!CustomizableUI.inDefaultState, "With titlebar flipped, no longer default");
   is(undoResetButton.hidden, true, "Undo reset button should be hidden after pref change");
 
   await gCustomizeMode.reset();
   ok(restoreDefaultsButton.disabled, "Restore defaults button should be disabled after reset");
-  is(titleBarButton.hasAttribute("checked"), !defaultValue, "Title bar button should reflect default value after reset");
+  is(titlebarCheckbox.hasAttribute("checked"), !defaultValue, "Title bar checkbox should reflect default value after reset");
   is(Services.prefs.getBoolPref(prefName), defaultValue, "Reset should reset drawInTitlebar");
   ok(CustomizableUI.inDefaultState, "In default state after titlebar reset");
   is(undoResetButton.hidden, false, "Undo reset button should be visible after reset");
   ok(!undoResetButton.disabled, "Undo reset button should be enabled after reset");
 
   await gCustomizeMode.undoReset();
   ok(!restoreDefaultsButton.disabled, "Restore defaults button should be enabled after undo-reset");
-  is(titleBarButton.hasAttribute("checked"), defaultValue, "Title bar button should reflect undo-reset value");
+  is(titlebarCheckbox.hasAttribute("checked"), defaultValue, "Title bar checkbox should reflect undo-reset value");
   ok(!CustomizableUI.inDefaultState, "No longer in default state after undo");
   is(Services.prefs.getBoolPref(prefName), !defaultValue, "Undo-reset goes back to previous pref value");
   is(undoResetButton.hidden, true, "Undo reset button should be hidden after undo-reset clicked");
 
   Services.prefs.clearUserPref(prefName);
   ok(CustomizableUI.inDefaultState, "In default state after pref cleared");
   is(undoResetButton.hidden, true, "Undo reset button should be hidden at end of test");
 });
--- a/browser/components/downloads/content/downloads.js
+++ b/browser/components/downloads/content/downloads.js
@@ -298,30 +298,16 @@ const DownloadsPanel = {
         this.keyFocusing = false;
         break;
       case "keydown":
         this._onKeyDown(aEvent);
         break;
       case "keypress":
         this._onKeyPress(aEvent);
         break;
-      case "popupshown":
-        if (this.setHeightToFitOnShow) {
-          this.setHeightToFitOnShow = false;
-          this.setHeightToFit();
-        }
-        break;
-    }
-  },
-
-  setHeightToFit() {
-    if (this._state == this.kStateShown) {
-      DownloadsBlockedSubview.view.setHeightToFit();
-    } else {
-      this.setHeightToFitOnShow = true;
     }
   },
 
   // Callback functions from DownloadsView
 
   /**
    * Called after data loading finished.
    */
@@ -401,28 +387,25 @@ const DownloadsPanel = {
    * panel has successfully loaded.
    */
   _attachEventListeners() {
     // Handle keydown to support accel-V.
     this.panel.addEventListener("keydown", this);
     // Handle keypress to be able to preventDefault() events before they reach
     // the richlistbox, for keyboard navigation.
     this.panel.addEventListener("keypress", this);
-    // Handle height adjustment on show.
-    this.panel.addEventListener("popupshown", this);
   },
 
   /**
    * Unattach event listeners that were added in _attachEventListeners. This
    * is called automatically on panel termination.
    */
   _unattachEventListeners() {
     this.panel.removeEventListener("keydown", this);
     this.panel.removeEventListener("keypress", this);
-    this.panel.removeEventListener("popupshown", this);
   },
 
   _onKeyPress(aEvent) {
     // Handle unmodified keys only.
     if (aEvent.altKey || aEvent.ctrlKey || aEvent.shiftKey || aEvent.metaKey) {
       return;
     }
 
@@ -853,19 +836,16 @@ const DownloadsView = {
       this._removeViewItem(download);
       if (this._downloads.length >= this.kItemCountLimit) {
         // Reinsert the next item into the panel.
         this._addViewItem(this._downloads[this.kItemCountLimit - 1], false);
       }
     }
 
     this._itemCountChanged();
-
-    // Adjust the panel height if we removed items.
-    DownloadsPanel.setHeightToFit();
   },
 
   /**
    * Associates each richlistitem for a download with its corresponding
    * DownloadsViewItem object.
    */
   _itemsForElements: new Map(),
 
@@ -1540,20 +1520,16 @@ const DownloadsFooter = {
    */
   set showingSummary(aValue) {
     if (this._footerNode) {
       if (aValue) {
         this._footerNode.setAttribute("showingsummary", "true");
       } else {
         this._footerNode.removeAttribute("showingsummary");
       }
-      if (!aValue && this._showingSummary) {
-        // Make sure the panel's height shrinks when the summary is hidden.
-        DownloadsPanel.setHeightToFit();
-      }
       this._showingSummary = aValue;
     }
     return aValue;
   },
 
   /**
    * Element corresponding to the footer of the downloads panel.
    */
--- a/browser/components/downloads/content/downloadsOverlay.xul
+++ b/browser/components/downloads/content/downloadsOverlay.xul
@@ -103,32 +103,30 @@
                   accesskey="&cmd.removeFromHistory.accesskey;"/>
         <menuitem command="downloadsCmd_clearList"
                   label="&cmd.clearList2.label;"
                   accesskey="&cmd.clearList2.accesskey;"/>
       </menupopup>
 
       <panelmultiview id="downloadsPanel-multiView"
                       mainViewId="downloadsPanel-mainView"
-                      align="stretch">
+                      descriptionheightworkaround="true">
 
-        <panelview id="downloadsPanel-mainView"
-                   flex="1"
-                   align="stretch">
-          <richlistbox id="downloadsListBox"
-                       context="downloadsContextMenu"
-                       onmouseover="DownloadsView.onDownloadMouseOver(event);"
-                       onmouseout="DownloadsView.onDownloadMouseOut(event);"
-                       oncontextmenu="DownloadsView.onDownloadContextMenu(event);"
-                       ondragstart="DownloadsView.onDownloadDragStart(event);"/>
-          <description id="emptyDownloads"
-                       mousethrough="always">
-             &downloadsPanelEmpty.label;
-          </description>
-          <spacer flex="1"/>
+        <panelview id="downloadsPanel-mainView">
+          <vbox class="panel-view-body-unscrollable">
+            <richlistbox id="downloadsListBox"
+                         context="downloadsContextMenu"
+                         onmouseover="DownloadsView.onDownloadMouseOver(event);"
+                         onmouseout="DownloadsView.onDownloadMouseOut(event);"
+                         oncontextmenu="DownloadsView.onDownloadContextMenu(event);"
+                         ondragstart="DownloadsView.onDownloadDragStart(event);"/>
+            <description id="emptyDownloads"
+                         mousethrough="always"
+                         value="&downloadsPanelEmpty.label;"/>
+          </vbox>
           <vbox id="downloadsFooter"
                 class="downloadsPanelFooter">
             <stack>
               <hbox id="downloadsSummary"
                     align="center"
                     orient="horizontal"
                     onkeydown="DownloadsSummary.onKeyDown(event);"
                     onclick="DownloadsSummary.onClick(event);">
@@ -154,23 +152,22 @@
                         accesskey="&downloadsHistory.accesskey;"
                         flex="1"
                         oncommand="DownloadsPanel.showDownloadsHistory();"/>
               </hbox>
             </stack>
           </vbox>
         </panelview>
 
-        <panelview id="downloadsPanel-blockedSubview"
-                   orient="vertical"
-                   flex="1">
-          <description id="downloadsPanel-blockedSubview-title"/>
-          <description id="downloadsPanel-blockedSubview-details1"/>
-          <description id="downloadsPanel-blockedSubview-details2"/>
-          <spacer flex="1"/>
+        <panelview id="downloadsPanel-blockedSubview">
+          <vbox class="panel-view-body-unscrollable">
+            <description id="downloadsPanel-blockedSubview-title"/>
+            <description id="downloadsPanel-blockedSubview-details1"/>
+            <description id="downloadsPanel-blockedSubview-details2"/>
+          </vbox>
           <hbox id="downloadsPanel-blockedSubview-buttons"
                 class="downloadsPanelFooter"
                 align="stretch">
             <button id="downloadsPanel-blockedSubview-openButton"
                     class="downloadsPanelFooterButton"
                     command="downloadsCmd_unblockAndOpen"
                     flex="1"/>
             <toolbarseparator/>
--- a/browser/components/extensions/ext-bookmarks.js
+++ b/browser/components/extensions/ext-bookmarks.js
@@ -21,18 +21,20 @@ function getTree(rootGuid, onlyChildren)
     }
 
     if (node.type == PlacesUtils.TYPE_X_MOZ_PLACE) {
       // This isn't quite correct. Recently Bookmarked ends up here ...
       treenode.url = node.uri;
     } else {
       treenode.dateGroupModified = node.lastModified / 1000;
 
-      if (node.children && !onlyChildren) {
-        treenode.children = node.children.map(child => convert(child, node));
+      if (!onlyChildren) {
+        treenode.children = node.children
+          ? node.children.map(child => convert(child, node))
+          : [];
       }
     }
 
     return treenode;
   }
 
   return PlacesUtils.promiseBookmarksTree(rootGuid, {
     excludeItemsCallback: item => {
--- a/browser/components/extensions/test/browser/browser_ext_identity_indication.js
+++ b/browser/components/extensions/test/browser/browser_ext_identity_indication.js
@@ -1,29 +1,29 @@
 /* -*- Mode: indent-tabs-mode: nil; js-indent-level: 2 -*- */
 /* vim: set sts=2 sw=2 et tw=80: */
 "use strict";
 
 function confirmDefaults() {
   let identityIconURL = getComputedStyle(document.getElementById("identity-icon")).listStyleImage;
-  is(identityIconURL, "url(\"chrome://browser/skin/identity-icon.svg#normal\")", "Identity icon should be the default identity icon");
+  is(identityIconURL, "url(\"chrome://browser/skin/identity-icon.svg\")", "Identity icon should be the default identity icon");
 
   let connectionIconURL = getComputedStyle(document.getElementById("connection-icon")).listStyleImage;
   is(connectionIconURL, "none", "Connection icon should not be displayed");
 
   let extensionIconURL = getComputedStyle(document.getElementById("extension-icon")).listStyleImage;
   is(extensionIconURL, "none", "Extension icon should not be displayed");
 
   let label = document.getElementById("identity-icon-label").value;
   is(label, "", "No label should be used before the extension is started");
 }
 
 function confirmExtensionPage() {
   let identityIcon = getComputedStyle(document.getElementById("identity-icon")).listStyleImage;
-  is(identityIcon, "url(\"chrome://browser/skin/identity-icon.svg#normal\")", "Identity icon  should be the default identity icon");
+  is(identityIcon, "url(\"chrome://browser/skin/identity-icon.svg\")", "Identity icon  should be the default identity icon");
 
   let connectionIconURL = getComputedStyle(document.getElementById("connection-icon")).listStyleImage;
   is(connectionIconURL, "none", "Connection icon should not be displayed");
 
   let extensionIconEl = document.getElementById("extension-icon");
   let extensionIconURL = getComputedStyle(extensionIconEl).listStyleImage;
   is(extensionIconURL, "url(\"chrome://browser/skin/controlcenter/extension.svg\")", "Extension icon should be the default extension icon");
   let tooltip = extensionIconEl.tooltipText;
--- a/browser/components/extensions/test/xpcshell/test_ext_bookmarks.js
+++ b/browser/components/extensions/test/xpcshell/test_ext_bookmarks.js
@@ -652,8 +652,50 @@ add_task(async function test_get_recent_
     let expected = createdBookmarks[i];
     equal(actual.url, expected.url, "Bookmark has the expected url.");
     equal(actual.title, expected.title, "Bookmark has the expected title.");
     equal(actual.parentId, expected.parentGuid, "Bookmark has the expected parentId.");
   }
 
   await extension.unload();
 });
+
+add_task(async function test_tree_with_empty_folder() {
+  async function background() {
+    await browser.bookmarks.create({title: "Empty Folder"});
+    let nonEmptyFolder = await browser.bookmarks.create({title: "Non-Empty Folder"});
+    await browser.bookmarks.create({title: "A bookmark", url: "http://example.com", parentId: nonEmptyFolder.id});
+
+    let tree = await browser.bookmarks.getSubTree(nonEmptyFolder.parentId);
+    browser.test.assertEq(0,
+      tree[0].children[0].children.length,
+      "The empty folder returns an empty array for children.");
+    browser.test.assertEq(1,
+      tree[0].children[1].children.length,
+      "The non-empty folder returns a single item array for children.");
+
+    let children = await browser.bookmarks.getChildren(nonEmptyFolder.parentId);
+    // getChildren should only return immediate children. This is not tested in the
+    // monster test above.
+    for (let child of children) {
+      browser.test.assertEq(undefined,
+        child.children,
+        "Child from getChildren does not contain any children.");
+    }
+
+    browser.test.sendMessage("done");
+  }
+
+  let extension = ExtensionTestUtils.loadExtension({
+    background,
+    manifest: {
+      permissions: ["bookmarks"],
+    },
+  });
+
+  // Start with an empty bookmarks database.
+  await PlacesUtils.bookmarks.eraseEverything();
+
+  await extension.startup();
+  await extension.awaitMessage("done");
+
+  await extension.unload();
+});
--- a/browser/components/preferences/in-content-old/search.js
+++ b/browser/components/preferences/in-content-old/search.js
@@ -261,18 +261,20 @@ var gSearchPane = {
       let eduplicate = false;
       let dupName = "";
 
       // Check for duplicates in Places keywords.
       let bduplicate = !!(await PlacesUtils.keywords.fetch(keyword));
 
       // Check for duplicates in changes we haven't committed yet
       let engines = gEngineView._engineStore.engines;
+      let lc_keyword = keyword.toLocaleLowerCase();
       for (let engine of engines) {
-        if (engine.alias == keyword &&
+        if (engine.alias &&
+            engine.alias.toLocaleLowerCase() == lc_keyword &&
             engine.name != aEngine.name) {
           eduplicate = true;
           dupName = engine.name;
           break;
         }
       }
 
       // Notify the user if they have chosen an existing engine/bookmark keyword
--- a/browser/components/preferences/in-content/main.js
+++ b/browser/components/preferences/in-content/main.js
@@ -1040,18 +1040,20 @@ var gMainPane = {
       let eduplicate = false;
       let dupName = "";
 
       // Check for duplicates in Places keywords.
       let bduplicate = !!(await PlacesUtils.keywords.fetch(keyword));
 
       // Check for duplicates in changes we haven't committed yet
       let engines = gEngineView._engineStore.engines;
+      let lc_keyword = keyword.toLocaleLowerCase();
       for (let engine of engines) {
-        if (engine.alias == keyword &&
+        if (engine.alias &&
+            engine.alias.toLocaleLowerCase() == lc_keyword &&
             engine.name != aEngine.name) {
           eduplicate = true;
           dupName = engine.name;
           break;
         }
       }
 
       // Notify the user if they have chosen an existing engine/bookmark keyword
--- a/browser/components/preferences/in-content/main.xul
+++ b/browser/components/preferences/in-content/main.xul
@@ -557,37 +557,37 @@
 </groupbox>
 
 <!-- Performance -->
 <groupbox id="performanceGroup" data-category="paneGeneral" hidden="true">
   <caption><label>&performance.label;</label></caption>
 
   <hbox align="center">
     <checkbox id="useRecommendedPerformanceSettings"
-              label="&useRecommendedPerformanceSettings.label;"
-              accesskey="&useRecommendedPerformanceSettings.accesskey;"
+              label="&useRecommendedPerformanceSettings2.label;"
+              accesskey="&useRecommendedPerformanceSettings2.accesskey;"
               preference="browser.preferences.defaultPerformanceSettings.enabled"/>
     <label id="performanceSettingsLearnMore" class="learnMore text-link">&performanceSettingsLearnMore.label;</label>
   </hbox>
-  <description class="indent">&useRecommendedPerformanceSettings.description;</description>
+  <description class="indent">&useRecommendedPerformanceSettings2.description;</description>
 
   <vbox id="performanceSettings" class="indent" hidden="true">
     <checkbox id="allowHWAccel"
               label="&allowHWAccel.label;"
               accesskey="&allowHWAccel.accesskey;"
               preference="layers.acceleration.disabled"/>
     <hbox align="center">
-      <label id="limitContentProcess" accesskey="&limitContentProcess.accesskey;" control="contentProcessCount">&limitContentProcess.label;</label>
+      <label id="limitContentProcess" accesskey="&limitContentProcess2.accesskey;" control="contentProcessCount">&limitContentProcess2.label;</label>
       <menulist id="contentProcessCount" preference="dom.ipc.processCount">
         <menupopup>
           <menuitem label="1" value="1"/>
           <menuitem label="2" value="2"/>
           <menuitem label="3" value="3"/>
           <menuitem label="4" value="4"/>
           <menuitem label="5" value="5"/>
           <menuitem label="6" value="6"/>
           <menuitem label="7" value="7"/>
         </menupopup>
       </menulist>
     </hbox>
-    <description>&limitContentProcess.description;</description>
+    <description>&limitContentProcess2.description;</description>
   </vbox>
 </groupbox>
--- a/browser/components/preferences/in-content/tests/browser.ini
+++ b/browser/components/preferences/in-content/tests/browser.ini
@@ -13,16 +13,17 @@ skip-if = !updater
 [browser_bug410900.js]
 [browser_bug705422.js]
 [browser_bug731866.js]
 [browser_search_within_preferences.js]
 [browser_bug795764_cachedisabled.js]
 [browser_bug1018066_resetScrollPosition.js]
 [browser_bug1020245_openPreferences_to_paneContent.js]
 [browser_bug1184989_prevent_scrolling_when_preferences_flipped.js]
+[browser_engines.js]
 support-files =
   browser_bug1184989_prevent_scrolling_when_preferences_flipped.xul
 [browser_change_app_handler.js]
 skip-if = os != "win" # This test tests the windows-specific app selection dialog, so can't run on non-Windows
 [browser_checkspelling.js]
 [browser_connection.js]
 [browser_connection_bug388287.js]
 [browser_cookies_exceptions.js]
new file mode 100644
--- /dev/null
+++ b/browser/components/preferences/in-content/tests/browser_engines.js
@@ -0,0 +1,26 @@
+// Test Engine list
+add_task(async function() {
+  let prefs = await openPreferencesViaOpenPreferencesAPI("general-search", {leaveOpen: true});
+  is(prefs.selectedPane, "paneGeneral", "General pane is selected by default");
+  let doc = gBrowser.contentDocument;
+
+  let tree = doc.querySelector("#engineList");
+  ok(!tree.hidden, "The search engine list should be visible when Search is requested");
+
+  // Check for default search engines to be displayed in the engineList
+  let defaultEngines = Services.search.getDefaultEngines();
+  for (let i = 0; i < defaultEngines.length; i++) {
+      let engine = defaultEngines[i];
+      let cellName = tree.view.getCellText(i, tree.columns.getNamedColumn("engineName"));
+      is(cellName, engine.name, "Default search engine " + engine.name + " displayed correctly");
+  }
+
+  // Avoid duplicated keywords
+  tree.view.setCellText(0, tree.columns.getNamedColumn("engineKeyword"), "keyword");
+  tree.view.setCellText(1, tree.columns.getNamedColumn("engineKeyword"), "keyword");
+  let cellKeyword = tree.view.getCellText(1, tree.columns.getNamedColumn("engineKeyword"));
+  isnot(cellKeyword, "keyword", "Do not allow duplicated keywords");
+
+  await BrowserTestUtils.removeTab(gBrowser.selectedTab);
+});
+
--- a/browser/components/uitour/UITour-lib.js
+++ b/browser/components/uitour/UITour-lib.js
@@ -356,17 +356,16 @@ if (typeof Mozilla == "undefined") {
    *   "name":         "My cool theme",
    *   "author":       "Mozilla",
    *   "footer":       "https://addons.mozilla.org/_files/….jpg",
    *   "previewURL":   "https://addons.mozilla.org/_files/…/preview.jpg",
    *   "updateURL":    "https://versioncheck.addons.mozilla.org/…",
    *   "accentcolor":  "#000000",
    *   "header":       "https://addons.mozilla.org/_files/….jpg",
    *   "version":      "1.0",
-   *   "footerURL":    "https://addons.mozilla.org/_files/….jpg",
    *   "detailURL":    "https://addons.mozilla.org/firefox/addon/…",
    *   "textcolor":    "#ffffff",
    *   "id":           "18066",
    *   "description":  "My awesome theme.",
    *   …
    * };
    *
    * Mozilla.UITour.previewTheme(theme);
--- a/browser/extensions/mortar/host/common/ppapi-runtime.jsm
+++ b/browser/extensions/mortar/host/common/ppapi-runtime.jsm
@@ -1813,17 +1813,18 @@ class PPAPIInstance {
       case 'save':
         this.mm.sendAsyncMessage("ppapipdf.js:save");
         break;
       case 'setHash':
         this.mm.sendAsyncMessage("ppapipdf.js:setHash", message.hash);
         break;
       case 'startPrint':
         // We need permission for showing print dialog to get print settings
-        this.mm.sendAsyncMessage("ppapipdf.js:getPrintSettings");
+        this.mm.sendAsyncMessage("ppapipdf.js:getPrintSettings", {
+          url: this.info.url });
         break;
       case 'openLink':
         this.mm.sendAsyncMessage("ppapipdf.js:openLink", {
           url: message.url,
           disposition: message.disposition
         });
         break;
       case 'viewport':
--- a/browser/extensions/mortar/host/pdf/ppapi-content-sandbox.js
+++ b/browser/extensions/mortar/host/pdf/ppapi-content-sandbox.js
@@ -39,16 +39,29 @@ if (isSynthetic) {
   pluginElement.ownerDocument.body.addEventListener(
     "selectstart", function(event) { event.preventDefault(); });
 }
 
 function mapValue(v, instance) {
   return instance.rt.toPP_Var(v, instance);
 }
 
+function getFileName(url) {
+  let filename = "document.pdf";
+  let regex = /[^\/#\?]+\.pdf$/i;
+
+  let result = regex.exec(url.hash) ||
+               regex.exec(url.search) ||
+               regex.exec(url.pathname);
+  if (result) {
+    filename = result[0];
+  }
+  return filename;
+}
+
 dump("<>>>>>>>>>>>>>>>>>>>> AHA <<<<<<<<<<<<<<<<<<<<<>\n");
 dump(`pluginElement: ${pluginElement.toSource()}\n`);
 dump(`pluginElement.frameLoader: ${pluginElement.frameLoader.toSource()}\n`);
 dump(`pluginElement.frameLoader.messageManager: ${pluginElement.frameLoader.messageManager.toSource()}\n`);
 dump("<>>>>>>>>>>>>>>>>>>>> AHA2 <<<<<<<<<<<<<<<<<<<<<>\n");
 
 mm.addMessageListener("ppapi.js:frameLoaded", ({ target }) => {
   let tagName = pluginElement.nodeName;
@@ -111,17 +124,21 @@ mm.addMessageListener("ppapi.js:setFulls
 });
 
 mm.addMessageListener("ppapipdf.js:setHash", ({ data }) => {
   if (data) {
     containerWindow.location.hash = data;
   }
 });
 
-mm.addMessageListener("ppapipdf.js:getPrintSettings", () => {
+mm.addMessageListener("ppapipdf.js:getPrintSettings", ({ data }) => {
+  // Set the title to pdf file name for the default print to file name.
+  let url = new containerWindow.URL(data.url);
+  containerWindow.document.title = getFileName(url);
+
   let PSSVC = Cc["@mozilla.org/gfx/printsettings-service;1"].
               getService(Ci.nsIPrintSettingsService);
   printSettings = PSSVC.globalPrintSettings;
   let webBrowserPrint =
     containerWindow.QueryInterface(Ci.nsIInterfaceRequestor).
     getInterface(Ci.nsIWebBrowserPrint);
   let PPSVC = Cc["@mozilla.org/embedcomp/printingprompt-service;1"].
               getService(Ci.nsIPrintingPromptService);
@@ -202,26 +219,17 @@ mm.addMessageListener("ppapipdf.js:openL
         "noopener=1,menubar=1,toolbar=1," +
         "location=1,personalbar=1,status=1,resizable");
       break;
   }
 });
 
 mm.addMessageListener("ppapipdf.js:save", () => {
   let url = containerWindow.document.location;
-  let filename = "document.pdf";
-  let regex = /[^\/#\?]+\.pdf$/i;
-
-  let result = regex.exec(url.hash) ||
-               regex.exec(url.search) ||
-               regex.exec(url.pathname);
-  if (result) {
-    filename = result[0];
-  }
-
+  let filename = getFileName(url);
   let originalUri = NetUtil.newURI(url.href);
   let extHelperAppSvc =
         Cc["@mozilla.org/uriloader/external-helper-app-service;1"].
            getService(Ci.nsIExternalHelperAppService);
 
   let docIsPrivate =
     PrivateBrowsingUtils.isContentWindowPrivate(containerWindow);
   let netChannel = NetUtil.newChannel({
--- a/browser/extensions/pocket/jar.mn
+++ b/browser/extensions/pocket/jar.mn
@@ -4,17 +4,28 @@
 
 [features/firefox@getpocket.com] chrome.jar:
 % content pocket %content/ contentaccessible=yes
 % skin pocket classic/1.0 %skin/linux/
 % skin pocket classic/1.0 %skin/osx/ os=Darwin
 % skin pocket classic/1.0 %skin/windows/ os=WINNT
 % skin pocket-shared classic/1.0 %skin/shared/
   content/  (content/*)
-  skin/  (skin/*)
+  skin/shared (skin/shared/*)
+#ifdef XP_WIN
+  skin/windows/ (skin/windows/*.png)
+* skin/windows/pocket.css (skin/windows/pocket.css)
+#elifdef XP_MACOSX
+  skin/osx/ (skin/osx/*.png)
+* skin/osx/pocket.css (skin/osx/pocket.css)
+#else
+  skin/linux/ (skin/linux/*.png)
+* skin/linux/pocket.css (skin/linux/pocket.css)
+#endif
+
 # windows overrides
 % override chrome://pocket/skin/menuPanel.png             chrome://pocket/skin/menuPanel-aero.png            os=WINNT osversion=6
 % override chrome://pocket/skin/menuPanel.png             chrome://pocket/skin/menuPanel-aero.png            os=WINNT osversion=6.1
 % override chrome://pocket/skin/menuPanel@2x.png          chrome://pocket/skin/menuPanel-aero@2x.png         os=WINNT osversion=6
 % override chrome://pocket/skin/menuPanel@2x.png          chrome://pocket/skin/menuPanel-aero@2x.png         os=WINNT osversion=6.1
 % override chrome://pocket/skin/menuPanel.png             chrome://pocket/skin/menuPanel-yosemite.png        os=Darwin osversion>=10.10
 % override chrome://pocket/skin/menuPanel@2x.png          chrome://pocket/skin/menuPanel-yosemite@2x.png     os=Darwin osversion>=10.10
 
--- a/browser/extensions/pocket/skin/linux/pocket.css
+++ b/browser/extensions/pocket/skin/linux/pocket.css
@@ -1,10 +1,14 @@
 @import url("chrome://pocket-shared/skin/pocket.css");
 
 #nav-bar #pocket-button > .toolbarbutton-icon {
+%ifndef MOZ_PHOTON_THEME
   padding: 2px 6px;
+%else
+  padding: calc(var(--toolbarbutton-inner-padding) - 1px);
+%endif
 }
 
 :-moz-any(#TabsToolbar, .widget-overflow-list) #pocket-button > .toolbarbutton-icon {
     max-width: 18px;
     padding: 0;
-}
\ No newline at end of file
+}
--- a/browser/extensions/pocket/skin/osx/pocket.css
+++ b/browser/extensions/pocket/skin/osx/pocket.css
@@ -1,9 +1,13 @@
 @import url("chrome://pocket-shared/skin/pocket.css");
 
 #nav-bar #pocket-button > .toolbarbutton-icon {
-  padding: calc(var(--toolbarbutton-inner-padding)) 6px;
+%ifndef MOZ_PHOTON_THEME
+  padding: var(--toolbarbutton-inner-padding) 6px;
+%else
+  padding: calc(var(--toolbarbutton-inner-padding) - 1px);
+%endif
 }
 
 #PanelUI-pocketView[mainview=true] > .panel-subview-body > #pocket-panel-iframe {
   border-radius: var(--arrowpanel-border-radius);
 }
--- a/browser/extensions/pocket/skin/windows/pocket.css
+++ b/browser/extensions/pocket/skin/windows/pocket.css
@@ -1,10 +1,14 @@
 @import url("chrome://pocket-shared/skin/pocket.css");
 
 #nav-bar #pocket-button > .toolbarbutton-icon {
-  padding: calc(var(--toolbarbutton-inner-padding)) 6px;
+%ifndef MOZ_PHOTON_THEME
+  padding: var(--toolbarbutton-inner-padding) 6px;
+%else
+  padding: calc(var(--toolbarbutton-inner-padding) - 1px);
+%endif
 }
 
 :-moz-any(#TabsToolbar, .widget-overflow-list) #pocket-button > .toolbarbutton-icon {
     max-width: 18px;
     padding: 0;
 }
--- a/browser/installer/allowed-dupes.mn
+++ b/browser/installer/allowed-dupes.mn
@@ -69,17 +69,16 @@ browser/chrome/browser/skin/classic/brow
 browser/chrome/browser/skin/classic/browser/preferences/in-content/icons.svg
 browser/chrome/browser/skin/classic/browser/preferences/in-content/preferences.css
 browser/chrome/browser/skin/classic/browser/preferences/in-content/dialog.css
 # browser branding / themes is bug 1313106
 browser/chrome/browser/content/branding/icon128.png
 browser/chrome/browser/content/branding/icon16.png
 browser/chrome/browser/content/branding/icon32.png
 browser/chrome/browser/content/branding/icon48.png
-browser/chrome/browser/content/browser/defaultthemes/5.footer.png
 browser/chrome/browser/content/browser/defaultthemes/5.header.png
 browser/chrome/browser/content/browser/extension.svg
 browser/chrome/browser/content/browser/places/bookmarkProperties.xul
 browser/chrome/browser/content/browser/places/bookmarkProperties2.xul
 browser/chrome/browser/skin/classic/browser/addons/addon-install-confirm.svg
 browser/chrome/browser/skin/classic/browser/connection-secure.svg
 browser/chrome/browser/skin/classic/browser/controlcenter/warning-gray.svg
 browser/chrome/browser/skin/classic/browser/newtab/close.png
--- a/browser/installer/windows/nsis/stub.nsi
+++ b/browser/installer/windows/nsis/stub.nsi
@@ -176,16 +176,24 @@ Var PreviousInstallArch
 ; with a 100 millisecond timer and a first step of 20 as defined by
 ; InstallProgressFirstStep .
 !define /math InstallPaveOverTotalSteps ${InstallProgressFirstStep} + 1800
 
 ; Blurb duty cycle
 !define BlurbDisplayMS 19500
 !define BlurbBlankMS 500
 
+; Amount of physical memory required for the 64-bit build to be selected.
+; Machines with less RAM than this get the 32-bit build, even with a 64-bit OS.
+; The value 1800 MB was chosen based on an initial requirement of 2 GB, reduced
+; to allow for hardware such as integrated graphics that reserves some of the
+; installed RAM for its own use.
+; 1800 MB * 1024 KB/MB * 1024 B/KB = 1887436800 bytes
+!define RAM_NEEDED_FOR_64BIT 1887436800
+
 ; Attempt to elevate Standard Users in addition to users that
 ; are a member of the Administrators group.
 !define NONADMIN_ELEVATE
 
 !define CONFIG_INI "config.ini"
 
 !ifndef FILE_SHARE_READ
   !define FILE_SHARE_READ 1
@@ -307,19 +315,28 @@ Function .onInit
 
   ; SSE2 CPU support
   ${If} "$R7" == "0"
     MessageBox MB_OKCANCEL|MB_ICONSTOP "$(WARN_MIN_SUPPORTED_CPU_MSG)" IDCANCEL +2
     ExecShell "open" "${URLSystemRequirements}"
     Quit
   ${EndIf}
 
+  ; Check if we meet the RAM requirement for the 64-bit build.
+  System::Call "*(i 64, i, l 0, l, l, l, l, l, l)p.r0"
+  System::Call "Kernel32::GlobalMemoryStatusEx(p r0)"
+  System::Call "*$0(i, i, l.r1, l, l, l, l, l, l)"
+  System::Free $0
+
   ${If} ${RunningX64}
+  ${AndIf} $1 L>= ${RAM_NEEDED_FOR_64BIT}
+    StrCpy $DroplistArch "$(VERSION_64BIT)"
     StrCpy $INSTDIR "${DefaultInstDir64bit}"
   ${Else}
+    StrCpy $DroplistArch "$(VERSION_32BIT)"
     StrCpy $INSTDIR "${DefaultInstDir32bit}"
   ${EndIf}
 
   ; Require elevation if the user can elevate
   ${ElevateUAC}
 
   ; If we have any existing installation, use its location as the default
   ; path for this install, even if it's not the same architecture.
@@ -418,21 +435,16 @@ Function .onInit
   ${If} "$0" == "true"
     StrCpy $CheckboxInstallMaintSvc "1"
   ${Else}
     StrCpy $CheckboxInstallMaintSvc "0"
   ${EndIf}
 !else
   StrCpy $CheckboxInstallMaintSvc "0"
 !endif
-  ${If} ${RunningX64}
-    StrCpy $DroplistArch "$(VERSION_64BIT)"
-  ${Else}
-    StrCpy $DroplistArch "$(VERSION_32BIT)"
-  ${EndIf}
 
   StrCpy $0 ""
 !ifdef FONT_FILE1
   ${If} ${FileExists} "$FONTS\${FONT_FILE1}"
     StrCpy $0 "${FONT_NAME1}"
   ${EndIf}
 !endif
 
--- a/browser/locales/en-US/chrome/browser/browser.dtd
+++ b/browser/locales/en-US/chrome/browser/browser.dtd
@@ -824,18 +824,19 @@ you can use these alternative items. Oth
 <!ENTITY social.directory.button "Take me there!">
 <!ENTITY social.directory.introText "Click on a service to add it to &brandShortName;.">
 <!ENTITY social.directory.viewmore.text "View More">
 
 <!ENTITY customizeMode.menuAndToolbars.header2 "Additional Tools and Features">
 <!ENTITY customizeMode.menuAndToolbars.empty "Want more tools?">
 <!ENTITY customizeMode.menuAndToolbars.emptyLink "Choose from thousands of add-ons">
 <!ENTITY customizeMode.restoreDefaults "Restore Defaults">
-<!ENTITY customizeMode.toolbars "Show / Hide Toolbars">
+<!ENTITY customizeMode.done "Done">
 <!ENTITY customizeMode.titlebar "Title Bar">
+<!ENTITY customizeMode.toolbars2 "Toolbars">
 <!ENTITY customizeMode.lwthemes "Themes">
 <!ENTITY customizeMode.lwthemes.myThemes "My Themes">
 <!ENTITY customizeMode.lwthemes.recommended "Recommended">
 <!ENTITY customizeMode.lwthemes.menuManage "Manage">
 <!ENTITY customizeMode.lwthemes.menuManage.accessKey "M">
 <!ENTITY customizeMode.lwthemes.menuGetMore "Get More Themes">
 <!ENTITY customizeMode.lwthemes.menuGetMore.accessKey "G">
 
@@ -939,11 +940,16 @@ you can use these alternative items. Oth
 <!ENTITY updateManual.panelUI.label "Download a fresh copy of &brandShorterName;">
 
 <!ENTITY updateRestart.message "After a quick restart, &brandShorterName; will restore all your open tabs and windows.">
 <!ENTITY updateRestart.header.message2 "Restart to update &brandShorterName;.">
 <!ENTITY updateRestart.acceptButton.label "Restart and Restore">
 <!ENTITY updateRestart.acceptButton.accesskey "R">
 <!ENTITY updateRestart.cancelButton.label "Not Now">
 <!ENTITY updateRestart.cancelButton.accesskey "N">
-<!ENTITY updateRestart.panelUI.label "Restart &brandShorterName; to apply the update">
+<!ENTITY updateRestart.panelUI.label2 "Restart to update &brandShorterName;">
 
 <!ENTITY pageActionButton.tooltip "Page actions">
+
+<!ENTITY sendToDevice.label "Send to Device…">
+<!ENTITY sendToDevice.viewTitle "Send to Device">
+<!ENTITY sendToDevice.fxaRequired.label "Required">
+<!ENTITY sendToDevice.noDevices.label "No Devices Available">
--- a/browser/locales/en-US/chrome/browser/browser.properties
+++ b/browser/locales/en-US/chrome/browser/browser.properties
@@ -585,16 +585,20 @@ fullscreenButton.tooltip=Display the win
 service.toolbarbutton.label=Services
 service.toolbarbutton.tooltiptext=Services
 
 # LOCALIZATION NOTE (social.install.description): %1$S is the hostname of the social provider, %2$S is brandShortName (e.g. Firefox)
 service.install.description=Would you like to enable services from %1$S to display in your %2$S toolbar and sidebar?
 service.install.ok.label=Enable Services
 service.install.ok.accesskey=E
 
+# These are visible when opening the popup inside the bookmarks sidebar
+sidebar.moveToLeft=Move sidebar to left
+sidebar.moveToRight=Move sidebar to right
+
 # LOCALIZATION NOTE (social.markpageMenu.label): %S is the name of the social provider
 social.markpageMenu.label=Save Page to %S
 # LOCALIZATION NOTE (social.marklinkMenu.label): %S is the name of the social provider
 social.marklinkMenu.label=Save Link to %S
 
 # LOCALIZATION NOTE (social.error.message): %1$S is brandShortName (e.g. Firefox), %2$S is the name of the social provider
 social.error.message=%1$S is unable to connect with %2$S right now.
 social.error.tryAgain.label=Try Again
--- a/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
+++ b/browser/locales/en-US/chrome/browser/preferences/advanced.dtd
@@ -133,22 +133,22 @@
 <!ENTITY enableOCSP.label                "Query OCSP responder servers to confirm the current validity of certificates">
 <!ENTITY enableOCSP.accesskey            "Q">
 <!ENTITY viewCerts.label                 "View Certificates">
 <!ENTITY viewCerts.accesskey             "C">
 <!ENTITY viewSecurityDevices.label       "Security Devices">
 <!ENTITY viewSecurityDevices.accesskey   "D">
 
 <!ENTITY performance.label               "Performance">
-<!ENTITY useRecommendedPerformanceSettings.label
+<!ENTITY useRecommendedPerformanceSettings2.label
                                          "Use recommended performance settings">
-<!ENTITY useRecommendedPerformanceSettings.description
-                                         "Recommended performance settings are tailored to your computer.">
-<!ENTITY useRecommendedPerformanceSettings.accesskey
+<!ENTITY useRecommendedPerformanceSettings2.description
+                                         "These settings are tailored to your computer’s hardware and operating system.">
+<!ENTITY useRecommendedPerformanceSettings2.accesskey
                                          "U">
 <!ENTITY performanceSettingsLearnMore.label
                                          "Learn more">
-<!ENTITY limitContentProcess.label       "Content process limit">
-<!ENTITY limitContentProcess.description
-                                         "More content processes can make &brandShortName; more responsive when using multiple tabs, but will also consume more memory.">
-<!ENTITY limitContentProcess.accesskey   "L">
+<!ENTITY limitContentProcess2.label       "Content process limit">
+<!ENTITY limitContentProcess2.description
+                                         "Additional content processes can improve &brandShortName; performance when using multiple tabs, but will also use more memory.">
+<!ENTITY limitContentProcess2.accesskey   "L">
 <!ENTITY allowHWAccel.label              "Use hardware acceleration when available">
 <!ENTITY allowHWAccel.accesskey          "r">
--- a/browser/themes/osx/browser.css
+++ b/browser/themes/osx/browser.css
@@ -1352,16 +1352,21 @@ html|span.ac-emphasize-text-url {
 /* ----- SIDEBAR ELEMENTS ----- */
 
 %include ../shared/sidebar.inc.css
 
 #sidebar-box {
   -moz-appearance: -moz-mac-source-list;
 }
 
+#sidebar-header {
+  /* match the font size used in side bar content */
+  font-size: 12px;
+}
+
 /* ----- CONTENT ----- */
 
 .browserContainer > findbar {
   background: @scopeBarBackground@;
   border-top: @scopeBarSeparatorBorder@;
   color: -moz-DialogText;
   text-shadow: none;
 }
@@ -1720,17 +1725,17 @@ toolbarbutton.chevron > .toolbarbutton-m
   }
 
   .tabs-newtab-button > .toolbarbutton-icon {
     width: 40px;
   }
 
   #TabsToolbar > #new-tab-button > .toolbarbutton-icon,
   #TabsToolbar > toolbarpaletteitem > #new-tab-button > .toolbarbutton-icon {
-    width: 18px;
+    max-width: 18px;
   }
 }
 
 #alltabs-button {
   list-style-image: url(chrome://browser/skin/tabbrowser/alltabs-box-bkgnd-icon.png);
   -moz-image-region: rect(0, 17px, 20px, 0);
 }
 
deleted file mode 100644
index fb0edd2566a4f803e43914f431b4c2050f5aba18..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 7200e74c2bdcbc6363d5f3903111c45572210b0e..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/osx/jar.mn
+++ b/browser/themes/osx/jar.mn
@@ -46,18 +46,16 @@ browser.jar:
   skin/classic/browser/webRTC-sharingDevice-menubar@2x.png
   skin/classic/browser/webRTC-sharingMicrophone-menubar.png
   skin/classic/browser/webRTC-sharingMicrophone-menubar@2x.png
   skin/classic/browser/webRTC-sharingScreen-menubar.png
   skin/classic/browser/webRTC-sharingScreen-menubar@2x.png
   skin/classic/browser/webRTC-indicator.css
 * skin/classic/browser/controlcenter/panel.css        (controlcenter/panel.css)
   skin/classic/browser/customizableui/background-noise-toolbar.png  (customizableui/background-noise-toolbar.png)
-  skin/classic/browser/customizableui/customize-titleBar-toggle.png  (customizableui/customize-titleBar-toggle.png)
-  skin/classic/browser/customizableui/customize-titleBar-toggle@2x.png  (customizableui/customize-titleBar-toggle@2x.png)
   skin/classic/browser/customizableui/customizeMode-gridTexture.png  (customizableui/customizeMode-gridTexture.png)
   skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png  (customizableui/customizeMode-separatorHorizontal.png)
   skin/classic/browser/customizableui/customizeMode-separatorVertical.png  (customizableui/customizeMode-separatorVertical.png)
 * skin/classic/browser/customizableui/panelUI.css    (customizableui/panelUI.css)
 * skin/classic/browser/downloads/allDownloadsViewOverlay.css (downloads/allDownloadsViewOverlay.css)
   skin/classic/browser/downloads/download-glow-menuPanel.png (downloads/download-glow-menuPanel.png)
   skin/classic/browser/downloads/download-glow-menuPanel@2x.png (downloads/download-glow-menuPanel@2x.png)
   skin/classic/browser/downloads/download-notification-finish.png  (downloads/download-notification-finish.png)
--- a/browser/themes/shared/browser.inc.css
+++ b/browser/themes/shared/browser.inc.css
@@ -73,29 +73,41 @@
   display: none;
 }
 
 /* Page action button */
 #urlbar-page-action-button {
   -moz-appearance: none;
   border-style: none;
   list-style-image: url("chrome://browser/skin/page-action.svg");
-  -moz-context-properties: fill;
   margin: 0;
   padding: 0 6px;
+  -moz-context-properties: fill;
   fill: currentColor;
 }
 
 #urlbar-page-action-button > .toolbarbutton-icon {
   width: 16px;
 }
 
 #page-action-copy-url-button {
   list-style-image: url("chrome://browser/skin/copy-url.svg");
-  -moz-context-properties: fill;
-  fill: currentColor;
 }
 
 #page-action-email-link-button {
   list-style-image: url("chrome://browser/skin/email-link.svg");
-  -moz-context-properties: fill;
-  fill: currentColor;
+}
+
+#page-action-send-to-device-button {
+  list-style-image: url("chrome://browser/skin/device-mobile.svg");
+}
+
+.page-action-sendToDevice-device[clientType=mobile] {
+  list-style-image: url("chrome://browser/skin/device-mobile.svg");
 }
+
+.page-action-sendToDevice-device[clientType=desktop] {
+  list-style-image: url("chrome://browser/skin/device-desktop.svg");
+}
+
+#page-action-sendToDevice-fxa-button {
+  list-style-image: url("chrome://browser/skin/sync.svg");
+}
--- a/browser/themes/shared/customizableui/customizeMode.inc.css
+++ b/browser/themes/shared/customizableui/customizeMode.inc.css
@@ -139,112 +139,112 @@
 }
 
 %if defined(XP_MACOSX) || defined(XP_WIN)
 %ifdef XP_WIN
 @media (-moz-windows-default-theme) {
 %endif
 
 .customizationmode-button {
-  border: 1px solid rgb(192,192,192);
-  border-radius: 3px;
-  margin: 5px;
-  padding: 2px 10px;
-  background-color: rgb(251,251,251);
+  border: 1px solid #b1b1b1;
+  margin: 6px 10px;
+  padding: 2px 5px;
+  background-color: #fcfcfd;
   color: rgb(71,71,71);
-  box-shadow: 0 1px rgba(255, 255, 255, 0.5),
-              inset 0 1px rgba(255, 255, 255, 0.5);
   -moz-appearance: none;
 }
 
+.customizationmode-checkbox {
+  margin: 6px 10px;
+  padding: 2px 5px;
+}
+
+#customization-reset-button,
+#customization-undo-reset-button,
+#customization-done-button {
+  min-width: 10em;
+}
+
+#customization-done-button {
+  color: #fff;
+  font-weight: 700;
+  border-color: #0060df;
+  background-color: #0a84ff;
+}
+
 .customizationmode-button > .box-inherit {
   border-width: 0;
+  padding: 3px 0;
   padding-inline-start: 0;
   padding-inline-end: 0;
 }
 
+/* We use a smaller padding to ensure images don't have padding.
+ * We can't detect whether a button has an image. This button doesn't
+ * so it needs more padding, so we unfortunately hardcode the extra
+ * padding in here:
+ */
+#customization-toolbar-visibility-button {
+  padding-inline-start: 8px;
+}
+
+.customizationmode-button[type=menu] > .box-inherit > .box-inherit > .button-text {
+  padding-inline-end: 10px;
+}
+
 .customizationmode-button > .button-icon {
   margin-inline-start: 0;
 }
 
 .customizationmode-button:not([type=menu]) > .button-text {
   margin-inline-end: 0;
 }
 
-.customizationmode-button > .button-menu-dropmarker {
+.customizationmode-button > .box-inherit > .button-menu-dropmarker {
   margin-inline-end: 0;
   padding-inline-end: 0;
+  list-style-image: url(chrome://browser/skin/arrow-dropdown.svg);
 }
 
-.customizationmode-button:hover:active:not([disabled]),
-.customizationmode-button[open],
-.customizationmode-button[checked] {
-  background-color: rgb(218, 218, 218);
-  border-color: rgb(168, 168, 168);
-  text-shadow: 0 1px rgb(236, 236, 236);
-  box-shadow: 0 1px rgba(255, 255, 255, 0.5),
-              inset 0 1px rgb(196, 196, 196);
+.customizationmode-button:-moz-any(:focus,:active,:hover):not([disabled]),
+.customizationmode-button[open] {
+  background-color: #e1e1e5;
+}
+
+#customization-done-button:-moz-any(:focus,:active,:hover):not([disabled]) {
+  background-color: #0060df;
 }
 
 .customizationmode-button[disabled="true"] {
   opacity: .5;
 }
 
 %ifdef XP_WIN
 } /* @media (-moz-windows-default-theme) */
 %endif
 %endif /* defined(XP_MACOSX) || defined(XP_WIN) */
 
 .customizationmode-button > .box-inherit > .box-inherit > .button-icon,
 .customizationmode-button > .button-box > .button-icon {
-  height: 24px;
+  height: 16px;
 }
 
-%ifdef CAN_DRAW_IN_TITLEBAR
-#customization-titlebar-visibility-button > .button-box > .button-text,
-%endif
 #customization-lwtheme-button > .box-inherit > .box-inherit > .button-text {
   /* Sadly, button.css thinks its margins are perfect for everyone. */
   margin-inline-start: 6px !important;
 }
 
 #customization-lwtheme-button > .box-inherit > .box-inherit > .button-icon {
-  width: 20px;
-  height: 20px;
+  width: 16px;
+  height: 16px;
   border-radius: 2px;
   background-image: url("chrome://browser/content/default-theme-icon.svg");
   background-size: contain;
 }
 
-%ifdef CAN_DRAW_IN_TITLEBAR
-#customization-titlebar-visibility-button {
-  list-style-image: url("chrome://browser/skin/customizableui/customize-titleBar-toggle.png");
-  -moz-image-region: rect(0, 24px, 24px, 0);
-}
-
-#customization-titlebar-visibility-button > .button-box > .button-icon {
-  vertical-align: middle;
-}
-
-#customization-titlebar-visibility-button[checked] {
-  -moz-image-region: rect(0, 48px, 24px, 24px);
-}
-
-@media (min-resolution: 1.1dppx) {
-  #customization-titlebar-visibility-button {
-    list-style-image: url("chrome://browser/skin/customizableui/customize-titleBar-toggle@2x.png");
-    -moz-image-region: rect(0, 48px, 48px, 0);
-  }
-
-  #customization-titlebar-visibility-button[checked] {
-    -moz-image-region: rect(0, 96px, 48px, 48px);
-  }
-}
-%endif /* CAN_DRAW_IN_TITLEBAR */
-
 #main-window[customize-entered] #customization-panel-container {
   background-image: url("chrome://browser/skin/customizableui/customizeMode-separatorHorizontal.png"),
                     url("chrome://browser/skin/customizableui/customizeMode-separatorVertical.png"),
                     url("chrome://browser/skin/customizableui/customizeMode-gridTexture.png"),
                     url("chrome://browser/skin/customizableui/background-noise-toolbar.png"),
                     linear-gradient(to bottom, #3e86ce, #3878ba);
   background-position: center top, left center, left top, left top, left top;
   background-repeat: no-repeat, no-repeat, repeat, repeat, no-repeat;
--- a/browser/themes/shared/customizableui/panelUI.inc.css
+++ b/browser/themes/shared/customizableui/panelUI.inc.css
@@ -117,17 +117,17 @@
 #PanelUI-menu-button[badge-status="update-available"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
 #PanelUI-menu-button[badge-status="update-manual"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
 #PanelUI-menu-button[badge-status="update-restart"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
   background: #74BF43 url(chrome://browser/skin/update-badge.svg) no-repeat center;
   border-radius: 50%;
   box-shadow: none;
   border: 2px solid -moz-dialog;
   /* "!important" is necessary to override the rule in toolbarbutton.css */
-  margin: -8px 0 0 !important;
+  margin: -9px 0 0 !important;
   margin-inline-end: -6px !important;
   min-width: 16px;
   min-height: 16px;
 }
 
 .panel-banner-item[notificationid^=update]::after {
   background: #74BF43 url(chrome://browser/skin/update-badge.svg) no-repeat center;
   border-radius: 50%;
@@ -193,26 +193,32 @@
 .panel-viewstack[viewtype="main"] > .panel-subviews:-moz-locale-dir(rtl) {
   transform: translateX(-@menuPanelWidth@);
 }
 
 panelmultiview[nosubviews=true] > .panel-viewcontainer > .panel-viewstack > .panel-subviews {
   display: none;
 }
 
-.panel-viewstack:not([viewtype="main"]) > .panel-mainview > #PanelUI-mainView {
+panelview {
+  -moz-box-orient: vertical;
   -moz-box-flex: 1;
 }
 
 .panel-subview-body {
   overflow-y: auto;
   overflow-x: hidden;
   -moz-box-flex: 1;
 }
 
+.panel-view-body-unscrollable {
+  overflow: hidden;
+  -moz-box-flex: 1;
+}
+
 #PanelUI-popup .panel-subview-body {
   margin: -4px;
   padding: 4px 4px;
 }
 
 .panel-subview-header,
 .subviewbutton.panel-subview-footer {
   box-sizing: border-box;
@@ -220,16 +226,18 @@ panelmultiview[nosubviews=true] > .panel
   padding: 11px 12px;
 }
 
 .panel-subview-header {
   margin: -4px -4px 4px;
   border-bottom: 1px solid var(--panel-separator-color);
   color: GrayText;
   font-variant: small-caps;
+  /* Workaround for min-height not being accounted for in vertical layout. */
+  height: 41px;
 }
 
 .cui-widget-panelview .panel-subview-header,
 photonpanelmultiview .panel-subview-header {
   display: none;
 }
 
 .cui-widget-panelview .subviewbutton.panel-subview-footer {
@@ -744,16 +752,20 @@ toolbarpaletteitem[place="palette"] > to
 #appMenu-fxa-icon > .toolbarbutton-text {
   display: none;
 }
 
 #appMenu-fxa-icon[syncstatus="active"] {
   list-style-image: url(chrome://browser/skin/syncProgress-horizontalbar.png);
 }
 
+#appMenu-fxa-status {
+  -moz-box-align: center;
+}
+
 #appMenu-fxa-avatar {
   pointer-events: none;
   list-style-image: url(chrome://browser/skin/fxa/default-avatar.svg);
 }
 
 @media (min-resolution: 1.1dppx) {
   #appMenu-fxa-label,
   #appMenu-fxa-icon {
@@ -1280,20 +1292,24 @@ photonpanelmultiview .subviewbutton[chec
 photonpanelmultiview .subviewbutton:not(.subviewbutton-iconic):not([checked="true"]) > .toolbarbutton-text {
   padding-inline-start: 24px; /* This is 16px for the icon + 8px for the padding as defined above. */
 }
 
 photonpanelmultiview .PanelUI-subView .panel-subview-footer {
   font-size: 1.2rem;
 }
 
+photonpanelmultiview .subviewbutton {
+  -moz-context-properties: fill;
+  fill: currentColor;
+}
+
 photonpanelmultiview .subviewbutton[checked="true"] {
   background: none;
   list-style-image: url(chrome://browser/skin/menu-icons/check.svg);
-  -moz-context-properties: fill;
 }
 
 photonpanelmultiview .subviewbutton > .menu-iconic-left {
   -moz-appearance: none;
   margin-inline-end: 0;
 }
 
 photonpanelmultiview .toolbaritem-combined-buttons:-moz-any(:not([cui-areatype="toolbar"]), [overflowedItem="true"]) {
@@ -1998,18 +2014,16 @@ menuitem[checked="true"].subviewbutton >
   #PanelUI-panic-actionlist-newwindow {
     background-image: -moz-image-rect(url(chrome://browser/skin/panic-panel/icons@2x.png), 0, 128, 32, 96);
   }
 
   #PanelUI-menu-button[badge-status="update-available"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
   #PanelUI-menu-button[badge-status="update-manual"] > .toolbarbutton-badge-stack > .toolbarbutton-badge,
   #PanelUI-menu-button[badge-status="update-restart"] > .toolbarbutton-badge-stack > .toolbarbutton-badge {
     border: 1px solid -moz-dialog;
-    /* "!important" is necessary to override the rule in toolbarbutton.css */
-    margin: -9px 0 0 !important;
   }
 }
 
 .subviewbutton-iconic > .toolbarbutton-text {
   padding-inline-start: 5px;
 }
 
 /* START photon adjustments */
--- a/browser/themes/shared/downloads/downloads.inc.css
+++ b/browser/themes/shared/downloads/downloads.inc.css
@@ -10,17 +10,16 @@
 %define itemFinished @item@[state="1"]
 %define itemNotFinished @item@:not([state="1"])
 %define itemFocused #downloadsListBox:focus > @item@[selected]
 
 /*** Panel and outer controls ***/
 
 #downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent {
   overflow: hidden;
-  display: block;
 }
 
 #downloadsPanel > .panel-arrowcontainer > .panel-arrowcontent,
 #downloadsPanel-multiView > .panel-viewcontainer > .panel-viewstack > .panel-subviews {
   padding: 0;
 }
 
 #downloadsListBox {
rename from browser/themes/shared/sidebar/arrow-dropdown.svg
rename to browser/themes/shared/icons/arrow-dropdown.svg
--- a/browser/themes/shared/icons/copy-url.svg
+++ b/browser/themes/shared/icons/copy-url.svg
@@ -1,7 +1,6 @@
-<?xml version="1.0"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
   <path fill="context-fill" d="M14.707 8.293l-3-3A1 1 0 0 0 11 5h-1V4a1 1 0 0 0-.293-.707l-3-3A1 1 0 0 0 6 0H3a2 2 0 0 0-2 2v7a2 2 0 0 0 2 2h3v3a2 2 0 0 0 2 2h5a2 2 0 0 0 2-2V9a1 1 0 0 0-.293-.707zM12.586 9H11V7.414zm-5-5H6V2.414zM6 7v2H3V2h2v2.5a.5.5 0 0 0 .5.5H8a2 2 0 0 0-2 2zm2 7V7h2v2.5a.5.5 0 0 0 .5.5H13v4z"/>
 </svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/icons/device-desktop.svg
@@ -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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" d="M0 12h16a1.959 1.959 0 0 1-2 2H2a1.959 1.959 0 0 1-2-2zM13.107 2H2.894A1.894 1.894 0 0 0 1 3.894V11h14V3.893A1.893 1.893 0 0 0 13.107 2zM14 10H2V4a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1z"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/icons/device-mobile.svg
@@ -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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" d="M10 1H6a2 2 0 0 0-2 2v10a2 2 0 0 0 2 2h4a2 2 0 0 0 2-2V3a2 2 0 0 0-2-2zm1 11.5a.5.5 0 0 1-.5.5h-5a.5.5 0 0 1-.5-.5v-9a.5.5 0 0 1 .5-.5h5a.5.5 0 0 1 .5.5z"/>
+</svg>
--- a/browser/themes/shared/icons/email-link.svg
+++ b/browser/themes/shared/icons/email-link.svg
@@ -1,8 +1,7 @@
-<?xml version="1.0"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
   <path fill="context-fill" d="M13 2H3a3.013 3.013 0 0 0-3 3v6a3.013 3.013 0 0 0 3 3h10a3.013 3.013 0 0 0 3-3V5a3.013 3.013 0 0 0-3-3zm1 9a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V5a1 1 0 0 1 1-1h10a1 1 0 0 1 1 1z"/>
   <path fill="context-fill" d="M8 9a.5.5 0 0 1-.294-.1l-5.5-4a.5.5 0 1 1 .588-.8L8 7.882 13.207 4.1a.5.5 0 0 1 .588.809l-5.5 4A.5.5 0 0 1 8 9z"/>
 </svg>
--- a/browser/themes/shared/icons/page-action.svg
+++ b/browser/themes/shared/icons/page-action.svg
@@ -1,7 +1,6 @@
-<?xml version="1.0"?>
 <!-- This Source Code Form is subject to the terms of the Mozilla Public
    - License, v. 2.0. If a copy of the MPL was not distributed with this
    - file, You can obtain one at http://mozilla.org/MPL/2.0/. -->
 <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16">
   <path fill="context-fill" d="M2 6a2 2 0 1 0 2 2 2 2 0 0 0-2-2zm6 0a2 2 0 1 0 2 2 2 2 0 0 0-2-2zm6 0a2 2 0 1 0 2 2 2 2 0 0 0-2-2z"/>
 </svg>
--- a/browser/themes/shared/identity-block/identity-block.inc.css
+++ b/browser/themes/shared/identity-block/identity-block.inc.css
@@ -71,31 +71,31 @@
 #connection-icon:-moz-lwtheme,
 #extension-icon:-moz-lwtheme {
   fill: rgba(0,0,0,.6);
 }
 
 /* MAIN IDENTITY ICON */
 
 #identity-icon {
-  list-style-image: url(chrome://browser/skin/identity-icon.svg#normal);
+  list-style-image: url(chrome://browser/skin/identity-icon.svg);
 }
 
 #identity-box:hover > #identity-icon:not(.no-hover),
 #identity-box[open=true] > #identity-icon {
-  list-style-image: url(chrome://browser/skin/identity-icon.svg#hover);
+  list-style-image: url(chrome://browser/skin/identity-icon-hover.svg);
 }
 
 #identity-box.grantedPermissions > #identity-icon {
-  list-style-image: url(chrome://browser/skin/identity-icon.svg#notice);
+  list-style-image: url(chrome://browser/skin/identity-icon-notice.svg);
 }
 
 #identity-box.grantedPermissions:hover > #identity-icon:not(.no-hover),
 #identity-box.grantedPermissions[open=true] > #identity-icon {
-  list-style-image: url(chrome://browser/skin/identity-icon.svg#notice-hover);
+  list-style-image: url(chrome://browser/skin/identity-icon-notice-hover.svg);
 }
 
 #urlbar[pageproxystate="valid"] > #identity-box.chromeUI > #identity-icon {
   list-style-image: url(chrome://branding/content/identity-icons-brand.svg);
 }
 
 #urlbar[pageproxystate="invalid"] > #identity-box > #identity-icon {
   opacity: .3;
@@ -212,14 +212,14 @@
 #identity-box.extensionPage > #extension-icon {
   list-style-image: url(chrome://browser/skin/controlcenter/extension.svg);
   visibility: visible;
 }
 
 /* REMOTE CONTROL ICON */
 
 #main-window[remotecontrol] #remote-control-icon {
-  list-style-image: url(chrome://browser/content/robot.ico);
+  list-style-image: url(chrome://browser/content/static-robot.png);
   visibility: visible;
   width: 16px;
   height: 16px;
   margin-inline-start: 2px;
 }
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/identity-block/identity-icon-hover.svg
@@ -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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" fill-rule="evenodd" d="M8 1a7 7 0 1 1-7 7 7 7 0 0 1 7-7zm0 3a1 1 0 1 1-1 1 1 1 0 0 1 1-1zm0 3a1 1 0 0 1 1 1v3a1 1 0 0 1-2 0V8a1 1 0 0 1 1-1z"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/identity-block/identity-icon-notice-hover.svg
@@ -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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" fill-rule="evenodd" d="M13.5 5A2.5 2.5 0 1 1 16 2.5 2.5 2.5 0 0 1 13.5 5zm0 1.039a3.5 3.5 0 0 0 1.125-.2 7.124 7.124 0 1 1-4.464-4.464 3.5 3.5 0 0 0-.2 1.125A3.54 3.54 0 0 0 13.5 6.039zM8 4a1 1 0 1 0 1 1 1 1 0 0 0-1-1zm1 4a1 1 0 0 0-2 0v3a1 1 0 0 0 2 0V8z"/>
+</svg>
new file mode 100644
--- /dev/null
+++ b/browser/themes/shared/identity-block/identity-icon-notice.svg
@@ -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/. -->
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" fill-rule="evenodd" d="M13.5 5A2.5 2.5 0 1 1 16 2.5 2.5 2.5 0 0 1 13.5 5zM8 6a1 1 0 1 1 1-1 1 1 0 0 1-1 1zm1 5a1 1 0 0 1-2 0V8a1 1 0 0 1 2 0v3zM8 2a6.08 6.08 0 1 0 5.629 3.987 3.452 3.452 0 0 0 .984-.185A6.9 6.9 0 0 1 15 8a7 7 0 1 1-7-7 6.9 6.9 0 0 1 2.2.387 3.452 3.452 0 0 0-.185.984A5.951 5.951 0 0 0 8 2z"/>
+</svg>
--- a/browser/themes/shared/identity-block/identity-icon.svg
+++ b/browser/themes/shared/identity-block/identity-icon.svg
@@ -1,24 +1,6 @@
-<?xml version="1.0" encoding="utf-8"?>
 <!-- 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/. -->
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
-     width="16" height="16" viewBox="0 0 16 16">
-  <style>
-    use:not(:target) {
-      display: none;
-    }
-  </style>
-
-  <defs>
-    <path id="glyph-normal" d="M128,193a7,7,0,1,1,7-7A7,7,0,0,1,128,193Zm0-13a6,6,0,1,0,6,6A6,6,0,0,0,128,180Zm0,10a1,1,0,0,1-1-1v-3a1,1,0,0,1,2,0v3A1,1,0,0,1,128,190Zm0-6a1,1,0,1,1,1-1A1,1,0,0,1,128,184Z" transform="translate(-120 -178)"/>
-    <path id="glyph-hover" d="M102,179a7,7,0,1,1-7,7A7,7,0,0,1,102,179Zm0,3a1,1,0,1,1-1,1A1,1,0,0,1,102,182Zm0,3a1,1,0,0,1,1,1v3a1,1,0,0,1-2,0v-3A1,1,0,0,1,102,185Z" transform="translate(-94 -178)"/>
-    <path id="glyph-notice" d="M133.5,202a2.5,2.5,0,1,1,2.5-2.5A2.5,2.5,0,0,1,133.5,202Zm-5.5,1a1,1,0,1,1,1-1A1,1,0,0,1,128,203Zm1,5a1,1,0,0,1-2,0v-3a1,1,0,0,1,2,0v3Zm-1-9a6.08,6.08,0,1,0,5.629,3.987,3.452,3.452,0,0,0,.984-0.185A6.9,6.9,0,0,1,135,205a7,7,0,1,1-7-7,6.9,6.9,0,0,1,2.2.387,3.452,3.452,0,0,0-.185.984A5.951,5.951,0,0,0,128,199Z" transform="translate(-120 -197)"/>
-    <path id="glyph-notice-hover" d="M107.5,202a2.5,2.5,0,1,1,2.5-2.5A2.5,2.5,0,0,1,107.5,202Zm0,1.039a3.5,3.5,0,0,0,1.125-.2,7.124,7.124,0,1,1-4.464-4.464,3.5,3.5,0,0,0-.2,1.125A3.54,3.54,0,0,0,107.5,203.039ZM102,201a1,1,0,1,0,1,1A1,1,0,0,0,102,201Zm1,4a1,1,0,0,0-2,0v3a1,1,0,0,0,2,0v-3Z" transform="translate(-94 -197)"/>
-  </defs>
-
-  <use fill="context-fill" fill-rule="evenodd" id="normal" xlink:href="#glyph-normal"/>
-  <use fill="context-fill" fill-rule="evenodd" id="hover" xlink:href="#glyph-hover"/>
-  <use fill="context-fill" fill-rule="evenodd" id="notice" xlink:href="#glyph-notice"/>
-  <use fill="context-fill" fill-rule="evenodd" id="notice-hover" xlink:href="#glyph-notice-hover"/>
+<svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 16 16">
+  <path fill="context-fill" fill-rule="evenodd" d="M8 15a7 7 0 1 1 7-7 7 7 0 0 1-7 7zM8 2a6 6 0 1 0 6 6 6 6 0 0 0-6-6zm0 10a1 1 0 0 1-1-1V8a1 1 0 0 1 2 0v3a1 1 0 0 1-1 1zm0-6a1 1 0 1 1 1-1 1 1 0 0 1-1 1z"/>
 </svg>
--- a/browser/themes/shared/incontentprefs/preferences.inc.css
+++ b/browser/themes/shared/incontentprefs/preferences.inc.css
@@ -610,23 +610,23 @@ description > html|a {
   text-decoration: none;
 }
 
 .search-tooltip {
   position: absolute;
   pointer-events: none;
   padding: 0 10px;
   bottom: 100%;
-  background-color: #ffe352;
+  background-color: #ffe900;
 }
 
 .search-tooltip::before {
   position: absolute;
   content: "";
   border: 6px solid transparent;
-  border-top-color: #ffe352;
+  border-top-color: #ffe900;
   top: 100%;
   offset-inline-start: calc(50% - 6px);
 }
 
 .search-tooltip-parent {
   position: relative;
 }
--- a/browser/themes/shared/jar.inc.mn
+++ b/browser/themes/shared/jar.inc.mn
@@ -43,17 +43,16 @@
   skin/classic/browser/customizableui/menuPanel-customizeFinish.png  (../shared/customizableui/menuPanel-customizeFinish.png)
   skin/classic/browser/customizableui/menuPanel-customizeFinish@2x.png  (../shared/customizableui/menuPanel-customizeFinish@2x.png)
   skin/classic/browser/customizableui/panelarrow-customizeTip.png  (../shared/customizableui/panelarrow-customizeTip.png)
   skin/classic/browser/customizableui/panelarrow-customizeTip@2x.png  (../shared/customizableui/panelarrow-customizeTip@2x.png)
   skin/classic/browser/customizableui/subView-arrow-back-inverted.png  (../shared/customizableui/subView-arrow-back-inverted.png)
   skin/classic/browser/customizableui/subView-arrow-back-inverted@2x.png  (../shared/customizableui/subView-arrow-back-inverted@2x.png)
   skin/classic/browser/customizableui/subView-arrow-back-inverted-rtl.png  (../shared/customizableui/subView-arrow-back-inverted-rtl.png)
   skin/classic/browser/customizableui/subView-arrow-back-inverted-rtl@2x.png  (../shared/customizableui/subView-arrow-back-inverted-rtl@2x.png)
-  skin/classic/browser/sidebar/arrow-dropdown.svg           (../shared/sidebar/arrow-dropdown.svg)
   skin/classic/browser/sidebar/bookmark-filled.svg          (../shared/sidebar/bookmark-filled.svg)
   skin/classic/browser/sidebar/close.svg                    (../shared/sidebar/close.svg)
   skin/classic/browser/sidebar/history.svg                  (../shared/sidebar/history.svg)
   skin/classic/browser/sidebar/sync.svg                     (../shared/sidebar/sync.svg)
   skin/classic/browser/customizableui/whimsy.png               (../shared/customizableui/whimsy.png)
   skin/classic/browser/customizableui/whimsy@2x.png            (../shared/customizableui/whimsy@2x.png)
   skin/classic/browser/downloads/contentAreaDownloadsView.css  (../shared/downloads/contentAreaDownloadsView.css)
   skin/classic/browser/downloads/download-blocked.svg          (../shared/downloads/download-blocked.svg)
@@ -63,16 +62,19 @@
   skin/classic/browser/fullscreen/secure.svg                   (../shared/fullscreen/secure.svg)
   skin/classic/browser/heartbeat-icon.svg                      (../shared/heartbeat-icon.svg)
   skin/classic/browser/heartbeat-star-lit.svg                  (../shared/heartbeat-star-lit.svg)
   skin/classic/browser/heartbeat-star-off.svg                  (../shared/heartbeat-star-off.svg)
   skin/classic/browser/connection-secure.svg                   (../shared/identity-block/connection-secure.svg)
   skin/classic/browser/connection-mixed-passive-loaded.svg     (../shared/identity-block/connection-mixed-passive-loaded.svg)
   skin/classic/browser/connection-mixed-active-loaded.svg      (../shared/identity-block/connection-mixed-active-loaded.svg)
   skin/classic/browser/identity-icon.svg                       (../shared/identity-block/identity-icon.svg)
+  skin/classic/browser/identity-icon-hover.svg                 (../shared/identity-block/identity-icon-hover.svg)
+  skin/classic/browser/identity-icon-notice.svg                (../shared/identity-block/identity-icon-notice.svg)
+  skin/classic/browser/identity-icon-notice-hover.svg          (../shared/identity-block/identity-icon-notice-hover.svg)
   skin/classic/browser/info.svg                                (../shared/info.svg)
 * skin/classic/browser/menuPanel.svg                           (../shared/menuPanel.svg)
 * skin/classic/browser/menuPanel-small.svg                     (../shared/menuPanel-small.svg)
 * skin/classic/browser/notification-icons.svg                  (../shared/notification-icons.svg)
   skin/classic/browser/tracking-protection-16.svg              (../shared/identity-block/tracking-protection-16.svg)
   skin/classic/browser/newtab/close.png                        (../shared/newtab/close.png)
   skin/classic/browser/newtab/controls.svg                     (../shared/newtab/controls.svg)
   skin/classic/browser/panel-icons.svg                         (../shared/panel-icons.svg)
@@ -92,16 +94,17 @@
   skin/classic/browser/fxa/sync-illustration.svg               (../shared/fxa/sync-illustration.svg)
   skin/classic/browser/fxa/android.png                         (../shared/fxa/android.png)
   skin/classic/browser/fxa/android@2x.png                      (../shared/fxa/android@2x.png)
   skin/classic/browser/fxa/ios.png                             (../shared/fxa/ios.png)
   skin/classic/browser/fxa/ios@2x.png                          (../shared/fxa/ios@2x.png)
 
 
   skin/classic/browser/addons.svg                     (../shared/icons/addons.svg)
+  skin/classic/browser/arrow-dropdown.svg             (../shared/icons/arrow-dropdown.svg)
   skin/classic/browser/back.svg                       (../shared/icons/back.svg)
 #ifndef MOZ_PHOTON_THEME
   skin/classic/browser/back-large.svg                 (../shared/icons/back-large.svg)
 #endif
   skin/classic/browser/bookmark.svg                   (../shared/icons/bookmark.svg)
   skin/classic/browser/bookmark-hollow.svg            (../shared/icons/bookmark-hollow.svg)
   skin/classic/browser/bookmarksMenu.svg              (../shared/icons/bookmarksMenu.svg)
   skin/classic/browser/characterEncoding.svg          (../shared/icons/characterEncoding.svg)
@@ -195,16 +198,18 @@
   skin/classic/browser/compacttheme/loading-inverted.png (../shared/compacttheme/loading-inverted.png)
   skin/classic/browser/compacttheme/loading-inverted@2x.png (../shared/compacttheme/loading-inverted@2x.png)
   skin/classic/browser/compacttheme/urlbar-history-dropmarker.svg (../shared/compacttheme/urlbar-history-dropmarker.svg)
   skin/classic/browser/urlbar-star.svg                         (../shared/urlbar-star.svg)
   skin/classic/browser/urlbar-tab.svg                          (../shared/urlbar-tab.svg)
   skin/classic/browser/page-action.svg                         (../shared/icons/page-action.svg)
   skin/classic/browser/copy-url.svg                            (../shared/icons/copy-url.svg)
   skin/classic/browser/email-link.svg                          (../shared/icons/email-link.svg)
+  skin/classic/browser/device-mobile.svg                       (../shared/icons/device-mobile.svg)
+  skin/classic/browser/device-desktop.svg                      (../shared/icons/device-desktop.svg)
   skin/classic/browser/menu-icons/back.svg                     (../shared/menu-icons/back.svg)
   skin/classic/browser/menu-icons/back-small.svg               (../shared/menu-icons/back-small.svg)
   skin/classic/browser/menu-icons/addons.svg                   (../shared/menu-icons/addons.svg)
   skin/classic/browser/menu-icons/check.svg                    (../shared/menu-icons/check.svg)
   skin/classic/browser/menu-icons/customize.svg                (../shared/menu-icons/customize.svg)
   skin/classic/browser/menu-icons/find.svg                     (../shared/menu-icons/find.svg)
   skin/classic/browser/menu-icons/help.svg                     (../shared/menu-icons/help.svg)
   skin/classic/browser/menu-icons/library.svg                  (../shared/menu-icons/library.svg)
--- a/browser/themes/shared/menupanel.inc.css
+++ b/browser/themes/shared/menupanel.inc.css
@@ -179,57 +179,48 @@ toolbarpaletteitem[place="palette"] > #z
 #add-share-provider {
   list-style-image: url(chrome://browser/skin/menuPanel-small.svg);
   -moz-image-region: rect(0px, 96px, 16px, 80px);
 }
 
 
 #appMenu-new-window-button {
   list-style-image: url(chrome://browser/skin/menu-icons/new-window.svg);
-  -moz-context-properties: fill;
 }
 
 #appMenu-private-window-button {
   list-style-image: url(chrome://browser/skin/menu-icons/private-window.svg);
-  -moz-context-properties: fill;
 }
 
 #appMenu-print-button {
   list-style-image: url(chrome://browser/skin/menu-icons/print.svg);
-  -moz-context-properties: fill;
 }
 
 #appMenu-library-button {
   list-style-image: url(chrome://browser/skin/menu-icons/library.svg);
-  -moz-context-properties: fill;
 }
 
 #appMenu-addons-button {
   list-style-image: url(chrome://browser/skin/menu-icons/addons.svg);
-  -moz-context-properties: fill;
 }
 
 #appMenu-preferences-button {
   list-style-image: url(chrome://browser/skin/menu-icons/settings.svg);
-  -moz-context-properties: fill;
 }
 
 #appMenu-customize-button {
   list-style-image: url(chrome://browser/skin/menu-icons/customize.svg);
-  -moz-context-properties: fill;
 }
 
 #appMenu-find-button {
   list-style-image: url(chrome://browser/skin/menu-icons/find.svg);
-  -moz-context-properties: fill;
 }
 
 #appMenu-help-button {
   list-style-image: url(chrome://browser/skin/menu-icons/help.svg);
-  -moz-context-properties: fill;
 }
 
 #appMenu-cut-button {
   list-style-image: url(chrome://browser/skin/edit-cut.svg);
   -moz-context-properties: fill;
 }
 
 #appMenu-copy-button {
--- a/browser/themes/shared/sidebar.inc.css
+++ b/browser/themes/shared/sidebar.inc.css
@@ -3,17 +3,16 @@
  * 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/. */
 %endif
 
 #sidebar-box {
   --icon-fill: rgba(12, 12, 13, 0.8);
   --header-background-color: #F2F2F2;
   --header-background-color-hover: rgba(204, 204, 204, 0.6);
-  --title-font-size: 13px;
 }
 
 .sidebar-header,
 #sidebar-header {
   padding: 4px;
   background-color: var(--header-background-color);
   text-shadow: none;
 }
@@ -44,30 +43,28 @@
 @media (min-resolution: 2dppx) {
   .sidebar-throbber[loading="true"],
   #sidebar-throbber[loading="true"] {
     list-style-image: url("chrome://global/skin/icons/loading@2x.png");
     width: 16px;
   }
 }
 
-.sidebar-title,
 #sidebar-title {
   margin: 0;
   padding: 0;
   padding-inline-start: 8px;
   padding-inline-end: 4px;
   color: -moz-DialogText;
-  font-size: var(--title-font-size);
 }
 
 #sidebar-switcher-arrow {
   -moz-context-properties: fill;
   fill: var(--icon-fill);
-  list-style-image: url(chrome://browser/skin/sidebar/arrow-dropdown.svg);
+  list-style-image: url(chrome://browser/skin/arrow-dropdown.svg);
   width: 12px;
   height: 12px;
 }
 
 #sidebar-close {
   -moz-appearance: none;
   -moz-context-properties: fill;
   fill: var(--icon-fill);
@@ -117,9 +114,9 @@
   list-style-image: url(chrome://browser/skin/sidebar/history.svg);
 }
 
 #sidebar-switcher-tabs > .toolbarbutton-icon,
 #sidebar-box[sidebarcommand="viewTabsSidebar"] #sidebar-icon {
   -moz-context-properties: fill;
   fill: var(--icon-fill);
   list-style-image: url(chrome://browser/skin/sidebar/sync.svg);
-}
\ No newline at end of file
+}
--- a/browser/themes/shared/toolbarbuttons.inc.css
+++ b/browser/themes/shared/toolbarbuttons.inc.css
@@ -24,16 +24,21 @@
 
   /* icon width + border + horizontal padding (without the overlap from backbutton-urlbar-overlap) */
   --forwardbutton-width: 25px;
 
   --toolbarbutton-inner-padding: 3px;
 %endif
 }
 
+/* Larger buttons in touch mode */
+:root[uidensity=touch] {
+  --toolbarbutton-inner-padding: 9px;
+}
+
 toolbar:-moz-lwtheme {
 %ifndef MOZ_PHOTON_THEME
   --toolbarbutton-hover-background: rgba(255,255,255,.25);
   --toolbarbutton-active-background: rgba(70%,70%,70%,.25);
 %endif
 
   --toolbarbutton-hover-bordercolor: rgba(0,0,0,.2);
 
@@ -175,18 +180,23 @@ toolbarbutton.bookmark-item:not(.subview
   border-radius: var(--toolbarbutton-border-radius);
   transition-property: background-color, border-color, box-shadow;
   transition-duration: 150ms;
 }
 
 #nav-bar .toolbarbutton-1 > .toolbarbutton-icon,
 #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon,
 #nav-bar #bookmarks-menu-button[cui-areatype="toolbar"] > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
-  /* horizontal padding + border + actual icon width */
+%ifdef MOZ_PHOTON_THEME
+  /* horizontal padding + actual icon width */
+  max-width: calc(2 * var(--toolbarbutton-inner-padding) + 16px);
+%else
+  /* Before Photon horizontal padding is 7px, but --toolbarbutton-inner-padding is set to 3px */
   max-width: 32px;
+%endif
 }
 
 #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon:-moz-locale-dir(ltr),
 #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon:-moz-locale-dir(rtl) {
   border-top-right-radius: 0;
   border-bottom-right-radius: 0;
 }
 
@@ -199,34 +209,44 @@ toolbarbutton.bookmark-item:not(.subview
 #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
   border-inline-end-style: none;
 }
 
 #nav-bar .toolbarbutton-1 > .toolbarbutton-menu-dropmarker {
   display: none;
 }
 
+%ifndef MOZ_PHOTON_THEME
 #nav-bar #bookmarks-menu-button[cui-areatype="toolbar"] > .toolbarbutton-menubutton-button > .toolbarbutton-icon {
   /* horizontal padding + border + actual icon width */
   max-width: 31px;
 }
+%endif
 
 #nav-bar .toolbarbutton-1 > .toolbarbutton-menubutton-dropmarker > .dropmarker-icon {
   padding-top: calc(var(--toolbarbutton-inner-padding) + 6px);
   padding-bottom: calc(var(--toolbarbutton-inner-padding) + 6px);
 }
 
 #nav-bar .toolbarbutton-1 > .toolbarbutton-text {
   padding-top: var(--toolbarbutton-vertical-text-padding);
   padding-bottom: 0;
+%ifdef MOZ_PHOTON_THEME
+  /* To make the hover feedback line up with sibling buttons, it needs the same
+   * height as the button icons and the same vertical padding, but as a minimum,
+   * because otherwise an increase in text sizes would break things.
+   */
+  min-height: calc(16px + 2 * var(--toolbarbutton-inner-padding));
+%else
   /* To make the hover feedback line up with sibling buttons, it needs the same
    * height (16px) + padding (2 * 3px) + border (2 * 1px), but as a minimum
    * because otherwise an increase in text sizes would break things.
    */
   min-height: calc(18px + 2 * var(--toolbarbutton-inner-padding));
+%endif
 }
 
 #nav-bar .toolbaritem-combined-buttons {
   margin-left: 2px;
   margin-right: 2px;
 }
 
 #nav-bar .toolbaritem-combined-buttons > .toolbarbutton-1 {
@@ -337,53 +357,65 @@ toolbarbutton.bookmark-item[open="true"]
 }
 
 @conditionalForwardWithUrlbar@:not(:hover) > #forward-button[disabled] {
   /* when not hovered anymore, trigger a new transition to hide the forward button immediately */
   margin-left: calc(-0.01px - var(--forwardbutton-width) - var(--backbutton-urlbar-overlap));
 }
 %endif
 
-#back-button {
-  padding-top: 3px !important;
-  padding-bottom: 3px !important;
+:root:not([uidensity=compact]) #back-button {
+  padding-top: 3px;
+  padding-bottom: 3px;
   padding-inline-start: 5px !important;
   padding-inline-end: 0 !important;
   position: relative !important;
   z-index: 1 !important;
-  border-radius: 0 10000px 10000px 0 !important;
+  border-radius: 0 10000px 10000px 0;
 }
 
-#back-button:-moz-locale-dir(rtl) {
-  border-radius: 10000px 0 0 10000px !important;
+:root:not([uidensity=compact]) #back-button:-moz-locale-dir(rtl) {
+  border-radius: 10000px 0 0 10000px;
 }
 
 #back-button > menupopup {
   margin-top: -1px !important;
 }
 
-#back-button > .toolbarbutton-icon {
+:root:not([uidensity=compact]) #back-button > .toolbarbutton-icon {
 %ifdef MOZ_PHOTON_THEME
   background: var(--backbutton-background);
   border: 1px solid var(--backbutton-border-color);
   background-origin: padding-box;
   background-clip: padding-box;
 %endif
-  border-radius: 10000px !important;
-  padding: 7px !important;
+  border-radius: 10000px;
+  max-width: 32px;
+  padding: 7px;
+}
+
+:root[uidensity=touch] #back-button {
+  padding-top: 1px;
+  padding-bottom: 1px;
+}
+
+:root[uidensity=touch] #back-button > .toolbarbutton-icon {
+  max-width: 38px;
+  padding: 10px;
 }
 
 %ifdef MOZ_PHOTON_THEME
-#back-button:not([disabled]):hover > .toolbarbutton-icon {
+:root:not([uidensity=compact]) #back-button:not([disabled]):not([open]):hover > .toolbarbutton-icon {
   background: var(--backbutton-background) !important;
   box-shadow: 0 1px 6px hsla(0,0%,0%,.1);
   border-color: hsla(240,5%,5%,.35);
 }
 
-#back-button:not([disabled]):hover:active > .toolbarbutton-icon {
+:root:not([uidensity=compact]) #back-button[open] > .toolbarbutton-icon,
+:root:not([uidensity=compact]) #back-button:not([disabled]):hover:active > .toolbarbutton-icon {
   background: var(--toolbarbutton-active-background) !important;
   border-color: hsla(240,5%,5%,.40);
 }
 %endif
 
 /* bookmarks menu-button */
 
 #bookmarks-menu-button[cui-areatype="toolbar"] > .toolbarbutton-menubutton-dropmarker {
--- a/browser/themes/shared/urlbar-searchbar.inc.css
+++ b/browser/themes/shared/urlbar-searchbar.inc.css
@@ -32,16 +32,28 @@
 #urlbar:-moz-lwtheme[focused="true"],
 .searchbar-textbox:-moz-lwtheme:hover,
 .searchbar-textbox:-moz-lwtheme[focused="true"] {
   background-color: white;
 }
 
 %endif
 
+:root[uidensity=compact] #urlbar,
+:root[uidensity=compact] .searchbar-textbox {
+  min-height: 26px;
+  margin-top: 3px;
+  margin-bottom: 3px;
+}
+
+:root[uidensity=touch] #urlbar,
+:root[uidensity=touch] .searchbar-textbox {
+  min-height: 32px;
+}
+
 #urlbar-container {
   -moz-box-align: center;
 }
 
 #urlbar-search-splitter {
   /* The splitter width should equal the location and search bars' combined
      neighboring margin and border width. */
   min-width: 12px;
deleted file mode 100644
index 3cf9f163db0e67397ed290c9ececc87722d3ab04..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
deleted file mode 100644
index 8e1beaec5b822330ce39f01872d9face87378979..e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
GIT binary patch
literal 0
Hc$@<O00001
--- a/browser/themes/windows/jar.mn
+++ b/browser/themes/windows/jar.mn
@@ -41,18 +41,16 @@ browser.jar:
   skin/classic/browser/urlbar-popup-blocked.png
   skin/classic/browser/urlbar-history-dropmarker.png
   skin/classic/browser/urlbar-history-dropmarker@2x.png
   skin/classic/browser/urlbar-history-dropmarker-win7.png
   skin/classic/browser/urlbar-history-dropmarker-win7@2x.png
   skin/classic/browser/webRTC-indicator.css  (../shared/webRTC-indicator.css)
 * skin/classic/browser/controlcenter/panel.css                 (controlcenter/panel.css)
   skin/classic/browser/customizableui/background-noise-toolbar.png  (customizableui/background-noise-toolbar.png)
-  skin/classic/browser/customizableui/customize-titleBar-toggle.png  (customizableui/customize-titleBar-toggle.png)
-  skin/classic/browser/customizableui/customize-titleBar-toggle@2x.png  (customizableui/customize-titleBar-toggle@2x.png)
   skin/classic/browser/customizableui/customizeMode-gridTexture.png  (customizableui/customizeMode-gridTexture.png)
   skin/classic/browser/customizableui/customizeMode-separatorHorizontal.png  (customizableui/customizeMode-separatorHorizontal.png)
   skin/classic/browser/customizableui/customizeMode-separatorVertical.png  (customizableui/customizeMode-separatorVertical.png)
   skin/classic/browser/customizableui/menu-arrow.svg           (customizableui/menu-arrow.svg)
 * skin/classic/browser/customizableui/panelUI.css       (customizableui/panelUI.css)
 * skin/classic/browser/downloads/allDownloadsViewOverlay.css   (downloads/allDownloadsViewOverlay.css)
   skin/classic/browser/downloads/download-glow-menuPanel.png   (downloads/download-glow-menuPanel.png)
   skin/classic/browser/downloads/download-glow-menuPanel-win7.png   (downloads/download-glow-menuPanel-win7.png)
--- a/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/LightweightThemes.jsm
+++ b/browser/tools/mozscreenshots/mozscreenshots/extension/configurations/LightweightThemes.jsm
@@ -33,17 +33,16 @@ this.LightweightThemes = {
     },
 
     darkLWT: {
       applyConfig() {
         LightweightThemeManager.setLocalTheme({
           id:          "black",
           name:        "black",
           headerURL:   LightweightThemes._blackImageURL,
-          footerURL:   LightweightThemes._blackImageURL,
           textcolor:   "#eeeeee",
           accentcolor: "#111111",
         });
 
         // Wait for LWT listener
         return new Promise(resolve => {
           setTimeout(() => {
             resolve("darkLWT");
@@ -53,17 +52,16 @@ this.LightweightThemes = {
     },
 
     lightLWT: {
       applyConfig() {
         LightweightThemeManager.setLocalTheme({
           id:          "white",
           name:        "white",
           headerURL:   LightweightThemes._whiteImageURL,
-          footerURL:   LightweightThemes._whiteImageURL,
           textcolor:   "#111111",
           accentcolor: "#eeeeee",
         });
         // Wait for LWT listener
         return new Promise(resolve => {
           setTimeout(() => {
             resolve("lightLWT");
           }, 500);
--- a/build/autoconf/compiler-opts.m4
+++ b/build/autoconf/compiler-opts.m4
@@ -262,17 +262,17 @@ fi
 MOZ_ARG_ENABLE_BOOL(pie,
 [  --enable-pie           Enable Position Independent Executables],
     MOZ_PIE=1,
     MOZ_PIE= )
 
 if test "$GNU_CC$CLANG_CC" -a -n "$MOZ_PIE"; then
     AC_MSG_CHECKING([for PIE support])
     _SAVE_LDFLAGS=$LDFLAGS
-    LDFLAGS="$LDFLAGS -pie"
+    LDFLAGS="$LDFLAGS $DSO_PIC_CFLAGS -pie"
     AC_TRY_LINK(,,AC_MSG_RESULT([yes])
                   [MOZ_PROGRAM_LDFLAGS="$MOZ_PROGRAM_LDFLAGS -pie"],
                   AC_MSG_RESULT([no])
                   AC_MSG_ERROR([--enable-pie requires PIE support from the linker.]))
     LDFLAGS=$_SAVE_LDFLAGS
 fi
 
 AC_SUBST(MOZ_PROGRAM_LDFLAGS)
--- a/db/sqlite3/src/sqlite3.c
+++ b/db/sqlite3/src/sqlite3.c
@@ -1,11 +1,11 @@
 /******************************************************************************
 ** This file is an amalgamation of many separate C source files from SQLite
-** version 3.18.0.  By combining all the individual C code files into this
+** version 3.19.1.  By combining all the individual C code files into this
 ** single large file, the entire code can be compiled as a single translation
 ** unit.  This allows many compilers to do optimizations that would not be
 ** possible if the files were compiled separately.  Performance improvements
 ** of 5% or more are commonly seen when SQLite is compiled as a single
 ** translation unit.
 **
 ** This file is all you need to compile SQLite.  To use SQLite in other
 ** programs, you need this file and the "sqlite3.h" header file that defines
@@ -393,19 +393,19 @@ extern "C" {
 ** within its configuration management system.  ^The SQLITE_SOURCE_ID
 ** string contains the date and time of the check-in (UTC) and a SHA1
 ** or SHA3-256 hash of the entire source tree.
 **
 ** See also: [sqlite3_libversion()],
 ** [sqlite3_libversion_number()], [sqlite3_sourceid()],
 ** [sqlite_version()] and [sqlite_source_id()].
 */
-#define SQLITE_VERSION        "3.18.0"
-#define SQLITE_VERSION_NUMBER 3018000
-#define SQLITE_SOURCE_ID      "2017-03-28 18:48:43 424a0d380332858ee55bdebc4af3789f74e70a2b3ba1cf29d84b9b4bcf3e2e37"
+#define SQLITE_VERSION        "3.19.1"
+#define SQLITE_VERSION_NUMBER 3019001
+#define SQLITE_SOURCE_ID      "2017-05-24 13:08:33 f6d7b988f40217821a382bc298180e9e6794f3ed79a83c6ef5cae048989b3f86"
 
 /*
 ** CAPI3REF: Run-Time Library Version Numbers
 ** KEYWORDS: sqlite3_version sqlite3_sourceid
 **
 ** These interfaces provide the same information as the [SQLITE_VERSION],
 ** [SQLITE_VERSION_NUMBER], and [SQLITE_SOURCE_ID] C preprocessor macros
 ** but are associated with the library instead of the header file.  ^(Cautious
@@ -1129,17 +1129,17 @@ struct sqlite3_io_methods {
 ** windows [VFS] in order to provide robustness in the presence of
 ** anti-virus programs.  By default, the windows VFS will retry file read,
 ** file write, and file delete operations up to 10 times, with a delay
 ** of 25 milliseconds before the first retry and with the delay increasing
 ** by an additional 25 milliseconds with each subsequent retry.  This
 ** opcode allows these two values (10 retries and 25 milliseconds of delay)
 ** to be adjusted.  The values are changed for all database connections
 ** within the same process.  The argument is a pointer to an array of two
-** integers where the first integer i the new retry count and the second
+** integers where the first integer is the new retry count and the second
 ** integer is the delay.  If either integer is negative, then the setting
 ** is not changed but instead the prior value of that setting is written
 ** into the array entry, allowing the current retry settings to be
 ** interrogated.  The zDbName parameter is ignored.
 **
 ** <li>[[SQLITE_FCNTL_PERSIST_WAL]]
 ** ^The [SQLITE_FCNTL_PERSIST_WAL] opcode is used to set or query the
 ** persistent [WAL | Write Ahead Log] setting.  By default, the auxiliary
@@ -2483,19 +2483,16 @@ SQLITE_API int sqlite3_total_changes(sql
 ** that are started after the sqlite3_interrupt() call and before the 
 ** running statements reaches zero are interrupted as if they had been
 ** running prior to the sqlite3_interrupt() call.  ^New SQL statements
 ** that are started after the running statement count reaches zero are
 ** not effected by the sqlite3_interrupt().
 ** ^A call to sqlite3_interrupt(D) that occurs when there are no running
 ** SQL statements is a no-op and has no effect on SQL statements
 ** that are started after the sqlite3_interrupt() call returns.
-**
-** If the database connection closes while [sqlite3_interrupt()]
-** is running then bad things will likely happen.
 */
 SQLITE_API void sqlite3_interrupt(sqlite3*);
 
 /*
 ** CAPI3REF: Determine If An SQL Statement Is Complete
 **
 ** These routines are useful during command-line input to determine if the
 ** currently entered text seems to form a complete SQL statement or
@@ -2948,16 +2945,17 @@ SQLITE_API sqlite3_int64 sqlite3_memory_
 ** internally and without recourse to the [sqlite3_vfs] xRandomness
 ** method.
 */
 SQLITE_API void sqlite3_randomness(int N, void *P);
 
 /*
 ** CAPI3REF: Compile-Time Authorization Callbacks
 ** METHOD: sqlite3
+** KEYWORDS: {authorizer callback}
 **
 ** ^This routine registers an authorizer callback with a particular
 ** [database connection], supplied in the first argument.
 ** ^The authorizer callback is invoked as SQL statements are being compiled
 ** by [sqlite3_prepare()] or its variants [sqlite3_prepare_v2()],
 ** [sqlite3_prepare16()] and [sqlite3_prepare16_v2()].  ^At various
 ** points during the compilation process, as logic is being created
 ** to perform various actions, the authorizer callback is invoked to
@@ -2975,26 +2973,32 @@ SQLITE_API void sqlite3_randomness(int N
 ** [sqlite3_prepare_v2()] or equivalent call that triggered the
 ** authorizer will fail with an error message explaining that
 ** access is denied. 
 **
 ** ^The first parameter to the authorizer callback is a copy of the third
 ** parameter to the sqlite3_set_authorizer() interface. ^The second parameter
 ** to the callback is an integer [SQLITE_COPY | action code] that specifies
 ** the particular action to be authorized. ^The third through sixth parameters
-** to the callback are zero-terminated strings that contain additional
-** details about the action to be authorized.
+** to the callback are either NULL pointers or zero-terminated strings
+** that contain additional details about the action to be authorized.
+** Applications must always be prepared to encounter a NULL pointer in any
+** of the third through the sixth parameters of the authorization callback.
 **
 ** ^If the action code is [SQLITE_READ]
 ** and the callback returns [SQLITE_IGNORE] then the
 ** [prepared statement] statement is constructed to substitute
 ** a NULL value in place of the table column that would have
 ** been read if [SQLITE_OK] had been returned.  The [SQLITE_IGNORE]
 ** return can be used to deny an untrusted user access to individual
 ** columns of a table.
+** ^When a table is referenced by a [SELECT] but no column values are
+** extracted from that table (for example in a query like
+** "SELECT count(*) FROM tab") then the [SQLITE_READ] authorizer callback
+** is invoked once for that table with a column name that is an empty string.
 ** ^If the action code is [SQLITE_DELETE] and the callback returns
 ** [SQLITE_IGNORE] then the [DELETE] operation proceeds but the
 ** [truncate optimization] is disabled and all rows are deleted individually.
 **
 ** An authorizer is used when [sqlite3_prepare | preparing]
 ** SQL statements from an untrusted source, to ensure that the SQL statements
 ** do not try to access data they are not allowed to see, or that they do not
 ** try to execute malicious statements that damage the database.  For
@@ -3977,17 +3981,17 @@ SQLITE_API int sqlite3_stmt_busy(sqlite3
 ** implementation of [application-defined SQL functions] are protected.
 ** ^The sqlite3_value object returned by
 ** [sqlite3_column_value()] is unprotected.
 ** Unprotected sqlite3_value objects may only be used with
 ** [sqlite3_result_value()] and [sqlite3_bind_value()].
 ** The [sqlite3_value_blob | sqlite3_value_type()] family of
 ** interfaces require protected sqlite3_value objects.
 */
-typedef struct Mem sqlite3_value;
+typedef struct sqlite3_value sqlite3_value;
 
 /*
 ** CAPI3REF: SQL Function Context Object
 **
 ** The context in which an SQL function executes is stored in an
 ** sqlite3_context object.  ^A pointer to an sqlite3_context object
 ** is always first parameter to [application-defined SQL functions].
 ** The application-defined SQL function implementation will pass this
@@ -5031,20 +5035,21 @@ SQLITE_API sqlite3 *sqlite3_context_db_h
 ** some circumstances the associated metadata may be preserved.  An example
 ** of where this might be useful is in a regular-expression matching
 ** function. The compiled version of the regular expression can be stored as
 ** metadata associated with the pattern string.  
 ** Then as long as the pattern string remains the same,
 ** the compiled regular expression can be reused on multiple
 ** invocations of the same function.
 **
-** ^The sqlite3_get_auxdata() interface returns a pointer to the metadata
-** associated by the sqlite3_set_auxdata() function with the Nth argument
-** value to the application-defined function. ^If there is no metadata
-** associated with the function argument, this sqlite3_get_auxdata() interface
+** ^The sqlite3_get_auxdata(C,N) interface returns a pointer to the metadata
+** associated by the sqlite3_set_auxdata(C,N,P,X) function with the Nth argument
+** value to the application-defined function.  ^N is zero for the left-most
+** function argument.  ^If there is no metadata
+** associated with the function argument, the sqlite3_get_auxdata(C,N) interface
 ** returns a NULL pointer.
 **
 ** ^The sqlite3_set_auxdata(C,N,P,X) interface saves P as metadata for the N-th
 ** argument of the application-defined function.  ^Subsequent
 ** calls to sqlite3_get_auxdata(C,N) return P from the most recent
 ** sqlite3_set_auxdata(C,N,P,X) call if the metadata is still valid or
 ** NULL if the metadata has been discarded.
 ** ^After each call to sqlite3_set_auxdata(C,N,P,X) where X is not NULL,
@@ -5065,16 +5070,20 @@ SQLITE_API sqlite3 *sqlite3_context_db_h
 ** should be called near the end of the function implementation and the
 ** function implementation should not make any use of P after
 ** sqlite3_set_auxdata() has been called.
 **
 ** ^(In practice, metadata is preserved between function calls for
 ** function parameters that are compile-time constants, including literal
 ** values and [parameters] and expressions composed from the same.)^
 **
+** The value of the N parameter to these interfaces should be non-negative.
+** Future enhancements may make use of negative N values to define new
+** kinds of function caching behavior.
+**
 ** These routines must be called from the same thread in which
 ** the SQL function is running.
 */
 SQLITE_API void *sqlite3_get_auxdata(sqlite3_context*, int N);
 SQLITE_API void sqlite3_set_auxdata(sqlite3_context*, int N, void*, void (*)(void*));
 
 
 /*
@@ -9659,17 +9668,17 @@ typedef struct sqlite3_changegroup sqlit
 **
 ** Any number of calls to add() and output() may be made between the calls to
 ** new() and delete(), and in any order.
 **
 ** As well as the regular sqlite3changegroup_add() and 
 ** sqlite3changegroup_output() functions, also available are the streaming
 ** versions sqlite3changegroup_add_strm() and sqlite3changegroup_output_strm().
 */
-int sqlite3changegroup_new(sqlite3_changegroup **pp);
+SQLITE_API int sqlite3changegroup_new(sqlite3_changegroup **pp);
 
 /*
 ** CAPI3REF: Add A Changeset To A Changegroup
 **
 ** Add all changes within the changeset (or patchset) in buffer pData (size
 ** nData bytes) to the changegroup. 
 **
 ** If the buffer contains a patchset, then all prior calls to this function
@@ -9736,17 +9745,17 @@ int sqlite3changegroup_new(sqlite3_chang
 ** case, this function fails with SQLITE_SCHEMA. If the input changeset
 ** appears to be corrupt and the corruption is detected, SQLITE_CORRUPT is
 ** returned. Or, if an out-of-memory condition occurs during processing, this
 ** function returns SQLITE_NOMEM. In all cases, if an error occurs the
 ** final contents of the changegroup is undefined.
 **
 ** If no error occurs, SQLITE_OK is returned.
 */
-int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
+SQLITE_API int sqlite3changegroup_add(sqlite3_changegroup*, int nData, void *pData);
 
 /*
 ** CAPI3REF: Obtain A Composite Changeset From A Changegroup
 **
 ** Obtain a buffer containing a changeset (or patchset) representing the
 ** current contents of the changegroup. If the inputs to the changegroup
 ** were themselves changesets, the output is a changeset. Or, if the
 ** inputs were patchsets, the output is also a patchset.
@@ -9762,26 +9771,26 @@ int sqlite3changegroup_add(sqlite3_chang
 **
 ** If an error occurs, an SQLite error code is returned and the output
 ** variables (*pnData) and (*ppData) are set to 0. Otherwise, SQLITE_OK
 ** is returned and the output variables are set to the size of and a 
 ** pointer to the output buffer, respectively. In this case it is the
 ** responsibility of the caller to eventually free the buffer using a
 ** call to sqlite3_free().
 */
-int sqlite3changegroup_output(
+SQLITE_API int sqlite3changegroup_output(
   sqlite3_changegroup*,
   int *pnData,                    /* OUT: Size of output buffer in bytes */
   void **ppData                   /* OUT: Pointer to output buffer */
 );
 
 /*
 ** CAPI3REF: Delete A Changegroup Object
 */
-void sqlite3changegroup_delete(sqlite3_changegroup*);
+SQLITE_API void sqlite3changegroup_delete(sqlite3_changegroup*);
 
 /*
 ** CAPI3REF: Apply A Changeset To A Database
 **
 ** Apply a changeset to a database. This function attempts to update the
 ** "main" database attached to handle db with the changes found in the
 ** changeset passed via the second and third arguments.
 **
@@ -10160,21 +10169,21 @@ SQLITE_API int sqlite3session_changeset_
   int (*xOutput)(void *pOut, const void *pData, int nData),
   void *pOut
 );
 SQLITE_API int sqlite3session_patchset_strm(
   sqlite3_session *pSession,
   int (*xOutput)(void *pOut, const void *pData, int nData),
   void *pOut
 );
-int sqlite3changegroup_add_strm(sqlite3_changegroup*, 
+SQLITE_API int sqlite3changegroup_add_strm(sqlite3_changegroup*, 
     int (*xInput)(void *pIn, void *pData, int *pnData),
     void *pIn
 );
-int sqlite3changegroup_output_strm(sqlite3_changegroup*,
+SQLITE_API int sqlite3changegroup_output_strm(sqlite3_changegroup*,
     int (*xOutput)(void *pOut, const void *pData, int nData), 
     void *pOut
 );
 
 
 /*
 ** Make sure we can call this stuff from C++.
 */
@@ -11448,86 +11457,86 @@ SQLITE_PRIVATE void sqlite3HashClear(Has
 #define TK_NOT                             19
 #define TK_EXISTS                          20
 #define TK_TEMP                            21
 #define TK_LP                              22
 #define TK_RP                              23
 #define TK_AS                              24
 #define TK_WITHOUT                         25
 #define TK_COMMA                           26
-#define TK_OR                              27
-#define TK_AND                             28
-#define TK_IS                              29
-#define TK_MATCH                           30
-#define TK_LIKE_KW                         31
-#define TK_BETWEEN                         32
-#define TK_IN                              33
-#define TK_ISNULL                          34
-#define TK_NOTNULL                         35
-#define TK_NE                              36
-#define TK_EQ                              37
-#define TK_GT                              38
-#define TK_LE                              39
-#define TK_LT                              40
-#define TK_GE                              41
-#define TK_ESCAPE                          42
-#define TK_BITAND                          43
-#define TK_BITOR                           44
-#define TK_LSHIFT                          45
-#define TK_RSHIFT                          46
-#define TK_PLUS                            47
-#define TK_MINUS                           48
-#define TK_STAR                            49
-#define TK_SLASH                           50
-#define TK_REM                             51
-#define TK_CONCAT                          52
-#define TK_COLLATE                         53
-#define TK_BITNOT                          54
-#define TK_ID                              55
-#define TK_INDEXED                         56
-#define TK_ABORT                           57
-#define TK_ACTION                          58
-#define TK_AFTER                           59
-#define TK_ANALYZE                         60
-#define TK_ASC                             61
-#define TK_ATTACH                          62
-#define TK_BEFORE                          63
-#define TK_BY                              64
-#define TK_CASCADE                         65
-#define TK_CAST                            66
-#define TK_COLUMNKW                        67
-#define TK_CONFLICT                        68
-#define TK_DATABASE                        69
-#define TK_DESC                            70
-#define TK_DETACH                          71
-#define TK_EACH                            72
-#define TK_FAIL                            73
-#define TK_FOR                             74
-#define TK_IGNORE                          75
-#define TK_INITIALLY                       76
-#define TK_INSTEAD                         77
-#define TK_NO                              78
-#define TK_KEY                             79
-#define TK_OF                              80
-#define TK_OFFSET                          81
-#define TK_PRAGMA                          82
-#define TK_RAISE                           83
-#define TK_RECURSIVE                       84
-#define TK_REPLACE                         85
-#define TK_RESTRICT                        86
-#define TK_ROW                             87
-#define TK_TRIGGER                         88
-#define TK_VACUUM                          89
-#define TK_VIEW                            90
-#define TK_VIRTUAL                         91
-#define TK_WITH                            92
-#define TK_REINDEX                         93
-#define TK_RENAME                          94
-#define TK_CTIME_KW                        95
-#define TK_ANY                             96
+#define TK_ID                              27
+#define TK_ABORT                           28
+#define TK_ACTION                          29
+#define TK_AFTER                           30
+#define TK_ANALYZE                         31
+#define TK_ASC                             32
+#define TK_ATTACH                          33
+#define TK_BEFORE                          34
+#define TK_BY                              35
+#define TK_CASCADE                         36
+#define TK_CAST                            37
+#define TK_COLUMNKW                        38
+#define TK_CONFLICT                        39
+#define TK_DATABASE                        40
+#define TK_DESC                            41
+#define TK_DETACH                          42
+#define TK_EACH                            43
+#define TK_FAIL                            44
+#define TK_FOR                             45
+#define TK_IGNORE                          46
+#define TK_INITIALLY                       47
+#define TK_INSTEAD                         48
+#define TK_LIKE_KW                         49
+#define TK_MATCH                           50
+#define TK_NO                              51
+#define TK_KEY                             52
+#define TK_OF                              53
+#define TK_OFFSET                          54
+#define TK_PRAGMA                          55
+#define TK_RAISE                           56
+#define TK_RECURSIVE                       57
+#define TK_REPLACE                         58
+#define TK_RESTRICT                        59
+#define TK_ROW                             60
+#define TK_TRIGGER                         61
+#define TK_VACUUM                          62
+#define TK_VIEW                            63
+#define TK_VIRTUAL                         64
+#define TK_WITH                            65
+#define TK_REINDEX                         66
+#define TK_RENAME                          67
+#define TK_CTIME_KW                        68
+#define TK_ANY                             69
+#define TK_OR                              70
+#define TK_AND                             71
+#define TK_IS                              72
+#define TK_BETWEEN                         73
+#define TK_IN                              74
+#define TK_ISNULL                          75
+#define TK_NOTNULL                         76
+#define TK_NE                              77
+#define TK_EQ                              78
+#define TK_GT                              79
+#define TK_LE                              80
+#define TK_LT                              81
+#define TK_GE                              82
+#define TK_ESCAPE                          83
+#define TK_BITAND                          84
+#define TK_BITOR                           85
+#define TK_LSHIFT                          86
+#define TK_RSHIFT                          87
+#define TK_PLUS                            88
+#define TK_MINUS                           89
+#define TK_STAR                            90
+#define TK_SLASH                           91
+#define TK_REM                             92
+#define TK_CONCAT                          93
+#define TK_COLLATE                         94
+#define TK_BITNOT                          95
+#define TK_INDEXED                         96
 #define TK_STRING                          97
 #define TK_JOIN_KW                         98
 #define TK_CONSTRAINT                      99
 #define TK_DEFAULT                        100
 #define TK_NULL                           101
 #define TK_PRIMARY                        102
 #define TK_UNIQUE                         103
 #define TK_CHECK                          104
@@ -11581,20 +11590,21 @@ SQLITE_PRIVATE void sqlite3HashClear(Has
 #define TK_COLUMN                         152
 #define TK_AGG_FUNCTION                   153
 #define TK_AGG_COLUMN                     154
 #define TK_UMINUS                         155
 #define TK_UPLUS                          156
 #define TK_REGISTER                       157
 #define TK_VECTOR                         158
 #define TK_SELECT_COLUMN                  159
-#define TK_ASTERISK                       160
-#define TK_SPAN                           161
-#define TK_SPACE                          162
-#define TK_ILLEGAL                        163
+#define TK_IF_NULL_ROW                    160
+#define TK_ASTERISK                       161
+#define TK_SPAN                           162
+#define TK_SPACE                          163
+#define TK_ILLEGAL                        164
 
 /* The token codes above must all fit in 8 bits */
 #define TKFLG_MASK           0xff  
 
 /* Flags that can be added to a token code when it is not
 ** being stored in a u8: */
 #define TKFLG_DONTFOLD       0x100  /* Omit constant folding optimizations */
 
@@ -12455,17 +12465,17 @@ SQLITE_PRIVATE int sqlite3BtreeDelete(Bt
 ** the information into this object helps to keep the interface more 
 ** organized and understandable, and it also helps the resulting code to
 ** run a little faster by using fewer registers for parameter passing.
 */
 struct BtreePayload {
   const void *pKey;       /* Key content for indexes.  NULL for tables */
   sqlite3_int64 nKey;     /* Size of pKey for indexes.  PRIMARY KEY for tabs */
   const void *pData;      /* Data for tables.  NULL for indexes */
-  struct Mem *aMem;       /* First of nMem value in the unpacked pKey */
+  sqlite3_value *aMem;    /* First of nMem value in the unpacked pKey */
   u16 nMem;               /* Number of aMem[] value.  Might be zero */
   int nData;              /* Size of pData.  0 if none. */
   int nZero;              /* Extra zero data appended after pData,nData */
 };
 
 SQLITE_PRIVATE int sqlite3BtreeInsert(BtCursor*, const BtreePayload *pPayload,
                        int flags, int seekResult);
 SQLITE_PRIVATE int sqlite3BtreeFirst(BtCursor*, int *pRes);
@@ -12585,17 +12595,17 @@ SQLITE_PRIVATE   int sqlite3SchemaMutexH
 ** of this structure.
 */
 typedef struct Vdbe Vdbe;
 
 /*
 ** The names of the following types declared in vdbeInt.h are required
 ** for the VdbeOp definition.
 */
-typedef struct Mem Mem;
+typedef struct sqlite3_value Mem;
 typedef struct SubProgram SubProgram;
 
 /*
 ** A single instruction of the virtual machine has an opcode
 ** and as many as three operands.  The instruction is recorded
 ** as an instance of the following structure:
 */
 struct VdbeOp {
@@ -12745,198 +12755,200 @@ typedef struct VdbeOpList VdbeOpList;
 #define OP_InitCoroutine  15
 #define OP_Yield          16
 #define OP_MustBeInt      17
 #define OP_Jump           18
 #define OP_Not            19 /* same as TK_NOT, synopsis: r[P2]= !r[P1]    */
 #define OP_Once           20
 #define OP_If             21
 #define OP_IfNot          22
-#define OP_SeekLT         23 /* synopsis: key=r[P3@P4]                     */
-#define OP_SeekLE         24 /* synopsis: key=r[P3@P4]                     */
-#define OP_SeekGE         25 /* synopsis: key=r[P3@P4]                     */
-#define OP_SeekGT         26 /* synopsis: key=r[P3@P4]                     */
-#define OP_Or             27 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
-#define OP_And            28 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
-#define OP_NoConflict     29 /* synopsis: key=r[P3@P4]                     */
-#define OP_NotFound       30 /* synopsis: key=r[P3@P4]                     */
-#define OP_Found          31 /* synopsis: key=r[P3@P4]                     */
-#define OP_SeekRowid      32 /* synopsis: intkey=r[P3]                     */
-#define OP_NotExists      33 /* synopsis: intkey=r[P3]                     */
-#define OP_IsNull         34 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
-#define OP_NotNull        35 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
-#define OP_Ne             36 /* same as TK_NE, synopsis: IF r[P3]!=r[P1]   */
-#define OP_Eq             37 /* same as TK_EQ, synopsis: IF r[P3]==r[P1]   */
-#define OP_Gt             38 /* same as TK_GT, synopsis: IF r[P3]>r[P1]    */
-#define OP_Le             39 /* same as TK_LE, synopsis: IF r[P3]<=r[P1]   */
-#define OP_Lt             40 /* same as TK_LT, synopsis: IF r[P3]<r[P1]    */
-#define OP_Ge             41 /* same as TK_GE, synopsis: IF r[P3]>=r[P1]   */
-#define OP_ElseNotEq      42 /* same as TK_ESCAPE                          */
-#define OP_BitAnd         43 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
-#define OP_BitOr          44 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
-#define OP_ShiftLeft      45 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
-#define OP_ShiftRight     46 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
-#define OP_Add            47 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
-#define OP_Subtract       48 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
-#define OP_Multiply       49 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
-#define OP_Divide         50 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
-#define OP_Remainder      51 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
-#define OP_Concat         52 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
-#define OP_Last           53
-#define OP_BitNot         54 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
-#define OP_IfSmaller      55
-#define OP_SorterSort     56
-#define OP_Sort           57
-#define OP_Rewind         58
-#define OP_IdxLE          59 /* synopsis: key=r[P3@P4]                     */
-#define OP_IdxGT          60 /* synopsis: key=r[P3@P4]                     */
-#define OP_IdxLT          61 /* synopsis: key=r[P3@P4]                     */
-#define OP_IdxGE          62 /* synopsis: key=r[P3@P4]                     */
-#define OP_RowSetRead     63 /* synopsis: r[P3]=rowset(P1)                 */
-#define OP_RowSetTest     64 /* synopsis: if r[P3] in rowset(P1) goto P2   */
-#define OP_Program        65
-#define OP_FkIfZero       66 /* synopsis: if fkctr[P1]==0 goto P2          */
-#define OP_IfPos          67 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
-#define OP_IfNotZero      68 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
-#define OP_DecrJumpZero   69 /* synopsis: if (--r[P1])==0 goto P2          */
-#define OP_IncrVacuum     70
-#define OP_VNext          71
-#define OP_Init           72 /* synopsis: Start at P2                      */
-#define OP_Return         73
-#define OP_EndCoroutine   74
-#define OP_HaltIfNull     75 /* synopsis: if r[P3]=null halt               */
-#define OP_Halt           76
-#define OP_Integer        77 /* synopsis: r[P2]=P1                         */
-#define OP_Int64          78 /* synopsis: r[P2]=P4                         */
-#define OP_String         79 /* synopsis: r[P2]='P4' (len=P1)              */
-#define OP_Null           80 /* synopsis: r[P2..P3]=NULL                   */
-#define OP_SoftNull       81 /* synopsis: r[P1]=NULL                       */
-#define OP_Blob           82 /* synopsis: r[P2]=P4 (len=P1)                */
-#define OP_Variable       83 /* synopsis: r[P2]=parameter(P1,P4)           */
-#define OP_Move           84 /* synopsis: r[P2@P3]=r[P1@P3]                */
-#define OP_Copy           85 /* synopsis: r[P2@P3+1]=r[P1@P3+1]            */
-#define OP_SCopy          86 /* synopsis: r[P2]=r[P1]                      */
-#define OP_IntCopy        87 /* synopsis: r[P2]=r[P1]                      */
-#define OP_ResultRow      88 /* synopsis: output=r[P1@P2]                  */
-#define OP_CollSeq        89
-#define OP_Function0      90 /* synopsis: r[P3]=func(r[P2@P5])             */
-#define OP_Function       91 /* synopsis: r[P3]=func(r[P2@P5])             */
-#define OP_AddImm         92 /* synopsis: r[P1]=r[P1]+P2                   */
-#define OP_RealAffinity   93
+#define OP_IfNullRow      23 /* synopsis: if P1.nullRow then r[P3]=NULL, goto P2 */
+#define OP_SeekLT         24 /* synopsis: key=r[P3@P4]                     */
+#define OP_SeekLE         25 /* synopsis: key=r[P3@P4]                     */
+#define OP_SeekGE         26 /* synopsis: key=r[P3@P4]                     */
+#define OP_SeekGT         27 /* synopsis: key=r[P3@P4]                     */
+#define OP_NoConflict     28 /* synopsis: key=r[P3@P4]                     */
+#define OP_NotFound       29 /* synopsis: key=r[P3@P4]                     */
+#define OP_Found          30 /* synopsis: key=r[P3@P4]                     */
+#define OP_SeekRowid      31 /* synopsis: intkey=r[P3]                     */
+#define OP_NotExists      32 /* synopsis: intkey=r[P3]                     */
+#define OP_Last           33
+#define OP_IfSmaller      34
+#define OP_SorterSort     35
+#define OP_Sort           36
+#define OP_Rewind         37
+#define OP_IdxLE          38 /* synopsis: key=r[P3@P4]                     */
+#define OP_IdxGT          39 /* synopsis: key=r[P3@P4]                     */
+#define OP_IdxLT          40 /* synopsis: key=r[P3@P4]                     */
+#define OP_IdxGE          41 /* synopsis: key=r[P3@P4]                     */
+#define OP_RowSetRead     42 /* synopsis: r[P3]=rowset(P1)                 */
+#define OP_RowSetTest     43 /* synopsis: if r[P3] in rowset(P1) goto P2   */
+#define OP_Program        44
+#define OP_FkIfZero       45 /* synopsis: if fkctr[P1]==0 goto P2          */
+#define OP_IfPos          46 /* synopsis: if r[P1]>0 then r[P1]-=P3, goto P2 */
+#define OP_IfNotZero      47 /* synopsis: if r[P1]!=0 then r[P1]--, goto P2 */
+#define OP_DecrJumpZero   48 /* synopsis: if (--r[P1])==0 goto P2          */
+#define OP_IncrVacuum     49
+#define OP_VNext          50
+#define OP_Init           51 /* synopsis: Start at P2                      */
+#define OP_Return         52
+#define OP_EndCoroutine   53
+#define OP_HaltIfNull     54 /* synopsis: if r[P3]=null halt               */
+#define OP_Halt           55
+#define OP_Integer        56 /* synopsis: r[P2]=P1                         */
+#define OP_Int64          57 /* synopsis: r[P2]=P4                         */
+#define OP_String         58 /* synopsis: r[P2]='P4' (len=P1)              */
+#define OP_Null           59 /* synopsis: r[P2..P3]=NULL                   */
+#define OP_SoftNull       60 /* synopsis: r[P1]=NULL                       */
+#define OP_Blob           61 /* synopsis: r[P2]=P4 (len=P1)                */
+#define OP_Variable       62 /* synopsis: r[P2]=parameter(P1,P4)           */
+#define OP_Move           63 /* synopsis: r[P2@P3]=r[P1@P3]                */
+#define OP_Copy           64 /* synopsis: r[P2@P3+1]=r[P1@P3+1]            */
+#define OP_SCopy          65 /* synopsis: r[P2]=r[P1]                      */
+#define OP_IntCopy        66 /* synopsis: r[P2]=r[P1]                      */
+#define OP_ResultRow      67 /* synopsis: output=r[P1@P2]                  */
+#define OP_CollSeq        68
+#define OP_Function0      69 /* synopsis: r[P3]=func(r[P2@P5])             */
+#define OP_Or             70 /* same as TK_OR, synopsis: r[P3]=(r[P1] || r[P2]) */
+#define OP_And            71 /* same as TK_AND, synopsis: r[P3]=(r[P1] && r[P2]) */
+#define OP_Function       72 /* synopsis: r[P3]=func(r[P2@P5])             */
+#define OP_AddImm         73 /* synopsis: r[P1]=r[P1]+P2                   */
+#define OP_RealAffinity   74
+#define OP_IsNull         75 /* same as TK_ISNULL, synopsis: if r[P1]==NULL goto P2 */
+#define OP_NotNull        76 /* same as TK_NOTNULL, synopsis: if r[P1]!=NULL goto P2 */
+#define OP_Ne             77 /* same as TK_NE, synopsis: IF r[P3]!=r[P1]   */
+#define OP_Eq             78 /* same as TK_EQ, synopsis: IF r[P3]==r[P1]   */
+#define OP_Gt             79 /* same as TK_GT, synopsis: IF r[P3]>r[P1]    */
+#define OP_Le             80 /* same as TK_LE, synopsis: IF r[P3]<=r[P1]   */
+#define OP_Lt             81 /* same as TK_LT, synopsis: IF r[P3]<r[P1]    */
+#define OP_Ge             82 /* same as TK_GE, synopsis: IF r[P3]>=r[P1]   */
+#define OP_ElseNotEq      83 /* same as TK_ESCAPE                          */
+#define OP_BitAnd         84 /* same as TK_BITAND, synopsis: r[P3]=r[P1]&r[P2] */
+#define OP_BitOr          85 /* same as TK_BITOR, synopsis: r[P3]=r[P1]|r[P2] */
+#define OP_ShiftLeft      86 /* same as TK_LSHIFT, synopsis: r[P3]=r[P2]<<r[P1] */
+#define OP_ShiftRight     87 /* same as TK_RSHIFT, synopsis: r[P3]=r[P2]>>r[P1] */
+#define OP_Add            88 /* same as TK_PLUS, synopsis: r[P3]=r[P1]+r[P2] */
+#define OP_Subtract       89 /* same as TK_MINUS, synopsis: r[P3]=r[P2]-r[P1] */
+#define OP_Multiply       90 /* same as TK_STAR, synopsis: r[P3]=r[P1]*r[P2] */
+#define OP_Divide         91 /* same as TK_SLASH, synopsis: r[P3]=r[P2]/r[P1] */
+#define OP_Remainder      92 /* same as TK_REM, synopsis: r[P3]=r[P2]%r[P1] */
+#define OP_Concat         93 /* same as TK_CONCAT, synopsis: r[P3]=r[P2]+r[P1] */
 #define OP_Cast           94 /* synopsis: affinity(r[P1])                  */
-#define OP_Permutation    95
-#define OP_Compare        96 /* synopsis: r[P1@P3] <-> r[P2@P3]            */
+#define OP_BitNot         95 /* same as TK_BITNOT, synopsis: r[P1]= ~r[P1] */
+#define OP_Permutation    96
 #define OP_String8        97 /* same as TK_STRING, synopsis: r[P2]='P4'    */
-#define OP_Column         98 /* synopsis: r[P3]=PX                         */
-#define OP_Affinity       99 /* synopsis: affinity(r[P1@P2])               */
-#define OP_MakeRecord    100 /* synopsis: r[P3]=mkrec(r[P1@P2])            */
-#define OP_Count         101 /* synopsis: r[P2]=count()                    */
-#define OP_ReadCookie    102
-#define OP_SetCookie     103
-#define OP_ReopenIdx     104 /* synopsis: root=P2 iDb=P3                   */
-#define OP_OpenRead      105 /* synopsis: root=P2 iDb=P3                   */
-#define OP_OpenWrite     106 /* synopsis: root=P2 iDb=P3                   */
-#define OP_OpenAutoindex 107 /* synopsis: nColumn=P2                       */
-#define OP_OpenEphemeral 108 /* synopsis: nColumn=P2                       */
-#define OP_SorterOpen    109
-#define OP_SequenceTest  110 /* synopsis: if( cursor[P1].ctr++ ) pc = P2   */
-#define OP_OpenPseudo    111 /* synopsis: P3 columns in r[P2]              */
-#define OP_Close         112
-#define OP_ColumnsUsed   113
-#define OP_Sequence      114 /* synopsis: r[P2]=cursor[P1].ctr++           */
-#define OP_NewRowid      115 /* synopsis: r[P2]=rowid                      */
-#define OP_Insert        116 /* synopsis: intkey=r[P3] data=r[P2]          */
-#define OP_InsertInt     117 /* synopsis: intkey=P3 data=r[P2]             */
-#define OP_Delete        118
-#define OP_ResetCount    119
-#define OP_SorterCompare 120 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
-#define OP_SorterData    121 /* synopsis: r[P2]=data                       */
-#define OP_RowData       122 /* synopsis: r[P2]=data                       */
-#define OP_Rowid         123 /* synopsis: r[P2]=rowid                      */
-#define OP_NullRow       124
-#define OP_SorterInsert  125 /* synopsis: key=r[P2]                        */
-#define OP_IdxInsert     126 /* synopsis: key=r[P2]                        */
-#define OP_IdxDelete     127 /* synopsis: key=r[P2@P3]                     */
-#define OP_Seek          128 /* synopsis: Move P3 to P1.rowid              */
-#define OP_IdxRowid      129 /* synopsis: r[P2]=rowid                      */
-#define OP_Destroy       130
-#define OP_Clear         131
+#define OP_Compare        98 /* synopsis: r[P1@P3] <-> r[P2@P3]            */
+#define OP_Column         99 /* synopsis: r[P3]=PX                         */
+#define OP_Affinity      100 /* synopsis: affinity(r[P1@P2])               */
+#define OP_MakeRecord    101 /* synopsis: r[P3]=mkrec(r[P1@P2])            */
+#define OP_Count         102 /* synopsis: r[P2]=count()                    */
+#define OP_ReadCookie    103
+#define OP_SetCookie     104
+#define OP_ReopenIdx     105 /* synopsis: root=P2 iDb=P3                   */
+#define OP_OpenRead      106 /* synopsis: root=P2 iDb=P3                   */
+#define OP_OpenWrite     107 /* synopsis: root=P2 iDb=P3                   */
+#define OP_OpenDup       108
+#define OP_OpenAutoindex 109 /* synopsis: nColumn=P2                       */
+#define OP_OpenEphemeral 110 /* synopsis: nColumn=P2                       */
+#define OP_SorterOpen    111
+#define OP_SequenceTest  112 /* synopsis: if( cursor[P1].ctr++ ) pc = P2   */
+#define OP_OpenPseudo    113 /* synopsis: P3 columns in r[P2]              */
+#define OP_Close         114
+#define OP_ColumnsUsed   115
+#define OP_Sequence      116 /* synopsis: r[P2]=cursor[P1].ctr++           */
+#define OP_NewRowid      117 /* synopsis: r[P2]=rowid                      */
+#define OP_Insert        118 /* synopsis: intkey=r[P3] data=r[P2]          */
+#define OP_InsertInt     119 /* synopsis: intkey=P3 data=r[P2]             */
+#define OP_Delete        120
+#define OP_ResetCount    121
+#define OP_SorterCompare 122 /* synopsis: if key(P1)!=trim(r[P3],P4) goto P2 */
+#define OP_SorterData    123 /* synopsis: r[P2]=data                       */
+#define OP_RowData       124 /* synopsis: r[P2]=data                       */
+#define OP_Rowid         125 /* synopsis: r[P2]=rowid                      */
+#define OP_NullRow       126
+#define OP_SorterInsert  127 /* synopsis: key=r[P2]                        */
+#define OP_IdxInsert     128 /* synopsis: key=r[P2]                        */
+#define OP_IdxDelete     129 /* synopsis: key=r[P2@P3]                     */
+#define OP_Seek          130 /* synopsis: Move P3 to P1.rowid              */
+#define OP_IdxRowid      131 /* synopsis: r[P2]=rowid                      */
 #define OP_Real          132 /* same as TK_FLOAT, synopsis: r[P2]=P4       */
-#define OP_ResetSorter   133
-#define OP_CreateIndex   134 /* synopsis: r[P2]=root iDb=P1                */
-#define OP_CreateTable   135 /* synopsis: r[P2]=root iDb=P1                */
-#define OP_SqlExec       136
-#define OP_ParseSchema   137
-#define OP_LoadAnalysis  138
-#define OP_DropTable     139
-#define OP_DropIndex     140
-#define OP_DropTrigger   141
-#define OP_IntegrityCk   142
-#define OP_RowSetAdd     143 /* synopsis: rowset(P1)=r[P2]                 */
-#define OP_Param         144
-#define OP_FkCounter     145 /* synopsis: fkctr[P1]+=P2                    */
-#define OP_MemMax        146 /* synopsis: r[P1]=max(r[P1],r[P2])           */
-#define OP_OffsetLimit   147 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
-#define OP_AggStep0      148 /* synopsis: accum=r[P3] step(r[P2@P5])       */
-#define OP_AggStep       149 /* synopsis: accum=r[P3] step(r[P2@P5])       */
-#define OP_AggFinal      150 /* synopsis: accum=r[P1] N=P2                 */
-#define OP_Expire        151
-#define OP_TableLock     152 /* synopsis: iDb=P1 root=P2 write=P3          */
-#define OP_VBegin        153
-#define OP_VCreate       154
-#define OP_VDestroy      155
-#define OP_VOpen         156
-#define OP_VColumn       157 /* synopsis: r[P3]=vcolumn(P2)                */
-#define OP_VRename       158
-#define OP_Pagecount     159
-#define OP_MaxPgcnt      160
-#define OP_CursorHint    161
-#define OP_Noop          162
-#define OP_Explain       163
+#define OP_Destroy       133
+#define OP_Clear         134
+#define OP_ResetSorter   135
+#define OP_CreateIndex   136 /* synopsis: r[P2]=root iDb=P1                */
+#define OP_CreateTable   137 /* synopsis: r[P2]=root iDb=P1                */
+#define OP_SqlExec       138
+#define OP_ParseSchema   139
+#define OP_LoadAnalysis  140
+#define OP_DropTable     141
+#define OP_DropIndex     142
+#define OP_DropTrigger   143
+#define OP_IntegrityCk   144
+#define OP_RowSetAdd     145 /* synopsis: rowset(P1)=r[P2]                 */
+#define OP_Param         146
+#define OP_FkCounter     147 /* synopsis: fkctr[P1]+=P2                    */
+#define OP_MemMax        148 /* synopsis: r[P1]=max(r[P1],r[P2])           */
+#define OP_OffsetLimit   149 /* synopsis: if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1) */
+#define OP_AggStep0      150 /* synopsis: accum=r[P3] step(r[P2@P5])       */
+#define OP_AggStep       151 /* synopsis: accum=r[P3] step(r[P2@P5])       */
+#define OP_AggFinal      152 /* synopsis: accum=r[P1] N=P2                 */
+#define OP_Expire        153
+#define OP_TableLock     154 /* synopsis: iDb=P1 root=P2 write=P3          */
+#define OP_VBegin        155
+#define OP_VCreate       156
+#define OP_VDestroy      157
+#define OP_VOpen         158
+#define OP_VColumn       159 /* synopsis: r[P3]=vcolumn(P2)                */
+#define OP_VRename       160
+#define OP_Pagecount     161
+#define OP_MaxPgcnt      162
+#define OP_CursorHint    163
+#define OP_Noop          164
+#define OP_Explain       165
 
 /* Properties such as "out2" or "jump" that are specified in
 ** comments following the "case" for each opcode in the vdbe.c
 ** are encoded into bitvectors as follows:
 */
 #define OPFLG_JUMP        0x01  /* jump:  P2 holds jmp target */
 #define OPFLG_IN1         0x02  /* in1:   P1 is an input */
 #define OPFLG_IN2         0x04  /* in2:   P2 is an input */
 #define OPFLG_IN3         0x08  /* in3:   P3 is an input */
 #define OPFLG_OUT2        0x10  /* out2:  P2 is an output */
 #define OPFLG_OUT3        0x20  /* out3:  P3 is an output */
 #define OPFLG_INITIALIZER {\
 /*   0 */ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,\
 /*   8 */ 0x00, 0x10, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,\
-/*  16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x09,\
-/*  24 */ 0x09, 0x09, 0x09, 0x26, 0x26, 0x09, 0x09, 0x09,\
-/*  32 */ 0x09, 0x09, 0x03, 0x03, 0x0b, 0x0b, 0x0b, 0x0b,\
-/*  40 */ 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26, 0x26,\
-/*  48 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x01, 0x12, 0x01,\
-/*  56 */ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x23,\
-/*  64 */ 0x0b, 0x01, 0x01, 0x03, 0x03, 0x03, 0x01, 0x01,\
-/*  72 */ 0x01, 0x02, 0x02, 0x08, 0x00, 0x10, 0x10, 0x10,\
-/*  80 */ 0x10, 0x00, 0x10, 0x10, 0x00, 0x00, 0x10, 0x10,\
-/*  88 */ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x02, 0x00,\
-/*  96 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00,\
+/*  16 */ 0x03, 0x03, 0x01, 0x12, 0x01, 0x03, 0x03, 0x01,\
+/*  24 */ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,\
+/*  32 */ 0x09, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,\
+/*  40 */ 0x01, 0x01, 0x23, 0x0b, 0x01, 0x01, 0x03, 0x03,\
+/*  48 */ 0x03, 0x01, 0x01, 0x01, 0x02, 0x02, 0x08, 0x00,\
+/*  56 */ 0x10, 0x10, 0x10, 0x10, 0x00, 0x10, 0x10, 0x00,\
+/*  64 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x26, 0x26,\
+/*  72 */ 0x00, 0x02, 0x02, 0x03, 0x03, 0x0b, 0x0b, 0x0b,\
+/*  80 */ 0x0b, 0x0b, 0x0b, 0x01, 0x26, 0x26, 0x26, 0x26,\
+/*  88 */ 0x26, 0x26, 0x26, 0x26, 0x26, 0x26, 0x02, 0x12,\
+/*  96 */ 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x10, 0x10,\
 /* 104 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
-/* 112 */ 0x00, 0x00, 0x10, 0x10, 0x00, 0x00, 0x00, 0x00,\
-/* 120 */ 0x00, 0x00, 0x00, 0x10, 0x00, 0x04, 0x04, 0x00,\
-/* 128 */ 0x00, 0x10, 0x10, 0x00, 0x10, 0x00, 0x10, 0x10,\
-/* 136 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06,\
-/* 144 */ 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00, 0x00, 0x00,\
-/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10,\
-/* 160 */ 0x10, 0x00, 0x00, 0x00,}
+/* 112 */ 0x00, 0x00, 0x00, 0x00, 0x10, 0x10, 0x00, 0x00,\
+/* 120 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x04,\
+/* 128 */ 0x04, 0x00, 0x00, 0x10, 0x10, 0x10, 0x00, 0x00,\
+/* 136 */ 0x10, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 144 */ 0x00, 0x06, 0x10, 0x00, 0x04, 0x1a, 0x00, 0x00,\
+/* 152 */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,\
+/* 160 */ 0x00, 0x10, 0x10, 0x00, 0x00, 0x00,}
 
 /* The sqlite3P2Values() routine is able to run faster if it knows
 ** the value of the largest JUMP opcode.  The smaller the maximum
 ** JUMP opcode the better, so the mkopcodeh.tcl script that
 ** generated this include file strives to group all JUMP opcodes
 ** together near the beginning of the list.
 */
-#define SQLITE_MX_JUMP_OPCODE  72  /* Maximum JUMP opcode */
+#define SQLITE_MX_JUMP_OPCODE  83  /* Maximum JUMP opcode */
 
 /************** End of opcodes.h *********************************************/
 /************** Continuing where we left off in vdbe.h ***********************/
 
 /*
 ** Prototypes for the VDBE interface.  See comments on the implementation
 ** for a description of what each of these routines does.
 */
@@ -15206,32 +15218,33 @@ struct Expr {
 ** column labels.  In this case, Expr.zSpan is typically the text of a
 ** column expression as it exists in a SELECT statement.  However, if
 ** the bSpanIsTab flag is set, then zSpan is overloaded to mean the name
 ** of the result column in the form: DATABASE.TABLE.COLUMN.  This later
 ** form is used for name resolution with nested FROM clauses.
 */
 struct ExprList {
   int nExpr;             /* Number of expressions on the list */
+  int nAlloc;            /* Number of a[] slots allocated */
   struct ExprList_item { /* For each expression in the list */
     Expr *pExpr;            /* The parse tree for this expression */
     char *zName;            /* Token associated with this expression */
     char *zSpan;            /* Original text of the expression */
     u8 sortOrder;           /* 1 for DESC or 0 for ASC */
     unsigned done :1;       /* A flag to indicate when processing is finished */
     unsigned bSpanIsTab :1; /* zSpan holds DB.TABLE.COLUMN */
     unsigned reusable :1;   /* Constant expression is reusable */
     union {
       struct {
         u16 iOrderByCol;      /* For ORDER BY, column number in result set */
         u16 iAlias;           /* Index into Parse.aAlias[] for zName */
       } x;
       int iConstExprReg;      /* Register in which Expr value is cached */
     } u;
-  } *a;                  /* Alloc a power of two greater or equal to nExpr */
+  } a[1];                  /* One slot for each expression in the list */
 };
 
 /*
 ** An instance of this structure is used by the parser to record both
 ** the parse tree for an expression and the span of input text for an
 ** expression.
 */
 struct ExprSpan {
@@ -16078,24 +16091,27 @@ struct Sqlite3Config {
 struct Walker {
   Parse *pParse;                            /* Parser context.  */
   int (*xExprCallback)(Walker*, Expr*);     /* Callback for expressions */
   int (*xSelectCallback)(Walker*,Select*);  /* Callback for SELECTs */
   void (*xSelectCallback2)(Walker*,Select*);/* Second callback for SELECTs */
   int walkerDepth;                          /* Number of subqueries */
   u8 eCode;                                 /* A small processing code */
   union {                                   /* Extra data for callback */
-    NameContext *pNC;                          /* Naming context */
-    int n;                                     /* A counter */
-    int iCur;                                  /* A cursor number */
-    SrcList *pSrcList;                         /* FROM clause */
-    struct SrcCount *pSrcCount;                /* Counting column references */
-    struct CCurHint *pCCurHint;                /* Used by codeCursorHint() */
-    int *aiCol;                                /* array of column indexes */
-    struct IdxCover *pIdxCover;                /* Check for index coverage */
+    NameContext *pNC;                         /* Naming context */
+    int n;                                    /* A counter */
+    int iCur;                                 /* A cursor number */
+    SrcList *pSrcList;                        /* FROM clause */
+    struct SrcCount *pSrcCount;               /* Counting column references */
+    struct CCurHint *pCCurHint;               /* Used by codeCursorHint() */
+    int *aiCol;                               /* array of column indexes */
+    struct IdxCover *pIdxCover;               /* Check for index coverage */
+    struct IdxExprTrans *pIdxTrans;           /* Convert indexed expr to column */
+    ExprList *pGroupBy;                       /* GROUP BY clause */
+    struct HavingToWhereCtx *pHavingCtx;      /* HAVING to WHERE clause ctx */
   } u;
 };
 
 /* Forward declarations */
 SQLITE_PRIVATE int sqlite3WalkExpr(Walker*, Expr*);
 SQLITE_PRIVATE int sqlite3WalkExprList(Walker*, ExprList*);
 SQLITE_PRIVATE int sqlite3WalkSelect(Walker*, Select*);
 SQLITE_PRIVATE int sqlite3WalkSelectExpr(Walker*, Select*);
@@ -16239,16 +16255,17 @@ SQLITE_PRIVATE void *sqlite3DbMallocZero
 SQLITE_PRIVATE void *sqlite3DbMallocRaw(sqlite3*, u64);
 SQLITE_PRIVATE void *sqlite3DbMallocRawNN(sqlite3*, u64);
 SQLITE_PRIVATE char *sqlite3DbStrDup(sqlite3*,const char*);
 SQLITE_PRIVATE char *sqlite3DbStrNDup(sqlite3*,const char*, u64);
 SQLITE_PRIVATE void *sqlite3Realloc(void*, u64);
 SQLITE_PRIVATE void *sqlite3DbReallocOrFree(sqlite3 *, void *, u64);
 SQLITE_PRIVATE void *sqlite3DbRealloc(sqlite3 *, void *, u64);
 SQLITE_PRIVATE void sqlite3DbFree(sqlite3*, void*);
+SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3*, void*);
 SQLITE_PRIVATE int sqlite3MallocSize(void*);
 SQLITE_PRIVATE int sqlite3DbMallocSize(sqlite3*, void*);
 SQLITE_PRIVATE void *sqlite3ScratchMalloc(int);
 SQLITE_PRIVATE void sqlite3ScratchFree(void*);
 SQLITE_PRIVATE void *sqlite3PageMalloc(int);
 SQLITE_PRIVATE void sqlite3PageFree(void*);
 SQLITE_PRIVATE void sqlite3MemSetDefault(void);
 #ifndef SQLITE_UNTESTABLE
@@ -16554,16 +16571,17 @@ SQLITE_PRIVATE void sqlite3BeginTransact
 SQLITE_PRIVATE void sqlite3CommitTransaction(Parse*);
 SQLITE_PRIVATE void sqlite3RollbackTransaction(Parse*);
 SQLITE_PRIVATE void sqlite3Savepoint(Parse*, int, Token*);
 SQLITE_PRIVATE void sqlite3CloseSavepoints(sqlite3 *);
 SQLITE_PRIVATE void sqlite3LeaveMutexAndCloseZombie(sqlite3*);
 SQLITE_PRIVATE int sqlite3ExprIsConstant(Expr*);
 SQLITE_PRIVATE int sqlite3ExprIsConstantNotJoin(Expr*);
 SQLITE_PRIVATE int sqlite3ExprIsConstantOrFunction(Expr*, u8);
+SQLITE_PRIVATE int sqlite3ExprIsConstantOrGroupBy(Parse*, Expr*, ExprList*);
 SQLITE_PRIVATE int sqlite3ExprIsTableConstant(Expr*,int);
 #ifdef SQLITE_ENABLE_CURSOR_HINTS
 SQLITE_PRIVATE int sqlite3ExprContainsSubquery(Expr*);
 #endif
 SQLITE_PRIVATE int sqlite3ExprIsInteger(Expr*, int*);
 SQLITE_PRIVATE int sqlite3ExprCanBeNull(const Expr*);
 SQLITE_PRIVATE int sqlite3ExprNeedsNoAffinityChange(const Expr*, char);
 SQLITE_PRIVATE int sqlite3IsRowid(const char*);
@@ -17263,19 +17281,26 @@ SQLITE_PRIVATE const unsigned char sqlit
 ** disabled by default.
 **
 ** EVIDENCE-OF: R-38799-08373 URI filenames can be enabled or disabled
 ** using the SQLITE_USE_URI=1 or SQLITE_USE_URI=0 compile-time options.
 **
 ** EVIDENCE-OF: R-43642-56306 By default, URI handling is globally
 ** disabled. The default value may be changed by compiling with the
 ** SQLITE_USE_URI symbol defined.
+**
+** URI filenames are enabled by default if SQLITE_HAS_CODEC is
+** enabled.
 */
 #ifndef SQLITE_USE_URI
-# define  SQLITE_USE_URI 0
+# ifdef SQLITE_HAS_CODEC
+#  define SQLITE_USE_URI 1
+# else
+#  define SQLITE_USE_URI 0
+# endif
 #endif
 
 /* EVIDENCE-OF: R-38720-18127 The default setting is determined by the
 ** SQLITE_ALLOW_COVERING_INDEX_SCAN compile-time option, or is "on" if
 ** that compile-time option is omitted.
 */
 #ifndef SQLITE_ALLOW_COVERING_INDEX_SCAN
 # define SQLITE_ALLOW_COVERING_INDEX_SCAN 1
@@ -18089,17 +18114,17 @@ struct VdbeFrame {
 
 #define VdbeFrameMem(p) ((Mem *)&((u8 *)p)[ROUND8(sizeof(VdbeFrame))])
 
 /*
 ** Internally, the vdbe manipulates nearly all SQL values as Mem
 ** structures. Each Mem struct may cache multiple representations (string,
 ** integer etc.) of the same value.
 */
-struct Mem {
+struct sqlite3_value {
   union MemValue {
     double r;           /* Real value used when MEM_Real is set in flags */
     i64 i;              /* Integer value used when MEM_Int is set in flags */
     int nZero;          /* Used when bit MEM_Zero is set in flags */
     FuncDef *pDef;      /* Used only when flags==MEM_Agg */
     RowSet *pRowSet;    /* Used only when flags==MEM_RowSet */
     VdbeFrame *pFrame;  /* Used when flags==MEM_Frame */
   } u;
@@ -18191,21 +18216,21 @@ struct Mem {
 /*
 ** Each auxiliary data pointer stored by a user defined function 
 ** implementation calling sqlite3_set_auxdata() is stored in an instance
 ** of this structure. All such structures associated with a single VM
 ** are stored in a linked list headed at Vdbe.pAuxData. All are destroyed
 ** when the VM is halted (if not before).
 */
 struct AuxData {
-  int iOp;                        /* Instruction number of OP_Function opcode */
-  int iArg;                       /* Index of function argument. */
+  int iAuxOp;                     /* Instruction number of OP_Function opcode */
+  int iAuxArg;                    /* Index of function argument. */
   void *pAux;                     /* Aux data pointer */
-  void (*xDelete)(void *);        /* Destructor for the aux data */
-  AuxData *pNext;                 /* Next element in list */
+  void (*xDeleteAux)(void*);      /* Destructor for the aux data */
+  AuxData *pNextAux;              /* Next element in list */
 };
 
 /*
 ** The "context" argument for an installable function.  A pointer to an
 ** instance of this structure is the first argument to the routines used
 ** implement the SQL functions.
 **
 ** There is a typedef for this structure in sqlite.h.  So all routines,
@@ -19219,18 +19244,20 @@ static int validJulianDay(sqlite3_int64 
 */
 static void computeYMD(DateTime *p){
   int Z, A, B, C, D, E, X1;
   if( p->validYMD ) return;
   if( !p->validJD ){
     p->Y = 2000;
     p->M = 1;
     p->D = 1;
-  }else{
-    assert( validJulianDay(p->iJD) );
+  }else if( !validJulianDay(p->iJD) ){
+    datetimeError(p);
+    return;
+  }else{
     Z = (int)((p->iJD + 43200000)/86400000);
     A = (int)((Z - 1867216.25)/36524.25);
     A = Z + 1 + A - (A/4);
     B = A + 1524;
     C = (int)((B - 122.1)/365.25);
     D = (36525*(C&32767))/100;
     E = (int)((B-D)/30.6001);
     X1 = (int)(30.6001*E);
@@ -24656,21 +24683,22 @@ SQLITE_API void sqlite3_free(void *p){
 ** *db->pnBytesFreed.
 */
 static SQLITE_NOINLINE void measureAllocationSize(sqlite3 *db, void *p){
   *db->pnBytesFreed += sqlite3DbMallocSize(db,p);
 }
 
 /*
 ** Free memory that might be associated with a particular database
-** connection.
-*/
-SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
+** connection.  Calling sqlite3DbFree(D,X) for X==0 is a harmless no-op.
+** The sqlite3DbFreeNN(D,X) version requires that X be non-NULL.
+*/
+SQLITE_PRIVATE void sqlite3DbFreeNN(sqlite3 *db, void *p){
   assert( db==0 || sqlite3_mutex_held(db->mutex) );
-  if( p==0 ) return;
+  assert( p!=0 );
   if( db ){
     if( db->pnBytesFreed ){
       measureAllocationSize(db, p);
       return;
     }
     if( isLookaside(db, p) ){
       LookasideSlot *pBuf = (LookasideSlot*)p;
 #ifdef SQLITE_DEBUG
@@ -24684,16 +24712,20 @@ SQLITE_PRIVATE void sqlite3DbFree(sqlite
     }
   }
   assert( sqlite3MemdebugHasType(p, (MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
   assert( sqlite3MemdebugNoType(p, (u8)~(MEMTYPE_LOOKASIDE|MEMTYPE_HEAP)) );
   assert( db!=0 || sqlite3MemdebugNoType(p, MEMTYPE_LOOKASIDE) );
   sqlite3MemdebugSetType(p, MEMTYPE_HEAP);
   sqlite3_free(p);
 }
+SQLITE_PRIVATE void sqlite3DbFree(sqlite3 *db, void *p){
+  assert( db==0 || sqlite3_mutex_held(db->mutex) );
+  if( p ) sqlite3DbFreeNN(db, p);
+}
 
 /*
 ** Change the size of an existing memory allocation
 */
 SQLITE_PRIVATE void *sqlite3Realloc(void *pOld, u64 nBytes){
   int nOld, nNew, nDiff;
   void *pNew;
   assert( sqlite3MemdebugHasType(pOld, MEMTYPE_HEAP) );
@@ -26376,25 +26408,30 @@ SQLITE_PRIVATE void sqlite3TreeViewSelec
 }
 
 /*
 ** Generate a human-readable explanation of an expression tree.
 */
 SQLITE_PRIVATE void sqlite3TreeViewExpr(TreeView *pView, const Expr *pExpr, u8 moreToFollow){
   const char *zBinOp = 0;   /* Binary operator */
   const char *zUniOp = 0;   /* Unary operator */
-  char zFlgs[30];
+  char zFlgs[60];
   pView = sqlite3TreeViewPush(pView, moreToFollow);
   if( pExpr==0 ){
     sqlite3TreeViewLine(pView, "nil");
     sqlite3TreeViewPop(pView);
     return;
   }
   if( pExpr->flags ){
-    sqlite3_snprintf(sizeof(zFlgs),zFlgs,"  flags=0x%x",pExpr->flags);
+    if( ExprHasProperty(pExpr, EP_FromJoin) ){
+      sqlite3_snprintf(sizeof(zFlgs),zFlgs,"  flags=0x%x iRJT=%d",
+                       pExpr->flags, pExpr->iRightJoinTable);
+    }else{
+      sqlite3_snprintf(sizeof(zFlgs),zFlgs,"  flags=0x%x",pExpr->flags);
+    }
   }else{
     zFlgs[0] = 0;
   }
   switch( pExpr->op ){
     case TK_AGG_COLUMN: {
       sqlite3TreeViewLine(pView, "AGG{%d:%d}%s",
             pExpr->iTable, pExpr->iColumn, zFlgs);
       break;
@@ -26603,16 +26640,21 @@ SQLITE_PRIVATE void sqlite3TreeViewExpr(
       sqlite3TreeViewBareExprList(pView, pExpr->x.pList, "VECTOR");
       break;
     }
     case TK_SELECT_COLUMN: {
       sqlite3TreeViewLine(pView, "SELECT-COLUMN %d", pExpr->iColumn);
       sqlite3TreeViewSelect(pView, pExpr->pLeft->x.pSelect, 0);
       break;
     }
+    case TK_IF_NULL_ROW: {
+      sqlite3TreeViewLine(pView, "IF-NULL-ROW %d", pExpr->iTable);
+      sqlite3TreeViewExpr(pView, pExpr->pLeft, 0);
+      break;
+    }
     default: {
       sqlite3TreeViewLine(pView, "op=%d", pExpr->op);
       break;
     }
   }
   if( zBinOp ){
     sqlite3TreeViewLine(pView, "%s%s", zBinOp, zFlgs);
     sqlite3TreeViewExpr(pView, pExpr->pLeft, 1);
@@ -28322,16 +28364,17 @@ SQLITE_PRIVATE int sqlite3GetInt32(const
     if( (u&0x80000000)==0 && sqlite3Isxdigit(zNum[i])==0 ){
       memcpy(pValue, &u, 4);
       return 1;
     }else{
       return 0;
     }
   }
 #endif
+  if( !sqlite3Isdigit(zNum[0]) ) return 0;
   while( zNum[0]=='0' ) zNum++;
   for(i=0; i<11 && (c = zNum[i] - '0')>=0 && c<=9; i++){
     v = v*10 + c;
   }
 
   /* The longest decimal representation of a 32 bit integer is 10 digits:
   **
   **             1234567890
@@ -29485,157 +29528,159 @@ SQLITE_PRIVATE const char *sqlite3Opcode
     /*  15 */ "InitCoroutine"    OpHelp(""),
     /*  16 */ "Yield"            OpHelp(""),
     /*  17 */ "MustBeInt"        OpHelp(""),
     /*  18 */ "Jump"             OpHelp(""),
     /*  19 */ "Not"              OpHelp("r[P2]= !r[P1]"),
     /*  20 */ "Once"             OpHelp(""),
     /*  21 */ "If"               OpHelp(""),
     /*  22 */ "IfNot"            OpHelp(""),
-    /*  23 */ "SeekLT"           OpHelp("key=r[P3@P4]"),
-    /*  24 */ "SeekLE"           OpHelp("key=r[P3@P4]"),
-    /*  25 */ "SeekGE"           OpHelp("key=r[P3@P4]"),
-    /*  26 */ "SeekGT"           OpHelp("key=r[P3@P4]"),
-    /*  27 */ "Or"               OpHelp("r[P3]=(r[P1] || r[P2])"),
-    /*  28 */ "And"              OpHelp("r[P3]=(r[P1] && r[P2])"),
-    /*  29 */ "NoConflict"       OpHelp("key=r[P3@P4]"),
-    /*  30 */ "NotFound"         OpHelp("key=r[P3@P4]"),
-    /*  31 */ "Found"            OpHelp("key=r[P3@P4]"),
-    /*  32 */ "SeekRowid"        OpHelp("intkey=r[P3]"),
-    /*  33 */ "NotExists"        OpHelp("intkey=r[P3]"),
-    /*  34 */ "IsNull"           OpHelp("if r[P1]==NULL goto P2"),
-    /*  35 */ "NotNull"          OpHelp("if r[P1]!=NULL goto P2"),
-    /*  36 */ "Ne"               OpHelp("IF r[P3]!=r[P1]"),
-    /*  37 */ "Eq"               OpHelp("IF r[P3]==r[P1]"),
-    /*  38 */ "Gt"               OpHelp("IF r[P3]>r[P1]"),
-    /*  39 */ "Le"               OpHelp("IF r[P3]<=r[P1]"),
-    /*  40 */ "Lt"               OpHelp("IF r[P3]<r[P1]"),
-    /*  41 */ "Ge"               OpHelp("IF r[P3]>=r[P1]"),
-    /*  42 */ "ElseNotEq"        OpHelp(""),
-    /*  43 */ "BitAnd"           OpHelp("r[P3]=r[P1]&r[P2]"),
-    /*  44 */ "BitOr"            OpHelp("r[P3]=r[P1]|r[P2]"),
-    /*  45 */ "ShiftLeft"        OpHelp("r[P3]=r[P2]<<r[P1]"),
-    /*  46 */ "ShiftRight"       OpHelp("r[P3]=r[P2]>>r[P1]"),
-    /*  47 */ "Add"              OpHelp("r[P3]=r[P1]+r[P2]"),
-    /*  48 */ "Subtract"         OpHelp("r[P3]=r[P2]-r[P1]"),
-    /*  49 */ "Multiply"         OpHelp("r[P3]=r[P1]*r[P2]"),
-    /*  50 */ "Divide"           OpHelp("r[P3]=r[P2]/r[P1]"),
-    /*  51 */ "Remainder"        OpHelp("r[P3]=r[P2]%r[P1]"),
-    /*  52 */ "Concat"           OpHelp("r[P3]=r[P2]+r[P1]"),
-    /*  53 */ "Last"             OpHelp(""),
-    /*  54 */ "BitNot"           OpHelp("r[P1]= ~r[P1]"),
-    /*  55 */ "IfSmaller"        OpHelp(""),
-    /*  56 */ "SorterSort"       OpHelp(""),
-    /*  57 */ "Sort"             OpHelp(""),
-    /*  58 */ "Rewind"           OpHelp(""),
-    /*  59 */ "IdxLE"            OpHelp("key=r[P3@P4]"),
-    /*  60 */ "IdxGT"            OpHelp("key=r[P3@P4]"),
-    /*  61 */ "IdxLT"            OpHelp("key=r[P3@P4]"),
-    /*  62 */ "IdxGE"            OpHelp("key=r[P3@P4]"),
-    /*  63 */ "RowSetRead"       OpHelp("r[P3]=rowset(P1)"),
-    /*  64 */ "RowSetTest"       OpHelp("if r[P3] in rowset(P1) goto P2"),
-    /*  65 */ "Program"          OpHelp(""),
-    /*  66 */ "FkIfZero"         OpHelp("if fkctr[P1]==0 goto P2"),
-    /*  67 */ "IfPos"            OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
-    /*  68 */ "IfNotZero"        OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
-    /*  69 */ "DecrJumpZero"     OpHelp("if (--r[P1])==0 goto P2"),
-    /*  70 */ "IncrVacuum"       OpHelp(""),
-    /*  71 */ "VNext"            OpHelp(""),
-    /*  72 */ "Init"             OpHelp("Start at P2"),
-    /*  73 */ "Return"           OpHelp(""),
-    /*  74 */ "EndCoroutine"     OpHelp(""),
-    /*  75 */ "HaltIfNull"       OpHelp("if r[P3]=null halt"),
-    /*  76 */ "Halt"             OpHelp(""),
-    /*  77 */ "Integer"          OpHelp("r[P2]=P1"),
-    /*  78 */ "Int64"            OpHelp("r[P2]=P4"),
-    /*  79 */ "String"           OpHelp("r[P2]='P4' (len=P1)"),
-    /*  80 */ "Null"             OpHelp("r[P2..P3]=NULL"),
-    /*  81 */ "SoftNull"         OpHelp("r[P1]=NULL"),
-    /*  82 */ "Blob"             OpHelp("r[P2]=P4 (len=P1)"),
-    /*  83 */ "Variable"         OpHelp("r[P2]=parameter(P1,P4)"),
-    /*  84 */ "Move"             OpHelp("r[P2@P3]=r[P1@P3]"),
-    /*  85 */ "Copy"             OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
-    /*  86 */ "SCopy"            OpHelp("r[P2]=r[P1]"),
-    /*  87 */ "IntCopy"          OpHelp("r[P2]=r[P1]"),
-    /*  88 */ "ResultRow"        OpHelp("output=r[P1@P2]"),
-    /*  89 */ "CollSeq"          OpHelp(""),
-    /*  90 */ "Function0"        OpHelp("r[P3]=func(r[P2@P5])"),
-    /*  91 */ "Function"         OpHelp("r[P3]=func(r[P2@P5])"),
-    /*  92 */ "AddImm"           OpHelp("r[P1]=r[P1]+P2"),
-    /*  93 */ "RealAffinity"     OpHelp(""),
+    /*  23 */ "IfNullRow"        OpHelp("if P1.nullRow then r[P3]=NULL, goto P2"),
+    /*  24 */ "SeekLT"           OpHelp("key=r[P3@P4]"),
+    /*  25 */ "SeekLE"           OpHelp("key=r[P3@P4]"),
+    /*  26 */ "SeekGE"           OpHelp("key=r[P3@P4]"),
+    /*  27 */ "SeekGT"           OpHelp("key=r[P3@P4]"),
+    /*  28 */ "NoConflict"       OpHelp("key=r[P3@P4]"),
+    /*  29 */ "NotFound"         OpHelp("key=r[P3@P4]"),
+    /*  30 */ "Found"            OpHelp("key=r[P3@P4]"),
+    /*  31 */ "SeekRowid"        OpHelp("intkey=r[P3]"),
+    /*  32 */ "NotExists"        OpHelp("intkey=r[P3]"),
+    /*  33 */ "Last"             OpHelp(""),
+    /*  34 */ "IfSmaller"        OpHelp(""),
+    /*  35 */ "SorterSort"       OpHelp(""),
+    /*  36 */ "Sort"             OpHelp(""),
+    /*  37 */ "Rewind"           OpHelp(""),
+    /*  38 */ "IdxLE"            OpHelp("key=r[P3@P4]"),
+    /*  39 */ "IdxGT"            OpHelp("key=r[P3@P4]"),
+    /*  40 */ "IdxLT"            OpHelp("key=r[P3@P4]"),
+    /*  41 */ "IdxGE"            OpHelp("key=r[P3@P4]"),
+    /*  42 */ "RowSetRead"       OpHelp("r[P3]=rowset(P1)"),
+    /*  43 */ "RowSetTest"       OpHelp("if r[P3] in rowset(P1) goto P2"),
+    /*  44 */ "Program"          OpHelp(""),
+    /*  45 */ "FkIfZero"         OpHelp("if fkctr[P1]==0 goto P2"),
+    /*  46 */ "IfPos"            OpHelp("if r[P1]>0 then r[P1]-=P3, goto P2"),
+    /*  47 */ "IfNotZero"        OpHelp("if r[P1]!=0 then r[P1]--, goto P2"),
+    /*  48 */ "DecrJumpZero"     OpHelp("if (--r[P1])==0 goto P2"),
+    /*  49 */ "IncrVacuum"       OpHelp(""),
+    /*  50 */ "VNext"            OpHelp(""),
+    /*  51 */ "Init"             OpHelp("Start at P2"),
+    /*  52 */ "Return"           OpHelp(""),
+    /*  53 */ "EndCoroutine"     OpHelp(""),
+    /*  54 */ "HaltIfNull"       OpHelp("if r[P3]=null halt"),
+    /*  55 */ "Halt"             OpHelp(""),
+    /*  56 */ "Integer"          OpHelp("r[P2]=P1"),
+    /*  57 */ "Int64"            OpHelp("r[P2]=P4"),
+    /*  58 */ "String"           OpHelp("r[P2]='P4' (len=P1)"),
+    /*  59 */ "Null"             OpHelp("r[P2..P3]=NULL"),
+    /*  60 */ "SoftNull"         OpHelp("r[P1]=NULL"),
+    /*  61 */ "Blob"             OpHelp("r[P2]=P4 (len=P1)"),
+    /*  62 */ "Variable"         OpHelp("r[P2]=parameter(P1,P4)"),
+    /*  63 */ "Move"             OpHelp("r[P2@P3]=r[P1@P3]"),
+    /*  64 */ "Copy"             OpHelp("r[P2@P3+1]=r[P1@P3+1]"),
+    /*  65 */ "SCopy"            OpHelp("r[P2]=r[P1]"),
+    /*  66 */ "IntCopy"          OpHelp("r[P2]=r[P1]"),
+    /*  67 */ "ResultRow"        OpHelp("output=r[P1@P2]"),
+    /*  68 */ "CollSeq"          OpHelp(""),
+    /*  69 */ "Function0"        OpHelp("r[P3]=func(r[P2@P5])"),
+    /*  70 */ "Or"               OpHelp("r[P3]=(r[P1] || r[P2])"),
+    /*  71 */ "And"              OpHelp("r[P3]=(r[P1] && r[P2])"),
+    /*  72 */ "Function"         OpHelp("r[P3]=func(r[P2@P5])"),
+    /*  73 */ "AddImm"           OpHelp("r[P1]=r[P1]+P2"),
+    /*  74 */ "RealAffinity"     OpHelp(""),
+    /*  75 */ "IsNull"           OpHelp("if r[P1]==NULL goto P2"),
+    /*  76 */ "NotNull"          OpHelp("if r[P1]!=NULL goto P2"),
+    /*  77 */ "Ne"               OpHelp("IF r[P3]!=r[P1]"),
+    /*  78 */ "Eq"               OpHelp("IF r[P3]==r[P1]"),
+    /*  79 */ "Gt"               OpHelp("IF r[P3]>r[P1]"),
+    /*  80 */ "Le"               OpHelp("IF r[P3]<=r[P1]"),
+    /*  81 */ "Lt"               OpHelp("IF r[P3]<r[P1]"),
+    /*  82 */ "Ge"               OpHelp("IF r[P3]>=r[P1]"),
+    /*  83 */ "ElseNotEq"        OpHelp(""),
+    /*  84 */ "BitAnd"           OpHelp("r[P3]=r[P1]&r[P2]"),
+    /*  85 */ "BitOr"            OpHelp("r[P3]=r[P1]|r[P2]"),
+    /*  86 */ "ShiftLeft"        OpHelp("r[P3]=r[P2]<<r[P1]"),
+    /*  87 */ "ShiftRight"       OpHelp("r[P3]=r[P2]>>r[P1]"),
+    /*  88 */ "Add"              OpHelp("r[P3]=r[P1]+r[P2]"),
+    /*  89 */ "Subtract"         OpHelp("r[P3]=r[P2]-r[P1]"),
+    /*  90 */ "Multiply"         OpHelp("r[P3]=r[P1]*r[P2]"),
+    /*  91 */ "Divide"           OpHelp("r[P3]=r[P2]/r[P1]"),
+    /*  92 */ "Remainder"        OpHelp("r[P3]=r[P2]%r[P1]"),
+    /*  93 */ "Concat"           OpHelp("r[P3]=r[P2]+r[P1]"),
     /*  94 */ "Cast"             OpHelp("affinity(r[P1])"),
-    /*  95 */ "Permutation"      OpHelp(""),
-    /*  96 */ "Compare"          OpHelp("r[P1@P3] <-> r[P2@P3]"),
+    /*  95 */ "BitNot"           OpHelp("r[P1]= ~r[P1]"),
+    /*  96 */ "Permutation"      OpHelp(""),
     /*  97 */ "String8"          OpHelp("r[P2]='P4'"),
-    /*  98 */ "Column"           OpHelp("r[P3]=PX"),
-    /*  99 */ "Affinity"         OpHelp("affinity(r[P1@P2])"),
-    /* 100 */ "MakeRecord"       OpHelp("r[P3]=mkrec(r[P1@P2])"),
-    /* 101 */ "Count"            OpHelp("r[P2]=count()"),
-    /* 102 */ "ReadCookie"       OpHelp(""),
-    /* 103 */ "SetCookie"        OpHelp(""),
-    /* 104 */ "ReopenIdx"        OpHelp("root=P2 iDb=P3"),
-    /* 105 */ "OpenRead"         OpHelp("root=P2 iDb=P3"),
-    /* 106 */ "OpenWrite"        OpHelp("root=P2 iDb=P3"),
-    /* 107 */ "OpenAutoindex"    OpHelp("nColumn=P2"),
-    /* 108 */ "OpenEphemeral"    OpHelp("nColumn=P2"),
-    /* 109 */ "SorterOpen"       OpHelp(""),
-    /* 110 */ "SequenceTest"     OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
-    /* 111 */ "OpenPseudo"       OpHelp("P3 columns in r[P2]"),
-    /* 112 */ "Close"            OpHelp(""),
-    /* 113 */ "ColumnsUsed"      OpHelp(""),
-    /* 114 */ "Sequence"         OpHelp("r[P2]=cursor[P1].ctr++"),
-    /* 115 */ "NewRowid"         OpHelp("r[P2]=rowid"),
-    /* 116 */ "Insert"           OpHelp("intkey=r[P3] data=r[P2]"),
-    /* 117 */ "InsertInt"        OpHelp("intkey=P3 data=r[P2]"),
-    /* 118 */ "Delete"           OpHelp(""),
-    /* 119 */ "ResetCount"       OpHelp(""),
-    /* 120 */ "SorterCompare"    OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
-    /* 121 */ "SorterData"       OpHelp("r[P2]=data"),
-    /* 122 */ "RowData"          OpHelp("r[P2]=data"),
-    /* 123 */ "Rowid"            OpHelp("r[P2]=rowid"),
-    /* 124 */ "NullRow"          OpHelp(""),
-    /* 125 */ "SorterInsert"     OpHelp("key=r[P2]"),
-    /* 126 */ "IdxInsert"        OpHelp("key=r[P2]"),
-    /* 127 */ "IdxDelete"        OpHelp("key=r[P2@P3]"),
-    /* 128 */ "Seek"             OpHelp("Move P3 to P1.rowid"),
-    /* 129 */ "IdxRowid"         OpHelp("r[P2]=rowid"),
-    /* 130 */ "Destroy"          OpHelp(""),
-    /* 131 */ "Clear"            OpHelp(""),
+    /*  98 */ "Compare"          OpHelp("r[P1@P3] <-> r[P2@P3]"),
+    /*  99 */ "Column"           OpHelp("r[P3]=PX"),
+    /* 100 */ "Affinity"         OpHelp("affinity(r[P1@P2])"),
+    /* 101 */ "MakeRecord"       OpHelp("r[P3]=mkrec(r[P1@P2])"),
+    /* 102 */ "Count"            OpHelp("r[P2]=count()"),
+    /* 103 */ "ReadCookie"       OpHelp(""),
+    /* 104 */ "SetCookie"        OpHelp(""),
+    /* 105 */ "ReopenIdx"        OpHelp("root=P2 iDb=P3"),
+    /* 106 */ "OpenRead"         OpHelp("root=P2 iDb=P3"),
+    /* 107 */ "OpenWrite"        OpHelp("root=P2 iDb=P3"),
+    /* 108 */ "OpenDup"          OpHelp(""),
+    /* 109 */ "OpenAutoindex"    OpHelp("nColumn=P2"),
+    /* 110 */ "OpenEphemeral"    OpHelp("nColumn=P2"),
+    /* 111 */ "SorterOpen"       OpHelp(""),
+    /* 112 */ "SequenceTest"     OpHelp("if( cursor[P1].ctr++ ) pc = P2"),
+    /* 113 */ "OpenPseudo"       OpHelp("P3 columns in r[P2]"),
+    /* 114 */ "Close"            OpHelp(""),
+    /* 115 */ "ColumnsUsed"      OpHelp(""),
+    /* 116 */ "Sequence"         OpHelp("r[P2]=cursor[P1].ctr++"),
+    /* 117 */ "NewRowid"         OpHelp("r[P2]=rowid"),
+    /* 118 */ "Insert"           OpHelp("intkey=r[P3] data=r[P2]"),
+    /* 119 */ "InsertInt"        OpHelp("intkey=P3 data=r[P2]"),
+    /* 120 */ "Delete"           OpHelp(""),
+    /* 121 */ "ResetCount"       OpHelp(""),
+    /* 122 */ "SorterCompare"    OpHelp("if key(P1)!=trim(r[P3],P4) goto P2"),
+    /* 123 */ "SorterData"       OpHelp("r[P2]=data"),
+    /* 124 */ "RowData"          OpHelp("r[P2]=data"),
+    /* 125 */ "Rowid"            OpHelp("r[P2]=rowid"),
+    /* 126 */ "NullRow"          OpHelp(""),
+    /* 127 */ "SorterInsert"     OpHelp("key=r[P2]"),
+    /* 128 */ "IdxInsert"        OpHelp("key=r[P2]"),
+    /* 129 */ "IdxDelete"        OpHelp("key=r[P2@P3]"),
+    /* 130 */ "Seek"             OpHelp("Move P3 to P1.rowid"),
+    /* 131 */ "IdxRowid"         OpHelp("r[P2]=rowid"),
     /* 132 */ "Real"             OpHelp("r[P2]=P4"),
-    /* 133 */ "ResetSorter"      OpHelp(""),
-    /* 134 */ "CreateIndex"      OpHelp("r[P2]=root iDb=P1"),
-    /* 135 */ "CreateTable"      OpHelp("r[P2]=root iDb=P1"),
-    /* 136 */ "SqlExec"          OpHelp(""),
-    /* 137 */ "ParseSchema"      OpHelp(""),
-    /* 138 */ "LoadAnalysis"     OpHelp(""),
-    /* 139 */ "DropTable"        OpHelp(""),
-    /* 140 */ "DropIndex"        OpHelp(""),
-    /* 141 */ "DropTrigger"      OpHelp(""),
-    /* 142 */ "IntegrityCk"      OpHelp(""),
-    /* 143 */ "RowSetAdd"        OpHelp("rowset(P1)=r[P2]"),
-    /* 144 */ "Param"            OpHelp(""),
-    /* 145 */ "FkCounter"        OpHelp("fkctr[P1]+=P2"),
-    /* 146 */ "MemMax"           OpHelp("r[P1]=max(r[P1],r[P2])"),
-    /* 147 */ "OffsetLimit"      OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
-    /* 148 */ "AggStep0"         OpHelp("accum=r[P3] step(r[P2@P5])"),
-    /* 149 */ "AggStep"          OpHelp("accum=r[P3] step(r[P2@P5])"),
-    /* 150 */ "AggFinal"         OpHelp("accum=r[P1] N=P2"),
-    /* 151 */ "Expire"           OpHelp(""),
-    /* 152 */ "TableLock"        OpHelp("iDb=P1 root=P2 write=P3"),
-    /* 153 */ "VBegin"           OpHelp(""),
-    /* 154 */ "VCreate"          OpHelp(""),
-    /* 155 */ "VDestroy"         OpHelp(""),
-    /* 156 */ "VOpen"            OpHelp(""),
-    /* 157 */ "VColumn"          OpHelp("r[P3]=vcolumn(P2)"),
-    /* 158 */ "VRename"          OpHelp(""),
-    /* 159 */ "Pagecount"        OpHelp(""),
-    /* 160 */ "MaxPgcnt"         OpHelp(""),
-    /* 161 */ "CursorHint"       OpHelp(""),
-    /* 162 */ "Noop"             OpHelp(""),
-    /* 163 */ "Explain"          OpHelp(""),
+    /* 133 */ "Destroy"          OpHelp(""),
+    /* 134 */ "Clear"            OpHelp(""),
+    /* 135 */ "ResetSorter"      OpHelp(""),
+    /* 136 */ "CreateIndex"      OpHelp("r[P2]=root iDb=P1"),
+    /* 137 */ "CreateTable"      OpHelp("r[P2]=root iDb=P1"),
+    /* 138 */ "SqlExec"          OpHelp(""),
+    /* 139 */ "ParseSchema"      OpHelp(""),
+    /* 140 */ "LoadAnalysis"     OpHelp(""),
+    /* 141 */ "DropTable"        OpHelp(""),
+    /* 142 */ "DropIndex"        OpHelp(""),
+    /* 143 */ "DropTrigger"      OpHelp(""),
+    /* 144 */ "IntegrityCk"      OpHelp(""),
+    /* 145 */ "RowSetAdd"        OpHelp("rowset(P1)=r[P2]"),
+    /* 146 */ "Param"            OpHelp(""),
+    /* 147 */ "FkCounter"        OpHelp("fkctr[P1]+=P2"),
+    /* 148 */ "MemMax"           OpHelp("r[P1]=max(r[P1],r[P2])"),
+    /* 149 */ "OffsetLimit"      OpHelp("if r[P1]>0 then r[P2]=r[P1]+max(0,r[P3]) else r[P2]=(-1)"),
+    /* 150 */ "AggStep0"         OpHelp("accum=r[P3] step(r[P2@P5])"),
+    /* 151 */ "AggStep"          OpHelp("accum=r[P3] step(r[P2@P5])"),
+    /* 152 */ "AggFinal"         OpHelp("accum=r[P1] N=P2"),
+    /* 153 */ "Expire"           OpHelp(""),
+    /* 154 */ "TableLock"        OpHelp("iDb=P1 root=P2 write=P3"),
+    /* 155 */ "VBegin"           OpHelp(""),
+    /* 156 */ "VCreate"          OpHelp(""),
+    /* 157 */ "VDestroy"         OpHelp(""),
+    /* 158 */ "VOpen"            OpHelp(""),
+    /* 159 */ "VColumn"          OpHelp("r[P3]=vcolumn(P2)"),
+    /* 160 */ "VRename"          OpHelp(""),
+    /* 161 */ "Pagecount"        OpHelp(""),
+    /* 162 */ "MaxPgcnt"         OpHelp(""),
+    /* 163 */ "CursorHint"       OpHelp(""),
+    /* 164 */ "Noop"             OpHelp(""),
+    /* 165 */ "Explain"          OpHelp(""),
   };
   return azName[i];
 }
 #endif
 
 /************** End of opcodes.c *********************************************/
 /************** Begin file os_unix.c *****************************************/
 /*
@@ -45240,27 +45285,26 @@ static int pcache1InitBulk(PCache1 *pCac
   }
   if( szBulk > pCache->szAlloc*(i64)pCache->nMax ){
     szBulk = pCache->szAlloc*(i64)pCache->nMax;
   }
   zBulk = pCache->pBulk = sqlite3Malloc( szBulk );
   sqlite3EndBenignMalloc();
   if( zBulk ){
     int nBulk = sqlite3MallocSize(zBulk)/pCache->szAlloc;
-    int i;
-    for(i=0; i<nBulk; i++){
+    do{
       PgHdr1 *pX = (PgHdr1*)&zBulk[pCache->szPage];
       pX->page.pBuf = zBulk;
       pX->page.pExtra = &pX[1];
       pX->isBulkLocal = 1;
       pX->isAnchor = 0;
       pX->pNext = pCache->pFree;
       pCache->pFree = pX;
       zBulk += pCache->szAlloc;
-    }
+    }while( --nBulk );
   }
   return pCache->pFree!=0;
 }
 
 /*
 ** Malloc function used within this file to allocate space from the buffer
 ** configured using sqlite3_config(SQLITE_CONFIG_PAGECACHE) option. If no 
 ** such buffer exists or there is no space left in it, this function falls 
@@ -46166,17 +46210,17 @@ SQLITE_PRIVATE sqlite3_mutex *sqlite3Pca
 ** nReq is the number of bytes of memory required. Once this much has
 ** been released, the function returns. The return value is the total number 
 ** of bytes of memory released.
 */
 SQLITE_PRIVATE int sqlite3PcacheReleaseMemory(int nReq){
   int nFree = 0;
   assert( sqlite3_mutex_notheld(pcache1.grp.mutex) );
   assert( sqlite3_mutex_notheld(pcache1.mutex) );
-  if( sqlite3GlobalConfig.nPage==0 ){
+  if( sqlite3GlobalConfig.pPage==0 ){
     PgHdr1 *p;
     pcache1EnterMutex(&pcache1.grp);
     while( (nReq<0 || nFree<nReq)
        &&  (p=pcache1.grp.lru.pLruPrev)!=0
        &&  p->isAnchor==0
     ){
       nFree += pcache1MemSize(p->page.pBuf);
 #ifdef SQLITE_PCACHE_SEPARATE_HEADER
@@ -49126,16 +49170,21 @@ static int pager_playback_one_page(
 ){
   int rc;
   PgHdr *pPg;                   /* An existing page in the cache */
   Pgno pgno;                    /* The page number of a page in journal */
   u32 cksum;                    /* Checksum used for sanity checking */
   char *aData;                  /* Temporary storage for the page */
   sqlite3_file *jfd;            /* The file descriptor for the journal file */
   int isSynced;                 /* True if journal page is synced */
+#ifdef SQLITE_HAS_CODEC
+  /* The jrnlEnc flag is true if Journal pages should be passed through
+  ** the codec.  It is false for pure in-memory journals. */
+  const int jrnlEnc = (isMainJrnl || pPager->subjInMemory==0);
+#endif
 
   assert( (isMainJrnl&~1)==0 );      /* isMainJrnl is 0 or 1 */
   assert( (isSavepnt&~1)==0 );       /* isSavepnt is 0 or 1 */
   assert( isMainJrnl || pDone );     /* pDone always used on sub-journals */
   assert( isSavepnt || pDone==0 );   /* pDone never used on non-savepoint */
 
   aData = pPager->pTmpSpace;
   assert( aData );         /* Temp storage must have already been allocated */
@@ -49249,24 +49298,44 @@ static int pager_playback_one_page(
   }
   if( isOpen(pPager->fd)
    && (pPager->eState>=PAGER_WRITER_DBMOD || pPager->eState==PAGER_OPEN)
    && isSynced
   ){
     i64 ofst = (pgno-1)*(i64)pPager->pageSize;
     testcase( !isSavepnt && pPg!=0 && (pPg->flags&PGHDR_NEED_SYNC)!=0 );
     assert( !pagerUseWal(pPager) );
+
+    /* Write the data read from the journal back into the database file.
+    ** This is usually safe even for an encrypted database - as the data
+    ** was encrypted before it was written to the journal file. The exception
+    ** is if the data was just read from an in-memory sub-journal. In that
+    ** case it must be encrypted here before it is copied into the database
+    ** file.  */
+#ifdef SQLITE_HAS_CODEC
+    if( !jrnlEnc ){
+      CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);
+      rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
+      CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
+    }else
+#endif
     rc = sqlite3OsWrite(pPager->fd, (u8 *)aData, pPager->pageSize, ofst);
+
     if( pgno>pPager->dbFileSize ){
       pPager->dbFileSize = pgno;
     }
     if( pPager->pBackup ){
-      CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
+#ifdef SQLITE_HAS_CODEC
+      if( jrnlEnc ){
+        CODEC1(pPager, aData, pgno, 3, rc=SQLITE_NOMEM_BKPT);
+        sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
+        CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT,aData);
+      }else
+#endif
       sqlite3BackupUpdate(pPager->pBackup, pgno, (u8*)aData);
-      CODEC2(pPager, aData, pgno, 7, rc=SQLITE_NOMEM_BKPT, aData);
     }
   }else if( !isMainJrnl && pPg==0 ){
     /* If this is a rollback of a savepoint and data was not written to
     ** the database and the page is not in-memory, there is a potential
     ** problem. When the page is next fetched by the b-tree layer, it 
     ** will be read from the database file, which may or may not be 
     ** current. 
     **
@@ -49308,17 +49377,19 @@ static int pager_playback_one_page(
 
     /* If this was page 1, then restore the value of Pager.dbFileVers.
     ** Do this before any decoding. */
     if( pgno==1 ){
       memcpy(&pPager->dbFileVers, &((u8*)pData)[24],sizeof(pPager->dbFileVers));
     }
 
     /* Decode the page just read from disk */
-    CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT);
+#if SQLITE_HAS_CODEC
+    if( jrnlEnc ){ CODEC1(pPager, pData, pPg->pgno, 3, rc=SQLITE_NOMEM_BKPT); }
+#endif
     sqlite3PcacheRelease(pPg);
   }
   return rc;
 }
 
 /*
 ** Parameter zMaster is the name of a master journal file. A single journal
 ** file that referred to the master journal file has just been rolled back.
@@ -51320,18 +51391,23 @@ static int subjournalPage(PgHdr *pPg){
     rc = openSubJournal(pPager);
 
     /* If the sub-journal was opened successfully (or was already open),
     ** write the journal record into the file.  */
     if( rc==SQLITE_OK ){
       void *pData = pPg->pData;
       i64 offset = (i64)pPager->nSubRec*(4+pPager->pageSize);
       char *pData2;
-  
-      CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
+
+#if SQLITE_HAS_CODEC   
+      if( !pPager->subjInMemory ){
+        CODEC2(pPager, pData, pPg->pgno, 7, return SQLITE_NOMEM_BKPT, pData2);
+      }else
+#endif
+      pData2 = pData;
       PAGERTRACE(("STMT-JOURNAL %d page %d\n", PAGERID(pPager), pPg->pgno));
       rc = write32bits(pPager->sjfd, offset, pPg->pgno);
       if( rc==SQLITE_OK ){
         rc = sqlite3OsWrite(pPager->sjfd, pData2, pPager->pageSize, offset+4);
       }
     }
   }
   if( rc==SQLITE_OK ){
@@ -58473,20 +58549,20 @@ struct BtCursor {
   u8 curPagerFlags;         /* Flags to send to sqlite3PagerGet() */
   u8 eState;                /* One of the CURSOR_XXX constants (see below) */
   u8 hints;                 /* As configured by CursorSetHints() */
   /* All fields above are zeroed when the cursor is allocated.  See
   ** sqlite3BtreeCursorZero().  Fields that follow must be manually
   ** initialized. */
   i8 iPage;                 /* Index of current page in apPage */
   u8 curIntKey;             /* Value of apPage[0]->intKey */
-  struct KeyInfo *pKeyInfo; /* Argument passed to comparison function */
-  void *padding1;           /* Make object size a multiple of 16 */
-  u16 aiIdx[BTCURSOR_MAX_DEPTH];        /* Current index in apPage[i] */
-  MemPage *apPage[BTCURSOR_MAX_DEPTH];  /* Pages from root to current page */
+  u16 ix;                   /* Current index for apPage[iPage] */
+  u16 aiIdx[BTCURSOR_MAX_DEPTH-1];     /* Current index in apPage[i] */
+  struct KeyInfo *pKeyInfo;            /* Arg passed to comparison function */
+  MemPage *apPage[BTCURSOR_MAX_DEPTH]; /* Pages from root to current page */
 };
 
 /*
 ** Legal values for BtCursor.curFlags
 */
 #define BTCF_WriteFlag    0x01   /* True if a write cursor */
 #define BTCF_ValidNKey    0x02   /* True if info.nKey is valid */
 #define BTCF_ValidOvfl    0x04   /* True if aOverflow is valid */
@@ -59452,36 +59528,37 @@ static void invalidateAllOverflowCache(B
 ** cursors open on any row within the table with root-page pgnoRoot.
 **
 ** Otherwise, if argument isClearTable is false, then the row with
 ** rowid iRow is being replaced or deleted. In this case invalidate
 ** only those incrblob cursors open on that specific row.
 */
 static void invalidateIncrblobCursors(
   Btree *pBtree,          /* The database file to check */
+  Pgno pgnoRoot,          /* The table that might be changing */
   i64 iRow,               /* The rowid that might be changing */
   int isClearTable        /* True if all rows are being deleted */
 ){
   BtCursor *p;
   if( pBtree->hasIncrblobCur==0 ) return;
   assert( sqlite3BtreeHoldsMutex(pBtree) );
   pBtree->hasIncrblobCur = 0;
   for(p=pBtree->pBt->pCursor; p; p=p->pNext){
     if( (p->curFlags & BTCF_Incrblob)!=0 ){
       pBtree->hasIncrblobCur = 1;
-      if( isClearTable || p->info.nKey==iRow ){
+      if( p->pgnoRoot==pgnoRoot && (isClearTable || p->info.nKey==iRow) ){
         p->eState = CURSOR_INVALID;
       }
     }
   }
 }
 
 #else
   /* Stub function when INCRBLOB is omitted */
-  #define invalidateIncrblobCursors(x,y,z)
+  #define invalidateIncrblobCursors(w,x,y,z)
 #endif /* SQLITE_OMIT_INCRBLOB */
 
 /*
 ** Set bit pgno of the BtShared.pHasContent bitvec. This is cal