Merge autoland to mozilla-central. a=merge
authorCsoregi Natalia <ncsoregi@mozilla.com>
Tue, 26 Feb 2019 23:49:43 +0200
changeset 461414 8c60d3a2fcc499bac3e232d666ff4491143085e6
parent 461413 f2145aac6de2be3a8c85c28ec568623faa5902c6 (current diff)
parent 461213 2a9b9f7b3b695a07705960bd2ddc3824f2e21357 (diff)
child 461417 4e181eeea4794a15711bb254f06d2ff216b1bef1
child 461421 31abc7fd9a2692757fd5ce7da0cf43e70d3b348f
push id79101
push userncsoregi@mozilla.com
push dateWed, 27 Feb 2019 04:36:23 +0000
treeherderautoland@faa18d5c3274 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone67.0a1
first release with
nightly linux32
8c60d3a2fcc4 / 67.0a1 / 20190226215106 / files
nightly linux64
8c60d3a2fcc4 / 67.0a1 / 20190226215106 / files
nightly mac
8c60d3a2fcc4 / 67.0a1 / 20190226215106 / files
nightly win32
8c60d3a2fcc4 / 67.0a1 / 20190226215106 / files
nightly win64
8c60d3a2fcc4 / 67.0a1 / 20190226215106 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge autoland to mozilla-central. a=merge
devtools/client/aboutdebugging-new/test/browser/resources/bad-extension/manifest.json
ipc/ipdl/test/ipdl/error/asyncMessageListed.ipdl
ipc/ipdl/test/ipdl/ok/AsyncReturn.ipdl
ipc/ipdl/test/ipdl/ok/Delete.ipdl
ipc/ipdl/test/ipdl/ok/DeleteSub.ipdl
ipc/ipdl/test/ipdl/ok/EndpointDecl.ipdl
ipc/ipdl/test/ipdl/ok/EndpointUse.ipdl
ipc/ipdl/test/ipdl/ok/Nullable.ipdl
ipc/ipdl/test/ipdl/ok/Struct.ipdl
ipc/ipdl/test/ipdl/ok/SyncSyncManagee.ipdl
ipc/ipdl/test/ipdl/ok/SyncSyncManager.ipdl
ipc/ipdl/test/ipdl/ok/actorparam.ipdl
ipc/ipdl/test/ipdl/ok/actorreturn.ipdl
ipc/ipdl/test/ipdl/ok/array_Basic.ipdl
ipc/ipdl/test/ipdl/ok/array_OfActors.ipdl
ipc/ipdl/test/ipdl/ok/array_OfActorsSub.ipdl
ipc/ipdl/test/ipdl/ok/array_Union.ipdl
ipc/ipdl/test/ipdl/ok/basicUsing.ipdl
ipc/ipdl/test/ipdl/ok/builtins.ipdl
ipc/ipdl/test/ipdl/ok/bytebuf.ipdl
ipc/ipdl/test/ipdl/ok/empty.ipdl
ipc/ipdl/test/ipdl/ok/emptyStruct.ipdl
ipc/ipdl/test/ipdl/ok/headerProto.ipdl
ipc/ipdl/test/ipdl/ok/intrProtocol.ipdl
ipc/ipdl/test/ipdl/ok/jetpack.ipdl
ipc/ipdl/test/ipdl/ok/manageSelf.ipdl
ipc/ipdl/test/ipdl/ok/manageSelf_Toplevel.ipdl
ipc/ipdl/test/ipdl/ok/managedProtocol.ipdl
ipc/ipdl/test/ipdl/ok/managerProtocol.ipdl
ipc/ipdl/test/ipdl/ok/maybe_Basic.ipdl
ipc/ipdl/test/ipdl/ok/maybe_OfActors.ipdl
ipc/ipdl/test/ipdl/ok/maybe_OfActorsSub.ipdl
ipc/ipdl/test/ipdl/ok/maybe_Union.ipdl
ipc/ipdl/test/ipdl/ok/media.ipdl
ipc/ipdl/test/ipdl/ok/messageCompress.ipdl
ipc/ipdl/test/ipdl/ok/messageVerify.ipdl
ipc/ipdl/test/ipdl/ok/messageVerifyTopLevel.ipdl
ipc/ipdl/test/ipdl/ok/multiManaged.ipdl
ipc/ipdl/test/ipdl/ok/multiManager1.ipdl
ipc/ipdl/test/ipdl/ok/multiManager2.ipdl
ipc/ipdl/test/ipdl/ok/multipleUsingCxxTypes.ipdl
ipc/ipdl/test/ipdl/ok/mutualRecStructUnion.ipdl
ipc/ipdl/test/ipdl/ok/mutualRecUnion.ipdl
ipc/ipdl/test/ipdl/ok/namespace_Basic.ipdl
ipc/ipdl/test/ipdl/ok/noRedeclCrossMessage.ipdl
ipc/ipdl/test/ipdl/ok/plugin.ipdl
ipc/ipdl/test/ipdl/ok/selfRecUnion.ipdl
ipc/ipdl/test/ipdl/ok/shmem.ipdl
ipc/ipdl/test/ipdl/ok/syncProtocol.ipdl
ipc/ipdl/test/ipdl/ok/threeDirections.ipdl
ipc/ipdl/test/ipdl/ok/union_Basic.ipdl
ipc/ipdl/test/ipdl/ok/union_Namespaced.ipdl
testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-006.html.ini
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -945,21 +945,17 @@ pref("app.feedback.baseURL", "https://in
 
 // base URL for web-based marketing pages
 pref("app.productInfo.baseURL", "https://www.mozilla.org/firefox/features/");
 
 // Name of alternate about: page for certificate errors (when undefined, defaults to about:neterror)
 pref("security.alternate_certificate_error_page", "certerror");
 
 // Enable the new certificate error pages.
-#ifdef EARLY_BETA_OR_EARLIER
 pref("browser.security.newcerterrorpage.enabled", true);
-#else
-pref("browser.security.newcerterrorpage.enabled", false);
-#endif
 
 pref("browser.security.newcerterrorpage.mitm.enabled", true);
 pref("security.certerrors.recordEventTelemetry", true);
 pref("security.certerrors.permanentOverride", true);
 
 // Whether to start the private browsing mode at application startup
 pref("browser.privatebrowsing.autostart", false);
 
--- a/browser/base/content/test/tabs/browser_allow_process_switches_despite_related_browser.js
+++ b/browser/base/content/test/tabs/browser_allow_process_switches_despite_related_browser.js
@@ -16,16 +16,17 @@ add_task(async function() {
   BrowserViewSource(tab.linkedBrowser);
   let viewSourceTab = await promiseTab;
   registerCleanupFunction(async function() {
     BrowserTestUtils.removeTab(viewSourceTab);
   });
 
   let dummyPage = getChromeDir(getResolvedURI(gTestPath));
   dummyPage.append(DUMMY_FILE);
+  dummyPage.normalize();
   const uriString = Services.io.newFileURI(dummyPage).spec;
 
   let viewSourceBrowser = viewSourceTab.linkedBrowser;
   let promiseLoad =
     BrowserTestUtils.browserLoaded(viewSourceBrowser, false, uriString);
   BrowserTestUtils.loadURI(viewSourceBrowser, uriString);
   let href = await promiseLoad;
   is(href, uriString,
--- a/browser/base/content/test/tabs/browser_contextmenu_openlink_after_tabnavigated.js
+++ b/browser/base/content/test/tabs/browser_contextmenu_openlink_after_tabnavigated.js
@@ -15,29 +15,26 @@ add_task(async function test_contextmenu
   }, gBrowser.selectedBrowser);
   await awaitPopupShown;
   info("Popup Shown");
 
   info("Navigate the tab with the opened context menu");
   BrowserTestUtils.loadURI(gBrowser.selectedBrowser, "about:blank");
   await BrowserTestUtils.browserLoaded(gBrowser.selectedBrowser);
 
-  let awaitNewTabOpen = BrowserTestUtils.waitForNewTab(gBrowser, "http://example.com/");
+  let awaitNewTabOpen = BrowserTestUtils.waitForNewTab(gBrowser, "http://example.com/", true);
 
   info("Click the 'open link in new tab' menu item");
   let openLinkMenuItem = contextMenu.querySelector("#context-openlinkintab");
   openLinkMenuItem.click();
 
   info("Wait for the new tab to be opened");
   const newTab = await awaitNewTabOpen;
 
   // Close the contextMenu popup if it has not been closed yet.
   contextMenu.hidePopup();
 
-  await BrowserTestUtils.browserLoaded(newTab.linkedBrowser);
-  const newTabURL = await ContentTask.spawn(newTab.linkedBrowser, null, async function() {
-    return content.location.href;
-  });
-  is(newTabURL, "http://example.com/", "Got the expected URL loaded in the new tab");
+  is(newTab.linkedBrowser.currentURI.spec, "http://example.com/",
+     "Got the expected URL loaded in the new tab");
 
   BrowserTestUtils.removeTab(newTab);
   BrowserTestUtils.removeTab(tab);
 });
--- a/browser/components/BrowserGlue.jsm
+++ b/browser/components/BrowserGlue.jsm
@@ -1414,19 +1414,36 @@ BrowserGlue.prototype = {
       if (permission.type == "trackingprotection") {
         exceptions++;
       }
     }
     Services.telemetry.scalarSet("contentblocking.exceptions", exceptions);
 
     let fpEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.fingerprinting.enabled");
     let cmEnabled = Services.prefs.getBoolPref("privacy.trackingprotection.cryptomining.enabled");
+    let categoryPref;
+    switch (Services.prefs.getStringPref("browser.contentblocking.category", null)) {
+    case "standard":
+      categoryPref = 0;
+      break;
+    case "strict":
+      categoryPref = 1;
+      break;
+    case "custom":
+      categoryPref = 2;
+      break;
+    default:
+      // Any other value is unsupported.
+      categoryPref = 3;
+      break;
+    }
 
     Services.telemetry.scalarSet("contentblocking.fingerprinting_blocking_enabled", fpEnabled);
     Services.telemetry.scalarSet("contentblocking.cryptomining_blocking_enabled", cmEnabled);
+    Services.telemetry.scalarSet("contentblocking.category", categoryPref);
   },
 
   _sendMediaTelemetry() {
     let win = Services.appShell.hiddenDOMWindow;
     let v = win.document.createElementNS("http://www.w3.org/1999/xhtml", "video");
     v.reportCanPlayTelemetry();
   },
 
--- a/browser/components/customizableui/PanelMultiView.jsm
+++ b/browser/components/customizableui/PanelMultiView.jsm
@@ -1330,18 +1330,19 @@ var PanelView = class extends Associated
         "label" + isMultiline,
         "toolbarbutton[wrap]:not([hidden])",
       ].join(",");
       for (let element of this.node.querySelectorAll(selector)) {
         // Ignore items in hidden containers.
         if (element.closest("[hidden]")) {
           continue;
         }
+
         // Take the label for toolbarbuttons; it only exists on those elements.
-        element = element.labelElement || element;
+        element = element.multilineLabel || element;
 
         let bounds = element.getBoundingClientRect();
         let previous = gMultiLineElementsMap.get(element);
         // We don't need to (re-)apply the workaround for invisible elements or
         // on elements we've seen before and haven't changed in the meantime.
         if (!bounds.width || !bounds.height ||
             (previous && element.textContent == previous.textContent &&
                          bounds.width == previous.bounds.width)) {
--- a/browser/components/urlbar/UrlbarController.jsm
+++ b/browser/components/urlbar/UrlbarController.jsm
@@ -87,19 +87,18 @@ class UrlbarController {
 
   /**
    * Takes a query context and starts the query based on the user input.
    *
    * @param {UrlbarQueryContext} queryContext The query details.
    */
   async startQuery(queryContext) {
     // Cancel any running query.
-    if (this._lastQueryContext) {
-      this.cancelQuery(this._lastQueryContext);
-    }
+    this.cancelQuery();
+
     this._lastQueryContext = queryContext;
 
     queryContext.lastResultCount = 0;
     TelemetryStopwatch.start(TELEMETRY_1ST_RESULT, queryContext);
     TelemetryStopwatch.start(TELEMETRY_6_FIRST_RESULTS, queryContext);
 
     this._notify("onQueryStarted", queryContext);
     await this.manager.startQuery(queryContext, this);
@@ -169,21 +168,24 @@ class UrlbarController {
    *
    * @param {object} listener The listener to add.
    */
   removeQueryListener(listener) {
     this._listeners.delete(listener);
   }
 
   /**
-   * When switching tabs, clear some internal caches to handle cases like
-   * backspace, autofill or repeated searches.
+   * When the containing context changes (for example when switching tabs),
+   * clear any caches that connects consecutive searches in the same context.
+   * For example it can be used to clear information used to improve autofill
+   * or save resourced on repeated searches.
    */
-  tabContextChanged() {
-    // TODO: implementation needed (bug 1496685)
+  viewContextChanged() {
+    this.cancelQuery();
+    this._notify("onViewContextChanged");
   }
 
   /**
    * Receives keyboard events from the input and handles those that should
    * navigate within the view or pick the currently selected item.
    *
    * @param {KeyboardEvent} event
    *   The DOM KeyboardEvent.
--- a/browser/components/urlbar/UrlbarInput.jsm
+++ b/browser/components/urlbar/UrlbarInput.jsm
@@ -1102,17 +1102,17 @@ class UrlbarInput {
     }
   }
 
   _on_scrollend(event) {
     this._updateTextOverflow();
   }
 
   _on_TabSelect(event) {
-    this.controller.tabContextChanged();
+    this.controller.viewContextChanged();
   }
 
   _on_keydown(event) {
     this.controller.handleKeyNavigation(event);
     this._toggleActionOverride(event);
   }
 
   _on_keyup(event) {
--- a/browser/components/urlbar/UrlbarView.jsm
+++ b/browser/components/urlbar/UrlbarView.jsm
@@ -268,16 +268,26 @@ class UrlbarView {
       newSelectionIndex = this._queryContext.results.length - 1;
     }
     if (newSelectionIndex >= 0) {
       this.selectedIndex = newSelectionIndex;
     }
   }
 
   /**
+   * Notified when the view context changes, for example when switching tabs.
+   * It can be used to reset internal state tracking.
+   */
+  onViewContextChanged() {
+    // Clear rows, so that when reusing results we don't visually leak them
+    // across different contexts.
+    this._rows.textContent = "";
+  }
+
+  /**
    * Passes DOM events for the view to the _on_<event type> methods.
    * @param {Event} event
    *   DOM event from the <view>.
    */
   handleEvent(event) {
     let methodName = "_on_" + event.type;
     if (methodName in this) {
       this[methodName](event);
--- a/browser/docs/AddressBar.rst
+++ b/browser/docs/AddressBar.rst
@@ -254,19 +254,19 @@ View (e.g. showing/hiding a panel). It i
   UrlbarController {
     async startQuery(queryContext);
     cancelQuery(queryContext);
     // Invoked by the ProvidersManager when results are available.
     receiveResults(queryContext);
     // Used by the View to listen for results.
     addQueryListener(listener);
     removeQueryListener(listener);
-    // Used to indicate the View context changed, as such any cached information
-    // should be reset.
-    tabContextChanged();
+    // Used to indicate the View context changed, so that cached information
+    // about the latest search is no more relevant and can be dropped.
+    viewContextChanged();
   }
 
 
 The View
 =========
 
 The View is the component responsible for presenting search results to the
 user and handling their input.
@@ -342,18 +342,22 @@ Represents the base *View* implementatio
     // Invoked when the query starts.
     onQueryStarted(queryContext);
     // Invoked when new results are available.
     onQueryResults(queryContext);
     // Invoked when the query has been canceled.
     onQueryCancelled(queryContext);
     // Invoked when the query is done.
     onQueryFinished(queryContext);
+    // Invoked when the view context changed, so that cached information about
+    // the latest search is no more relevant and can be dropped.
+    onViewContextChanged();
   }
 
+
 UrlbarResult
 ===========
 
 An `UrlbarResult <https://dxr.mozilla.org/mozilla-central/source/browser/components/urlbar/UrlbarResult.jsm>`_
 instance represents a single search result with a result type, that
 identifies specific kind of results.
 Each kind has its own properties, that the *View* may support, and a few common
 properties, supported by all of the results.
@@ -394,16 +398,17 @@ The following RESULT_TYPEs are supported
     URL: 3,
     // Payload: { icon, url, keyword, postData }
     KEYWORD: 4,
     // Payload: { icon, keyword, title, content }
     OMNIBOX: 5,
     // Payload: { icon, url, device, title }
     REMOTE_TAB: 6,
 
+
 Shared Modules
 ==============
 
 Various modules provide shared utilities to the other components:
 
 `UrlbarPrefs.jsm <https://dxr.mozilla.org/mozilla-central/source/browser/components/urlbar/UrlbarPrefs.jsm>`_
 ----------------
 
--- a/config/external/nspr/pr/moz.build
+++ b/config/external/nspr/pr/moz.build
@@ -105,39 +105,42 @@ else:
 
 LOCAL_INCLUDES += [
     '/config/external/nspr',
     '/nsprpub/pr/include',
     '/nsprpub/pr/include/private',
 ]
 
 SOURCES += [
+    '/nsprpub/pr/src/io/prpolevt.c', # conflicting definition of PRFilePrivate
+    '/nsprpub/pr/src/misc/praton.c', # duplicate definition of index_hex
+    '/nsprpub/pr/src/misc/prcountr.c', # duplicate definition of QName, RName
+ ]
+
+UNIFIED_SOURCES += [
     '/nsprpub/pr/src/io/prfdcach.c',
     '/nsprpub/pr/src/io/priometh.c',
     '/nsprpub/pr/src/io/pripv6.c',
     '/nsprpub/pr/src/io/prlayer.c',
     '/nsprpub/pr/src/io/prlog.c',
     '/nsprpub/pr/src/io/prmapopt.c',
     '/nsprpub/pr/src/io/prmmap.c',
     '/nsprpub/pr/src/io/prmwait.c',
-    '/nsprpub/pr/src/io/prpolevt.c',
     '/nsprpub/pr/src/io/prprf.c',
     '/nsprpub/pr/src/io/prscanf.c',
     '/nsprpub/pr/src/io/prstdio.c',
     '/nsprpub/pr/src/linking/prlink.c',
     '/nsprpub/pr/src/malloc/prmalloc.c',
     '/nsprpub/pr/src/malloc/prmem.c',
     '/nsprpub/pr/src/md/prosdep.c',
     '/nsprpub/pr/src/memory/prseg.c',
     '/nsprpub/pr/src/memory/prshm.c',
     '/nsprpub/pr/src/memory/prshma.c',
     '/nsprpub/pr/src/misc/pralarm.c',
     '/nsprpub/pr/src/misc/pratom.c',
-    '/nsprpub/pr/src/misc/praton.c',
-    '/nsprpub/pr/src/misc/prcountr.c',
     '/nsprpub/pr/src/misc/prdtoa.c',
     '/nsprpub/pr/src/misc/prenv.c',
     '/nsprpub/pr/src/misc/prerr.c',
     '/nsprpub/pr/src/misc/prerror.c',
     '/nsprpub/pr/src/misc/prerrortable.c',
     '/nsprpub/pr/src/misc/prinit.c',
     '/nsprpub/pr/src/misc/prinrval.c',
     '/nsprpub/pr/src/misc/pripc.c',
@@ -153,41 +156,46 @@ SOURCES += [
     '/nsprpub/pr/src/misc/prtrace.c',
     '/nsprpub/pr/src/threads/prcmon.c',
     '/nsprpub/pr/src/threads/prrwlock.c',
     '/nsprpub/pr/src/threads/prtpd.c',
 ]
 
 if CONFIG['OS_TARGET'] != 'WINNT':
     DEFINES['_PR_PTHREADS'] = True
-    SOURCES += [
+    UNIFIED_SOURCES += [
         '/nsprpub/pr/src/md/unix/unix.c',
         '/nsprpub/pr/src/md/unix/unix_errors.c',
         '/nsprpub/pr/src/md/unix/uxproces.c',
         '/nsprpub/pr/src/md/unix/uxrng.c',
         '/nsprpub/pr/src/md/unix/uxshm.c',
         '/nsprpub/pr/src/md/unix/uxwrap.c',
         '/nsprpub/pr/src/pthreads/ptio.c',
         '/nsprpub/pr/src/pthreads/ptmisc.c',
         '/nsprpub/pr/src/pthreads/ptsynch.c',
         '/nsprpub/pr/src/pthreads/ptthread.c',
     ]
 else:
     SOURCES += [
+        # ntinrval.c needs windows.h without WIN32_LEAN_AND_MEAN, so it can't be
+        # unified after any file that pulled in windows.h in lean-and-mean mode.
+        '/nsprpub/pr/src/md/windows/ntinrval.c',
+        # w32poll.c needs a custom value of FD_SETSIZE for winsock.h.
+        '/nsprpub/pr/src/md/windows/w32poll.c',
+    ]
+    UNIFIED_SOURCES += [
         '/nsprpub/pr/src/io/prdir.c',
         '/nsprpub/pr/src/io/prfile.c',
         '/nsprpub/pr/src/io/prio.c',
         '/nsprpub/pr/src/io/prsocket.c',
         '/nsprpub/pr/src/md/windows/ntgc.c',
-        '/nsprpub/pr/src/md/windows/ntinrval.c',
         '/nsprpub/pr/src/md/windows/ntmisc.c',
         '/nsprpub/pr/src/md/windows/ntsec.c',
         '/nsprpub/pr/src/md/windows/ntsem.c',
         '/nsprpub/pr/src/md/windows/w32ipcsem.c',
-        '/nsprpub/pr/src/md/windows/w32poll.c',
         '/nsprpub/pr/src/md/windows/w32rng.c',
         '/nsprpub/pr/src/md/windows/w32shm.c',
         '/nsprpub/pr/src/md/windows/w95cv.c',
         '/nsprpub/pr/src/md/windows/w95dllmain.c',
         '/nsprpub/pr/src/md/windows/w95io.c',
         '/nsprpub/pr/src/md/windows/w95sock.c',
         '/nsprpub/pr/src/md/windows/w95thred.c',
         '/nsprpub/pr/src/md/windows/win32_errors.c',
--- a/devtools/client/aboutdebugging-new/src/components/RuntimePage.js
+++ b/devtools/client/aboutdebugging-new/src/components/RuntimePage.js
@@ -45,17 +45,17 @@ class RuntimePage extends PureComponent 
       otherWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
       runtimeDetails: Types.runtimeDetails,
       runtimeId: PropTypes.string.isRequired,
       serviceWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
       sharedWorkers: PropTypes.arrayOf(PropTypes.object).isRequired,
       showProfilerDialog: PropTypes.bool.isRequired,
       tabs: PropTypes.arrayOf(PropTypes.object).isRequired,
       temporaryExtensions: PropTypes.arrayOf(PropTypes.object).isRequired,
-      temporaryInstallError: PropTypes.string,
+      temporaryInstallError: PropTypes.object,
     };
   }
 
   // TODO: avoid the use of this method
   // https://bugzilla.mozilla.org/show_bug.cgi?id=1508688
   componentWillMount() {
     const { dispatch, runtimeId } = this.props;
     dispatch(Actions.selectPage(PAGE_TYPES.RUNTIME, runtimeId));
@@ -104,34 +104,46 @@ class RuntimePage extends PureComponent 
     const { runtimeDetails, temporaryInstallError } = this.props;
     const { type } = runtimeDetails.info;
 
     if (!temporaryInstallError ||
         !isSupportedDebugTargetPane(type, DEBUG_TARGET_PANE.TEMPORARY_EXTENSION)) {
       return null;
     }
 
+    let errorMessages = [temporaryInstallError.message];
+
+    // Additional error messages can be found in additionalErrors.
+    if (Array.isArray(temporaryInstallError.additionalErrors)) {
+      errorMessages = errorMessages.concat(temporaryInstallError.additionalErrors);
+    }
+
+    const errors = errorMessages.map((message, index) => {
+      return dom.div(
+        {
+          className: "technical-text",
+          key: "tmp-extension-install-error-" + index,
+        },
+        message
+      );
+    });
+
     return Message(
       {
         level: MESSAGE_LEVEL.ERROR,
       },
       dom.div(
         {},
         Localized(
           {
             id: "about-debugging-tmp-extension-install-error",
           },
           dom.span({}, "There was an error during the temporary add-on installation")
         ),
-        dom.div(
-          {
-            className: "technical-text",
-          },
-          temporaryInstallError
-        )
+        errors
       )
     );
   }
 
   render() {
     const {
       dispatch,
       installedExtensions,
--- a/devtools/client/aboutdebugging-new/src/reducers/ui-state.js
+++ b/devtools/client/aboutdebugging-new/src/reducers/ui-state.js
@@ -75,17 +75,17 @@ function uiReducer(state = UiState(), ac
     }
 
     case TEMPORARY_EXTENSION_INSTALL_SUCCESS: {
       return Object.assign({}, state, { temporaryInstallError: null });
     }
 
     case TEMPORARY_EXTENSION_INSTALL_FAILURE: {
       const { error } = action;
-      return Object.assign({}, state, { temporaryInstallError: error.message });
+      return Object.assign({}, state, { temporaryInstallError: error });
     }
 
     default:
       return state;
   }
 }
 
 module.exports = {
--- a/devtools/client/aboutdebugging-new/test/browser/browser.ini
+++ b/devtools/client/aboutdebugging-new/test/browser/browser.ini
@@ -10,17 +10,17 @@ support-files =
   helper-adb.js
   helper-addons.js
   helper-collapsibilities.js
   helper-mocks.js
   helper-real-usb.js
   helper-serviceworker.js
   helper-telemetry.js
   mocks/*
-  resources/bad-extension/*
+  resources/bad-extensions/*
   resources/packaged-extension/*
   resources/service-workers/*
   resources/test-adb-extension/*
   resources/test-temporary-extension/*
   test-tab-favicons.html
   !/devtools/client/shared/test/shared-head.js
   !/devtools/client/shared/test/shared-redux-head.js
   !/devtools/client/shared/test/telemetry-test-helpers.js
--- a/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_temporary_install_error.js
+++ b/devtools/client/aboutdebugging-new/test/browser/browser_aboutdebugging_addons_temporary_install_error.js
@@ -6,40 +6,65 @@
 /* import-globals-from helper-addons.js */
 Services.scriptloader.loadSubScript(CHROME_URL_ROOT + "helper-addons.js", this);
 
 /**
  * Test that the installation error messages are displayed when installing temporary
  * extensions.
  */
 
-const BAD_EXTENSION_PATH = "resources/bad-extension/manifest.json";
+const INVALID_JSON_EXTENSION_PATH = "resources/bad-extensions/invalid-json/manifest.json";
+const INVALID_PROP_EXTENSION_PATH =
+  "resources/bad-extensions/invalid-property/manifest.json";
 const EXTENSION_PATH = "resources/test-temporary-extension/manifest.json";
 const EXTENSION_NAME = "test-temporary-extension";
 
-add_task(async function() {
+// Extension with an invalid JSON manifest will not be parsed. We check the expected
+// error message is displayed
+add_task(async function testInvalidJsonExtension() {
   const { document, tab, window } = await openAboutDebugging();
   await selectThisFirefoxPage(document, window.AboutDebugging.store);
 
-  info("Install a bad extension");
-  // Do not use installTemporaryAddon here since the install will fail.
-  prepareMockFilePicker(BAD_EXTENSION_PATH);
-  document.querySelector(".js-temporary-extension-install-button").click();
-
-  info("Wait until the install error message appears");
-  await waitUntil(() => document.querySelector(".js-message"));
-  const installError = document.querySelector(".js-message");
+  const installError = await installBadExtension(INVALID_JSON_EXTENSION_PATH, document);
   ok(installError.textContent.includes("JSON.parse: unexpected keyword"),
     "The expected installation error is displayed: " + installError.textContent);
 
   info("Install a valid extension to make the message disappear");
   await installTemporaryExtension(EXTENSION_PATH, EXTENSION_NAME, document);
 
   info("Wait until the error message disappears");
   await waitUntil(() => !document.querySelector(".js-message"));
 
   info("Wait for the temporary addon to be displayed as a debug target");
   await waitUntil(() => findDebugTargetByText(EXTENSION_NAME, document));
 
   await removeTemporaryExtension(EXTENSION_NAME, document);
 
   await removeTab(tab);
 });
+
+// Extension with a valid JSON manifest but containing an invalid property should display
+// a detailed error message coming from the Addon Manager.
+add_task(async function testInvalidPropertyExtension() {
+  const { document, tab, window } = await openAboutDebugging();
+  await selectThisFirefoxPage(document, window.AboutDebugging.store);
+
+  const installError = await installBadExtension(INVALID_PROP_EXTENSION_PATH, document);
+
+  ok(installError.textContent.includes("Extension is invalid"),
+    "The basic installation error is displayed: " + installError.textContent);
+  ok(installError.textContent.includes(
+    "Reading manifest: Error processing content_scripts.0.matches"),
+    "The detailed installation error is also displayed: " + installError.textContent);
+
+  await removeTab(tab);
+});
+
+async function installBadExtension(path, document) {
+  info("Install a bad extension at path: " + path);
+  // Do not use installTemporaryAddon here since the install will fail.
+  prepareMockFilePicker(path);
+  document.querySelector(".js-temporary-extension-install-button").click();
+
+  info("Wait until the install error message appears");
+  await waitUntil(() => document.querySelector(".js-message"));
+  return document.querySelector(".js-message");
+}
rename from devtools/client/aboutdebugging-new/test/browser/resources/bad-extension/manifest.json
rename to devtools/client/aboutdebugging-new/test/browser/resources/bad-extensions/invalid-json/manifest.json
new file mode 100644
--- /dev/null
+++ b/devtools/client/aboutdebugging-new/test/browser/resources/bad-extensions/invalid-property/manifest.json
@@ -0,0 +1,26 @@
+{
+  "manifest_version": 2,
+  "name": "test-invalid-extension",
+  "version": "1",
+  "description": "the name says it all",
+  "permissions": [
+    "*://*.foo.com/*",
+    "alarms",
+    "notifications",
+    "tabs"
+  ],
+  "background": {
+    "scripts": ["background.js"]
+  },
+  "content_scripts": [{
+    "matches": "*://*.foo.com/*",
+    "js": ["content.js"]
+  }],
+  "browser_action": {
+    "default_icon": {
+      "32": "home.svg"
+    },
+    "default_title": "foobarbaz (v1)",
+    "browser_style": true
+  }
+}
\ No newline at end of file
--- a/devtools/client/aboutdebugging/aboutdebugging.css
+++ b/devtools/client/aboutdebugging/aboutdebugging.css
@@ -202,16 +202,22 @@ button {
 
 .addons-install-error .warning,
 .service-worker-multi-process .warning {
   /* The warning icon can be hard to see on red / yellow backgrounds, this turns the icon
   to a black icon. */
   fill: #0c0c0d;
 }
 
+.addons-install-error__additional-errors {
+  font-family: monospace;
+  font-size: 13px;
+  margin-block: 8px;
+}
+
 .addons-options {
   flex: 1;
 }
 
 .service-worker-disabled-label,
 .addons-debugging-label,
 .addons-web-ext-tip {
   display: inline-block;
--- a/devtools/client/aboutdebugging/components/addons/Controls.js
+++ b/devtools/client/aboutdebugging/components/addons/Controls.js
@@ -62,17 +62,17 @@ class AddonsControls extends Component {
 
   installAddon(file) {
     AddonManager.installTemporaryAddon(file)
       .then(() => {
         this.setState({ lastInstallErrorFile: null });
       })
       .catch(e => {
         console.error(e);
-        this.setState({ installError: e.message, lastInstallErrorFile: file });
+        this.setState({ installError: e, lastInstallErrorFile: file });
       });
   }
 
   render() {
     const { debugDisabled } = this.props;
 
     return dom.div({ className: "addons-top" },
       dom.div({ className: "addons-controls" },
--- a/devtools/client/aboutdebugging/components/addons/InstallError.js
+++ b/devtools/client/aboutdebugging/components/addons/InstallError.js
@@ -12,32 +12,41 @@ const dom = require("devtools/client/sha
 const Services = require("Services");
 
 const Strings = Services.strings.createBundle(
   "chrome://devtools/locale/aboutdebugging.properties");
 
 class AddonsInstallError extends Component {
   static get propTypes() {
     return {
-      error: PropTypes.string,
+      error: PropTypes.object,
       retryInstall: PropTypes.func,
     };
   }
 
   render() {
+    const { error } = this.props;
     if (!this.props.error) {
       return null;
     }
-    const text = Strings.formatStringFromName("addonInstallError", [this.props.error], 1);
+    const text = Strings.formatStringFromName("addonInstallError", [error.message], 1);
+
+    const additionalErrors = Array.isArray(error.additionalErrors) ?
+      dom.div(
+        { className: "addons-install-error__additional-errors" },
+        error.additionalErrors.join(" ")
+      ) : null;
+
     return dom.div(
       { className: "addons-install-error" },
       dom.span(
         {},
         dom.div({ className: "warning" }),
         dom.span({}, text),
+        additionalErrors
       ),
       dom.button(
         { className: "addons-install-retry", onClick: this.props.retryInstall },
         Strings.GetStringFromName("retryTemporaryInstall")));
   }
 }
 
 module.exports = AddonsInstallError;
--- a/devtools/client/framework/menu.js
+++ b/devtools/client/framework/menu.js
@@ -92,17 +92,17 @@ Menu.prototype.popup = function(screenX,
   // opening a new one.
   let popup = popupset.querySelector("menupopup[menu-api=\"true\"]");
   if (popup) {
     popup.hidePopup();
   }
 
   popup = doc.createXULElement("menupopup");
   popup.setAttribute("menu-api", "true");
-  popup.setAttribute("consumeoutsideclicks", "true");
+  popup.setAttribute("consumeoutsideclicks", "false");
 
   if (this.id) {
     popup.id = this.id;
   }
   this._createMenuItems(popup);
 
   // Remove the menu from the DOM once it's hidden.
   popup.addEventListener("popuphidden", (e) => {
--- a/devtools/client/netmonitor/src/assets/styles/NetworkDetailsPanel.css
+++ b/devtools/client/netmonitor/src/assets/styles/NetworkDetailsPanel.css
@@ -203,16 +203,31 @@
   color: inherit;
   padding-inline-start: 3px;
 }
 
 .theme-dark .network-monitor .tabpanel-summary-value {
   color: var(--theme-selection-color);
 }
 
+.network-monitor .tracking-protection {
+  background-color: var(--toolbarbutton-background);
+  color: inherit;
+  margin-top: 2px;
+  margin-bottom: 2px;
+}
+
+.theme-dark .network-monitor .tracking-protection .tracking-resource {
+  filter: brightness(500%);
+}
+
+.theme-light .network-monitor .tracking-protection .tracking-resource {
+  filter: brightness(0);
+}
+
 .theme-dark .network-monitor .edit-and-resend-button  {
   background-color: var(--toolbarbutton-background);
   color: var(--theme-selection-color);
 }
 
 .summary-edit-and-resend {
   display: flex;
   align-items: center;
--- a/devtools/client/netmonitor/src/assets/styles/RequestList.css
+++ b/devtools/client/netmonitor/src/assets/styles/RequestList.css
@@ -379,17 +379,17 @@
   background-image: url(chrome://devtools/skin/images/globe-small.svg);
 }
 
 .tracking-resource {
   display: inline-block;
   width: 16px;
   height: 16px;
   margin: 0 3px 0 -3px;
-  vertical-align: text-bottom;
+  vertical-align: middle;
   background-image: url(chrome://devtools/content/netmonitor/src/assets/icons/shield.svg);
   background-repeat: no-repeat;
 }
 
 .selected .tracking-resource {
   filter: brightness(500%);
 }
 
--- a/devtools/client/netmonitor/src/components/HeadersPanel.js
+++ b/devtools/client/netmonitor/src/components/HeadersPanel.js
@@ -10,16 +10,17 @@ const dom = require("devtools/client/sha
 const {
   getFormattedIPAndPort,
   getFormattedSize,
 } = require("../utils/format-utils");
 const { L10N } = require("../utils/l10n");
 const {
   getHeadersURL,
   getHTTPStatusCodeURL,
+  getTrackingProtectionURL,
 } = require("../utils/mdn-utils");
 const {
   fetchNetworkUpdatePacket,
   writeHeaderText,
 } = require("../utils/request-utils");
 const {
   HeadersProvider,
   HeaderList,
@@ -353,16 +354,17 @@ class HeadersPanel extends Component {
         remotePort,
         requestHeaders,
         requestHeadersFromUploadStream: uploadHeaders,
         responseHeaders,
         status,
         statusText,
         urlDetails,
         referrerPolicy,
+        isThirdPartyTrackingResource,
       },
     } = this.props;
     const item = { fromCache, fromServiceWorker, status, statusText };
 
     if ((!requestHeaders || !requestHeaders.headers.length) &&
         (!uploadHeaders || !uploadHeaders.headers.length) &&
         (!responseHeaders || !responseHeaders.headers.length)) {
       return div({ className: "empty-notice" },
@@ -411,16 +413,37 @@ class HeadersPanel extends Component {
             title: SUMMARY_STATUS_LEARN_MORE,
           }) : span({
             className: "headers-summary learn-more-link",
           }),
         )
       );
     }
 
+    let trackingProtectionStatus;
+
+    if (isThirdPartyTrackingResource) {
+      const trackingProtectionDocURL = getTrackingProtectionURL();
+
+      trackingProtectionStatus = (
+        div({ className: "tabpanel-summary-container tracking-protection" },
+          div({
+            className: "tracking-resource",
+          }),
+          L10N.getStr("netmonitor.trackingResource.tooltip"),
+          trackingProtectionDocURL ? MDNLink({
+            url: trackingProtectionDocURL,
+            title: SUMMARY_STATUS_LEARN_MORE,
+          }) : span({
+            className: "headers-summary learn-more-link",
+          }),
+        )
+      );
+    }
+
     const summaryVersion = httpVersion ?
       this.renderSummary(SUMMARY_VERSION, httpVersion) : null;
 
     const summaryReferrerPolicy = referrerPolicy ?
       this.renderSummary(SUMMARY_REFERRER_POLICY, referrerPolicy) : null;
 
     const summaryEditAndResendBtn = (
       div({
@@ -432,16 +455,17 @@ class HeadersPanel extends Component {
         }, EDIT_AND_RESEND)
       )
     );
 
     return (
       div({ className: "panel-container" },
         div({ className: "headers-overview" },
           summaryUrl,
+          trackingProtectionStatus,
           summaryMethod,
           summaryAddress,
           summaryStatus,
           summaryVersion,
           summaryEditAndResendBtn,
         ),
         PropertiesView({
           object,
--- a/devtools/client/netmonitor/src/utils/mdn-utils.js
+++ b/devtools/client/netmonitor/src/utils/mdn-utils.js
@@ -209,15 +209,25 @@ function getPerformanceAnalysisURL() {
  *
  * @return {string} The MDN URL for the documentation of Filter box.
  */
 function getFilterBoxURL() {
   return `${MDN_URL}Tools/Network_Monitor/request_list${getGAParams()}` +
     `#Filtering_by_properties`;
 }
 
+/**
+ * Get the MDN URL for Tracking Protection
+ *
+ * @return {string} The MDN URL for the documentation of Tracking Protection.
+ */
+function getTrackingProtectionURL() {
+  return `${MDN_URL}Mozilla/Firefox/Privacy/Tracking_Protection${getGAParams()}`;
+}
+
 module.exports = {
   getHeadersURL,
   getHTTPStatusCodeURL,
   getNetMonitorTimingsURL,
   getPerformanceAnalysisURL,
   getFilterBoxURL,
+  getTrackingProtectionURL,
 };
--- a/devtools/client/themes/changes.css
+++ b/devtools/client/themes/changes.css
@@ -1,33 +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/. */
 
  /* CSS Variables specific to the Changes panel that aren't defined by the themes */
  :root {
-   --changes-button-background-color: var(--grey-90-a10);
-   --changes-button-background-color-hover: var(--grey-90-a15);
-   --changes-button-background-color-active: var(--grey-90-a20);
+   --changes-button-copy-all-background-color--hover: var(--grey-90-a10);
+   --changes-button-copy-all-background-color--active: var(--grey-90-a15);
+   --changes-button-copy-rule-background-color: var(--grey-90-a10);
+   --changes-button-copy-rule-background-color--hover: var(--grey-90-a15);
+   --changes-button-copy-rule-background-color--active: var(--grey-90-a20);
    --diff-add-background-color: #f1feec;
    --diff-add-text-color: #54983f;
    --diff-remove-background-color: #fbf2f5;
    --diff-remove-text-color: #bf7173;
    --diff-source-background: var(--theme-toolbar-background);
    --diff-level: 0;
    --diff-level-offset: 10px;
    /*
     Minimum padding so content on the first level (zero) isn't touching the edge. Added
     and removed lines will re-declare this to add extra padding to clear the +/- icons.
    */
    --diff-level-min-offset: 5px;
  }
 
 :root.theme-dark {
-  --changes-button-background-color: #252526;
+  --changes-button-copy-all-background-color--hover: var(--grey-10-a10);
+  --changes-button-copy-all-background-color--active: var(--grey-10-a15);
+  --changes-button-copy-rule-background-color: var(--grey-10-a10);
+  --changes-button-copy-rule-background-color--hover: var(--grey-10-a15);
+  --changes-button-copy-rule-background-color--active: var(--grey-10-a20);
   --diff-add-background-color: rgba(18, 188, 0, 0.15);
   --diff-add-text-color: #12BC00;
   --diff-remove-background-color: rgba(255, 0, 57, 0.15);
   --diff-remove-text-color: #FF0039;
   --diff-source-background: #222225;
 }
 
 :root[dir="rtl"] {
@@ -79,44 +85,66 @@
   padding-bottom: 3px;
   padding-left: calc(var(--diff-level-min-offset) +
                      var(--diff-level-offset) * var(--diff-level));
 }
 
 .changes__copy-all-changes-button {
   -moz-context-properties: fill;
   background: url(chrome://devtools/skin/images/copy.svg) no-repeat;
+  background-position: 4px 3px;
   background-size: 16px;
   border: none;
+  border-radius: 3px;
   color: var(--theme-body-color);
   fill: currentColor;
-  height: 16px;
-  margin: 7px 10px;
-  padding-left: 21px;
+  margin: 2px 5px;
+  padding: 4px 5px 4px 25px;
+}
+
+.changes__copy-all-changes-button:hover {
+  background-color: var(--changes-button-copy-all-background-color--hover);
+}
+
+.changes__copy-all-changes-button:active {
+  background-color: var(--changes-button-copy-all-background-color--active);
 }
 
 /* Hide the Copy Rule button by default. */
 .changes__copy-rule-button {
-  background-color: var(--changes-button-background-color);
-  border-radius: 5px;
+  /**
+   * The rgba() format of the background colors makes the button see-through and it looks
+   * bad when stacked on top of long selectors.
+   *
+   * To solve this and not change the color format which is inherited from the Photon
+   * color guide in `client/themes/variables.css`, we use a blending trick to overlay the
+   * rgba() color value onto a solid color used for the panel background (achieved with
+   * a linear gradient with no transition). This keeps the rgba() color, but prevents the
+   * see-through effect.
+   */
+  background-blend-mode: overlay;
+  background-color: var(--changes-button-copy-rule-background-color);
+  background-image:
+    linear-gradient(var(--theme-sidebar-background), var(--theme-sidebar-background));
+  border-radius: 8px;
   border: none;
   color: var(--theme-body-color);
   display: none;
-  padding: 1px 5px;
+  padding: 1px 7px;
   position: absolute;
   right: 5px;
   top: 2px;
 }
 
 .changes__copy-rule-button:hover {
-  background-color: var(--changes-button-background-color-hover);
+  background-color: var(--changes-button-copy-rule-background-color--hover);
 }
 
 .changes__copy-rule-button:active {
-  background-color: var(--changes-button-background-color-active);
+  background-color: var(--changes-button-copy-rule-background-color--active);
 }
 
 .changes__rule {
   position: relative;
 }
 
 .changes__selector {
   word-wrap: break-word;
--- a/devtools/client/themes/variables.css
+++ b/devtools/client/themes/variables.css
@@ -238,16 +238,19 @@
   --green-70: #058b00;
 
   --yellow-50: #ffe900;
   --yellow-60: #d7b600;
   --yellow-65: #be9b00;
   --yellow-80: #715100;
 
   --grey-10: #f9f9fa;
+  --grey-10-a10: rgba(249, 249, 250, 0.1);
+  --grey-10-a15: rgba(249, 249, 250, 0.15);
+  --grey-10-a20: rgba(249, 249, 250, 0.2);
   --grey-20: #ededf0;
   --grey-25: #e0e0e2;
   --grey-30: #d7d7db;
   --grey-40: #b1b1b3;
   --grey-45: #939395;
   --grey-50: #737373;
   --grey-55: #5c5c5f;
   --grey-60: #4a4a4f;
--- a/devtools/client/webconsole/components/ConsoleOutput.js
+++ b/devtools/client/webconsole/components/ConsoleOutput.js
@@ -68,17 +68,20 @@ class ConsoleOutput extends Component {
 
   constructor(props) {
     super(props);
     this.onContextMenu = this.onContextMenu.bind(this);
     this.maybeScrollToBottom = this.maybeScrollToBottom.bind(this);
   }
 
   componentDidMount() {
-    scrollToBottom(this.outputNode);
+    if (this.props.visibleMessages.length > 0) {
+      scrollToBottom(this.outputNode);
+    }
+
     const {
       serviceContainer,
       onFirstMeaningfulPaint,
       dispatch,
     } = this.props;
     serviceContainer.attachRefToWebConsoleUI("outputScroller", this.outputNode);
 
     // Waiting for the next paint.
@@ -202,17 +205,19 @@ class ConsoleOutput extends Component {
         },
       }, messageNodes
       )
     );
   }
 }
 
 function scrollToBottom(node) {
-  node.scrollTop = node.scrollHeight;
+  if (node.scrollHeight > node.clientHeight) {
+    node.scrollTop = node.scrollHeight;
+  }
 }
 
 function isScrolledToBottom(outputNode, scrollNode) {
   const lastNodeHeight = outputNode.lastChild ?
                        outputNode.lastChild.clientHeight : 0;
   return scrollNode.scrollTop + scrollNode.clientHeight >=
          scrollNode.scrollHeight - lastNodeHeight / 2;
 }
--- a/dom/base/MaybeCrossOriginObject.cpp
+++ b/dom/base/MaybeCrossOriginObject.cpp
@@ -446,14 +446,44 @@ bool MaybeCrossOriginObject<Base>::enume
   JS::Rooted<JSObject*> self(cx, proxy);
   if (!MaybeWrapObject(cx, &self)) {
     return false;
   }
 
   return js::GetPropertyKeys(cx, self, 0, &props);
 }
 
+template <typename Base>
+bool MaybeCrossOriginObject<Base>::hasInstance(JSContext* cx,
+                                               JS::Handle<JSObject*> proxy,
+                                               JS::MutableHandle<JS::Value> v,
+                                               bool* bp) const {
+  if (!IsPlatformObjectSameOrigin(cx, proxy)) {
+    // In the cross-origin case we never have @@hasInstance, and we're never
+    // callable, so just go ahead and report an error.  If we enter the realm of
+    // "proxy" to do that, our caller won't be able to do anything with the
+    // exception, so instead let's wrap "proxy" into our realm.  We definitely
+    // do NOT want to call JS::InstanceofOperator here after entering "proxy's"
+    // realm, because that would do the wrong thing with @@hasInstance on the
+    // object by seeing any such definitions when we should not.
+    JS::Rooted<JS::Value> val(cx, JS::ObjectValue(*proxy));
+    if (!MaybeWrapValue(cx, &val)) {
+      return false;
+    }
+    return js::ReportIsNotFunction(cx, val);
+  }
+
+  // Safe to enter the realm of "proxy" and do the normal thing of looking up
+  // @@hasInstance, etc.
+  JSAutoRealm ar(cx, proxy);
+  JS::Rooted<JS::Value> val(cx, v);
+  if (!MaybeWrapValue(cx, &val)) {
+    return false;
+  }
+  return JS::InstanceofOperator(cx, proxy, val, bp);
+}
+
 // Force instantiations of the out-of-line template methods we need.
 template class MaybeCrossOriginObject<js::Wrapper>;
 template class MaybeCrossOriginObject<DOMProxyHandler>;
 
 }  // namespace dom
 }  // namespace mozilla
--- a/dom/base/MaybeCrossOriginObject.h
+++ b/dom/base/MaybeCrossOriginObject.h
@@ -314,16 +314,24 @@ class MaybeCrossOriginObject : public Ba
 
   /**
    * Spidermonkey-internal hook for enumerating objects.
    */
   bool enumerate(JSContext* cx, JS::Handle<JSObject*> proxy,
                  JS::AutoIdVector& props) const final;
 
   /**
+   * Spidermonkey-internal hook used for instanceof.  We need to override this
+   * because otherwise we can end up doing instanceof work in the wrong
+   * compartment.
+   */
+  bool hasInstance(JSContext* cx, JS::Handle<JSObject*> proxy,
+                   JS::MutableHandle<JS::Value> v, bool* bp) const final;
+
+  /**
    * Spidermonkey-internal hook used by Object.prototype.toString.  Subclasses
    * need to implement this, because we don't know what className they want.
    * Except in the cross-origin case, when we could maybe handle it...
    */
   const char* className(JSContext* cx,
                         JS::Handle<JSObject*> proxy) const override = 0;
 };
 
new file mode 100644
--- /dev/null
+++ b/dom/base/crashtests/1528675.html
@@ -0,0 +1,28 @@
+<script>
+function start() {
+  o14=window.document;
+  o432=document.createElement('audio');
+  o433=document.createElement('track');
+  o432.appendChild(o433);
+  o493=o432.textTracks;
+    o14.write('<html></html>');
+  o757=document.createElement('iframe');
+  o757.addEventListener('load', fun0, false);
+    document.documentElement.appendChild(o757);
+  o432.controls^=1;
+}
+function fun0(e) {
+  o1062=e.target;
+  o1063=o1062.contentWindow;
+  o1064=o1063.document;
+  document.documentElement.appendChild(o432);
+  setTimeout(fun1,240);
+}
+function fun1() {
+  o433.parentNode.removeChild(o433);
+  document.replaceChild(o1064.documentElement,document.documentElement);
+  SpecialPowers.forceGC();
+  SpecialPowers.forceCC();
+}
+</script>
+<body onload="start()"></body>
--- a/dom/base/crashtests/crashtests.list
+++ b/dom/base/crashtests/crashtests.list
@@ -241,11 +241,12 @@ load 1458016.html
 load 1459688.html
 load 1460794.html
 load 1462548.html
 load 1505811.html
 load 1505875.html
 load 1508845.html
 load 1516289.html
 load 1516560.html
+load 1528675.html
 load structured_clone_container_throws.html
 load xhr_empty_datauri.html
 load xhr_html_nullresponse.html
--- a/dom/bindings/Codegen.py
+++ b/dom/bindings/Codegen.py
@@ -9909,17 +9909,17 @@ class CGStaticMethodJitinfo(CGGeneric):
     """
     def __init__(self, method):
         CGGeneric.__init__(
             self,
             "\n"
             "static const JSJitInfo %s_methodinfo = {\n"
             "  { (JSJitGetterOp)%s },\n"
             "  { prototypes::id::_ID_Count }, { 0 }, JSJitInfo::StaticMethod,\n"
-            "  JSJitInfo::AliasEverything, JSVAL_TYPE_MISSING, false, false,\n"
+            "  JSJitInfo::AliasEverything, JSVAL_TYPE_OBJECT, false, false,\n"
             "  false, false, 0\n"
             "};\n" %
             (IDLToCIdentifier(method.identifier.name),
              CppKeywords.checkMethodName(
                  IDLToCIdentifier(method.identifier.name))))
 
 
 def getEnumValueName(value):
--- a/dom/tests/mochitest/bugs/mochitest.ini
+++ b/dom/tests/mochitest/bugs/mochitest.ini
@@ -143,10 +143,11 @@ skip-if = toolkit == 'android' || os == 
 skip-if = toolkit == 'android' #Windows can't change size on Android
 [test_toJSON.html]
 [test_window_bar.html]
 skip-if = toolkit == 'android'
 [test_bug1022869.html]
 [test_bug1112040.html]
 [test_bug1160342_marquee.html]
 [test_bug1171215.html]
+[test_bug1530292.html]
 [test_no_find_showDialog.html]
 skip-if = toolkit == 'android' # Bug 1358633 - window.find doesn't work for Android
new file mode 100644
--- /dev/null
+++ b/dom/tests/mochitest/bugs/test_bug1530292.html
@@ -0,0 +1,47 @@
+<!DOCTYPE HTML>
+<html>
+<!--
+https://bugzilla.mozilla.org/show_bug.cgi?id=1530292
+-->
+<head>
+  <meta charset="utf-8">
+  <title>Test for Bug 1530292</title>
+  <script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+  <link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
+  <script type="application/javascript">
+
+  /** Test for Bug 1530292 **/
+  SimpleTest.waitForExplicitFinish();
+  addLoadEvent(() => {
+    // This is really a crashtest, but we need some cross-origin (and hence
+    // cross-compartment) windows to test it, so can't use the crashtest
+    // harness.
+    try {
+      ({} instanceof frames[0]);
+      ok(false, "Should have thrown for same-process window");
+    } catch (e) {
+      is(e.message, "frames[0] is not a function");
+    }
+    try {
+      ({} instanceof frames[1]);
+      ok(false, "Should have thrown for maybe other-process window");
+    } catch (e) {
+      is(e.message, "frames[1] is not a function");
+    }
+    SimpleTest.finish();
+  });
+  </script>
+</head>
+<body>
+<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1530292">Mozilla Bug 1530292</a>
+<p id="display"></p>
+<div id="content" style="display: none">
+  <!-- Cross-origin but same-site; must be same-process -->
+  <iframe src="//test1.mochi.test:8888/tests/dom/tests/mochitest/bugs/file_empty.html"></iframe>
+  <!-- Completely cross-origin; might be cross-process -->
+  <iframe src="//example.org/tests/dom/tests/mochitest/bugs/file_empty.html"></iframe>
+</div>
+<pre id="test">
+</pre>
+</body>
+</html>
--- a/gfx/2d/Types.h
+++ b/gfx/2d/Types.h
@@ -513,17 +513,17 @@ constexpr int eCornerCount = 4;
 static inline Corner operator++(Corner& aCorner) {
   MOZ_ASSERT(aCorner >= eCornerTopLeft && aCorner <= eCornerBottomLeft,
              "Out of range corner!");
   aCorner = Corner(aCorner + 1);
   return aCorner;
 }
 
 // Indices into "half corner" arrays (nsStyleCorners e.g.)
-enum HalfCorner {
+enum HalfCorner : uint8_t {
   // This order is important!
   eCornerTopLeftX = 0,
   eCornerTopLeftY = 1,
   eCornerTopRightX = 2,
   eCornerTopRightY = 3,
   eCornerBottomRightX = 4,
   eCornerBottomRightY = 5,
   eCornerBottomLeftX = 6,
--- a/gfx/wr/webrender/src/device/gl.rs
+++ b/gfx/wr/webrender/src/device/gl.rs
@@ -2340,28 +2340,24 @@ impl Device {
     fn create_vao_with_vbos(
         &mut self,
         descriptor: &VertexDescriptor,
         main_vbo_id: VBOId,
         instance_vbo_id: VBOId,
         ibo_id: IBOId,
         owns_vertices_and_indices: bool,
     ) -> VAO {
-        debug_assert!(self.inside_frame);
-
         let instance_stride = descriptor.instance_stride() as usize;
         let vao_id = self.gl.gen_vertex_arrays(1)[0];
 
-        self.gl.bind_vertex_array(vao_id);
+        self.bind_vao_impl(vao_id);
 
         descriptor.bind(self.gl(), main_vbo_id, instance_vbo_id);
         ibo_id.bind(self.gl()); // force it to be a part of VAO
 
-        self.gl.bind_vertex_array(0);
-
         VAO {
             id: vao_id,
             ibo_id,
             main_vbo_id,
             instance_vbo_id,
             instance_stride,
             owns_vertices_and_indices,
         }
@@ -2369,32 +2365,30 @@ impl Device {
 
     pub fn create_custom_vao(
         &mut self,
         streams: &[Stream],
     ) -> CustomVAO {
         debug_assert!(self.inside_frame);
 
         let vao_id = self.gl.gen_vertex_arrays(1)[0];
-        self.gl.bind_vertex_array(vao_id);
+        self.bind_vao_impl(vao_id);
 
         let mut attrib_index = 0;
         for stream in streams {
             VertexDescriptor::bind_attributes(
                 stream.attributes,
                 attrib_index,
                 0,
                 self.gl(),
                 stream.vbo,
             );
             attrib_index += stream.attributes.len();
         }
 
-        self.gl.bind_vertex_array(0);
-
         CustomVAO {
             id: vao_id,
         }
     }
 
     pub fn delete_custom_vao(&mut self, mut vao: CustomVAO) {
         self.gl.delete_vertex_arrays(&[vao.id]);
         vao.id = 0;
--- a/gfx/wr/webrender/src/renderer.rs
+++ b/gfx/wr/webrender/src/renderer.rs
@@ -4241,16 +4241,20 @@ impl Renderer {
         self.debug_flags = flags;
     }
 
     pub fn save_cpu_profile(&self, filename: &str) {
         write_profile(filename);
     }
 
     fn draw_frame_debug_items(&mut self, items: &[DebugItem]) {
+        if items.is_empty() {
+            return;
+        }
+
         let debug_renderer = match self.debug.get_mut(&mut self.device) {
             Some(render) => render,
             None => return,
         };
 
         for item in items {
             match item {
                 DebugItem::Rect { rect, color } => {
--- a/ipc/ipdl/ipdl/direct_call.py
+++ b/ipc/ipdl/ipdl/direct_call.py
@@ -133,16 +133,308 @@ DIRECT_CALL_OVERRIDES = {
     ("PVRGPU", "child"): ("VRGPUChild", "VRGPUChild.h"),
     ("PVRGPU", "parent"): ("VRGPUParent", "VRGPUParent.h"),
     ("PVRLayer", "child"): ("VRLayerChild", "VRLayerChild.h"),
     ("PVRManager", "child"): ("VRManagerChild", "VRManagerChild.h"),
     ("PVRManager", "parent"): ("VRManagerParent", "VRManagerParent.h"),
 
     ("PWebSocket", "child"): ("WebSocketChannelChild", "mozilla/net/WebSocketChannelChild.h"),
     ("PWebSocket", "parent"): ("WebSocketChannelParent", "mozilla/net/WebSocketChannelParent.h"),
+
+    # _ipdltest
+    ("PTestActorPunning", "child"): (
+        "TestActorPunningChild", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+    ("PTestActorPunning", "parent"): (
+        "TestActorPunningParent", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+    ("PTestActorPunningPunned", "child"): (
+        "TestActorPunningPunnedChild", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+    ("PTestActorPunningPunned", "parent"): (
+        "TestActorPunningPunnedParent", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+    ("PTestActorPunningSub", "child"): (
+        "TestActorPunningSubChild", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+    ("PTestActorPunningSub", "parent"): (
+        "TestActorPunningSubParent", "mozilla/_ipdltest/TestActorPunning.h"
+    ),
+
+    ("PTestAsyncReturns", "child"): (
+        "TestAsyncReturnsChild", "mozilla/_ipdltest/TestAsyncReturns.h"
+    ),
+    ("PTestAsyncReturns", "parent"): (
+        "TestAsyncReturnsParent", "mozilla/_ipdltest/TestAsyncReturns.h"
+    ),
+
+    ("PTestBadActor", "parent"): ("TestBadActorParent", "mozilla/_ipdltest/TestBadActor.h"),
+    ("PTestBadActor", "child"): ("TestBadActorChild", "mozilla/_ipdltest/TestBadActor.h"),
+    ("PTestBadActorSub", "child"): ("TestBadActorSubChild", "mozilla/_ipdltest/TestBadActor.h"),
+    ("PTestBadActorSub", "parent"): ("TestBadActorSubParent", "mozilla/_ipdltest/TestBadActor.h"),
+
+    ("PTestCancel", "child"): ("TestCancelChild", "mozilla/_ipdltest/TestCancel.h"),
+    ("PTestCancel", "parent"): ("TestCancelParent", "mozilla/_ipdltest/TestCancel.h"),
+
+    ("PTestCrashCleanup", "child"): (
+        "TestCrashCleanupChild", "mozilla/_ipdltest/TestCrashCleanup.h"
+    ),
+    ("PTestCrashCleanup", "parent"): (
+        "TestCrashCleanupParent", "mozilla/_ipdltest/TestCrashCleanup.h"
+    ),
+
+    ("PTestDataStructures", "child"): (
+        "TestDataStructuresChild", "mozilla/_ipdltest/TestDataStructures.h"
+    ),
+    ("PTestDataStructures", "parent"): (
+        "TestDataStructuresParent", "mozilla/_ipdltest/TestDataStructures.h"
+    ),
+    ("PTestDataStructuresSub", "child"): (
+        "TestDataStructuresSub", "mozilla/_ipdltest/TestDataStructures.h"
+    ),
+    ("PTestDataStructuresSub", "parent"): (
+        "TestDataStructuresSub", "mozilla/_ipdltest/TestDataStructures.h"
+    ),
+
+    ("PTestDemon", "child"): ("TestDemonChild", "mozilla/_ipdltest/TestDemon.h"),
+    ("PTestDemon", "parent"): ("TestDemonParent", "mozilla/_ipdltest/TestDemon.h"),
+
+    ("PTestDesc", "child"): ("TestDescChild", "mozilla/_ipdltest/TestDesc.h"),
+    ("PTestDesc", "parent"): ("TestDescParent", "mozilla/_ipdltest/TestDesc.h"),
+    ("PTestDescSub", "child"): ("TestDescSubChild", "mozilla/_ipdltest/TestDesc.h"),
+    ("PTestDescSub", "parent"): ("TestDescSubParent", "mozilla/_ipdltest/TestDesc.h"),
+    ("PTestDescSubsub", "child"): ("TestDescSubsubChild", "mozilla/_ipdltest/TestDesc.h"),
+    ("PTestDescSubsub", "parent"): ("TestDescSubsubParent", "mozilla/_ipdltest/TestDesc.h"),
+
+    ("PTestEndpointBridgeMain", "child"): (
+        "TestEndpointBridgeMainChild", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+    ("PTestEndpointBridgeMain", "parent"): (
+        "TestEndpointBridgeMainParent", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+    ("PTestEndpointBridgeMainSub", "child"): (
+        "TestEndpointBridgeMainSubChild", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+    ("PTestEndpointBridgeMainSub", "parent"): (
+        "TestEndpointBridgeMainSubParent", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+    ("PTestEndpointBridgeSub", "child"): (
+        "TestEndpointBridgeSubChild", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+    ("PTestEndpointBridgeSub", "parent"): (
+        "TestEndpointBridgeSubParent", "mozilla/_ipdltest/TestEndpointBridgeMain.h"
+    ),
+
+    ("PTestEndpointOpens", "child"): (
+        "TestEndpointOpensChild", "mozilla/_ipdltest/TestEndpointOpens.h"
+    ),
+    ("PTestEndpointOpens", "parent"): (
+        "TestEndpointOpensParent", "mozilla/_ipdltest/TestEndpointOpens.h"
+    ),
+    ("PTestEndpointOpensOpened", "child"): (
+        "TestEndpointOpensOpenedChild", "mozilla/_ipdltest/TestEndpointOpens.h"
+    ),
+    ("PTestEndpointOpensOpened", "parent"): (
+        "TestEndpointOpensOpenedParent", "mozilla/_ipdltest/TestEndpointOpens.h"
+    ),
+
+    ("PTestFailedCtor", "child"): ("TestFailedCtorChild", "mozilla/_ipdltest/TestFailedCtor.h"),
+    ("PTestFailedCtor", "parent"): ("TestFailedCtorParent", "mozilla/_ipdltest/TestFailedCtor.h"),
+    ("PTestFailedCtorSub", "child"): (
+        "TestFailedCtorSubChild", "mozilla/_ipdltest/TestFailedCtor.h"
+    ),
+    ("PTestFailedCtorSub", "parent"): (
+        "TestFailedCtorSubParent", "mozilla/_ipdltest/TestFailedCtor.h"
+    ),
+    ("PTestFailedCtorSubsub", "child"): (
+        "TestFailedCtorSubsub", "mozilla/_ipdltest/TestFailedCtor.h"
+    ),
+    ("PTestFailedCtorSubsub", "parent"): (
+        "TestFailedCtorSubsub", "mozilla/_ipdltest/TestFailedCtor.h"
+    ),
+
+    ("PTestHandle", "child"): ("TestHandleChild", "mozilla/_ipdltest/TestJSON.h"),
+    ("PTestHandle", "parent"): ("TestHandleParent", "mozilla/_ipdltest/TestJSON.h"),
+    ("PTestJSON", "child"): ("TestJSONChild", "mozilla/_ipdltest/TestJSON.h"),
+    ("PTestJSON", "parent"): ("TestJSONParent", "mozilla/_ipdltest/TestJSON.h"),
+
+    ("PTestHangs", "child"): ("TestHangsChild", "mozilla/_ipdltest/TestHangs.h"),
+    ("PTestHangs", "parent"): ("TestHangsParent", "mozilla/_ipdltest/TestHangs.h"),
+
+    ("PTestHighestPrio", "child"): ("TestHighestPrioChild", "mozilla/_ipdltest/TestHighestPrio.h"),
+    ("PTestHighestPrio", "parent"): (
+        "TestHighestPrioParent", "mozilla/_ipdltest/TestHighestPrio.h"
+    ),
+
+    ("PTestInterruptErrorCleanup", "child"): (
+        "TestInterruptErrorCleanupChild", "mozilla/_ipdltest/TestInterruptErrorCleanup.h"
+    ),
+    ("PTestInterruptErrorCleanup", "parent"): (
+        "TestInterruptErrorCleanupParent", "mozilla/_ipdltest/TestInterruptErrorCleanup.h"
+    ),
+
+    ("PTestInterruptRaces", "child"): (
+        "TestInterruptRacesChild", "mozilla/_ipdltest/TestInterruptRaces.h"
+    ),
+    ("PTestInterruptRaces", "parent"): (
+        "TestInterruptRacesParent", "mozilla/_ipdltest/TestInterruptRaces.h"
+    ),
+
+    ("PTestInterruptShutdownRace", "child"): (
+        "TestInterruptShutdownRaceChild", "mozilla/_ipdltest/TestInterruptShutdownRace.h"
+    ),
+    ("PTestInterruptShutdownRace", "parent"): (
+        "TestInterruptShutdownRaceParent", "mozilla/_ipdltest/TestInterruptShutdownRace.h"
+    ),
+
+    ("PTestLatency", "child"): ("TestLatencyChild", "mozilla/_ipdltest/TestLatency.h"),
+    ("PTestLatency", "parent"): ("TestLatencyParent", "mozilla/_ipdltest/TestLatency.h"),
+
+    ("PTestLayoutThread", "child"): (
+        "TestOffMainThreadPaintingChild", "mozilla/_ipdltest/TestOffMainThreadPainting.h"
+    ),
+    ("PTestLayoutThread", "parent"): (
+        "TestOffMainThreadPaintingParent", "mozilla/_ipdltest/TestOffMainThreadPainting.h"
+    ),
+    ("PTestPaintThread", "child"): (
+        "TestPaintThreadChild", "mozilla/_ipdltest/TestOffMainThreadPainting.h"
+    ),
+    ("PTestPaintThread", "parent"): (
+        "TestPaintThreadParent", "mozilla/_ipdltest/TestOffMainThreadPainting.h"
+    ),
+
+    ("PTestManyChildAllocs", "child"): (
+        "TestManyChildAllocsChild", "mozilla/_ipdltest/TestManyChildAllocs.h"
+    ),
+    ("PTestManyChildAllocs", "parent"): (
+        "TestManyChildAllocsParent", "mozilla/_ipdltest/TestManyChildAllocs.h"
+    ),
+    ("PTestManyChildAllocsSub", "child"): (
+        "TestManyChildAllocsSubChild", "mozilla/_ipdltest/TestManyChildAllocs.h"
+    ),
+    ("PTestManyChildAllocsSub", "parent"): (
+        "TestManyChildAllocsSubParent", "mozilla/_ipdltest/TestManyChildAllocs.h"
+    ),
+
+    ("PTestMultiMgrs", "child"): ("TestMultiMgrsChild", "mozilla/_ipdltest/TestMultiMgrs.h"),
+    ("PTestMultiMgrs", "parent"): ("TestMultiMgrsParent", "mozilla/_ipdltest/TestMultiMgrs.h"),
+    ("PTestMultiMgrsBottom", "child"): (
+        "TestMultiMgrsBottomChild", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+    ("PTestMultiMgrsBottom", "parent"): (
+        "TestMultiMgrsBottomParent", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+    ("PTestMultiMgrsLeft", "child"): (
+        "TestMultiMgrsLeftChild", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+    ("PTestMultiMgrsLeft", "parent"): (
+        "TestMultiMgrsLeftParent", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+    ("PTestMultiMgrsRight", "child"): (
+        "TestMultiMgrsRightChild", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+    ("PTestMultiMgrsRight", "parent"): (
+        "TestMultiMgrsRightParent", "mozilla/_ipdltest/TestMultiMgrs.h"
+    ),
+
+    ("PTestNestedLoops", "child"): ("TestNestedLoopsChild", "mozilla/_ipdltest/TestNestedLoops.h"),
+    ("PTestNestedLoops", "parent"): (
+        "TestNestedLoopsParent", "mozilla/_ipdltest/TestNestedLoops.h"
+    ),
+
+    ("PTestRaceDeadlock", "child"): (
+        "TestRaceDeadlockChild", "mozilla/_ipdltest/TestRaceDeadlock.h"
+    ),
+    ("PTestRaceDeadlock", "parent"): (
+        "TestRaceDeadlockParent", "mozilla/_ipdltest/TestRaceDeadlock.h"
+    ),
+
+    ("PTestRaceDeferral", "child"): (
+        "TestRaceDeferralChild", "mozilla/_ipdltest/TestRaceDeferral.h"
+    ),
+    ("PTestRaceDeferral", "parent"): (
+        "TestRaceDeferralParent", "mozilla/_ipdltest/TestRaceDeferral.h"
+    ),
+
+    ("PTestRacyInterruptReplies", "child"): (
+        "TestRacyInterruptRepliesChild", "mozilla/_ipdltest/TestRacyInterruptReplies.h"
+    ),
+    ("PTestRacyInterruptReplies", "parent"): (
+        "TestRacyInterruptRepliesParent", "mozilla/_ipdltest/TestRacyInterruptReplies.h"
+    ),
+
+    ("PTestRacyReentry", "child"): ("TestRacyReentryChild", "mozilla/_ipdltest/TestRacyReentry.h"),
+    ("PTestRacyReentry", "parent"): (
+        "TestRacyReentryParent", "mozilla/_ipdltest/TestRacyReentry.h"
+    ),
+
+    ("PTestRacyUndefer", "child"): ("TestRacyUndeferChild", "mozilla/_ipdltest/TestRacyUndefer.h"),
+    ("PTestRacyUndefer", "parent"): (
+        "TestRacyUndeferParent", "mozilla/_ipdltest/TestRacyUndefer.h"
+    ),
+
+    ("PTestRPC", "child"): ("TestRPCChild", "mozilla/_ipdltest/TestRPC.h"),
+    ("PTestRPC", "parent"): ("TestRPCParent", "mozilla/_ipdltest/TestRPC.h"),
+
+    ("PTestSanity", "child"): ("TestSanityChild", "mozilla/_ipdltest/TestSanity.h"),
+    ("PTestSanity", "parent"): ("TestSanityParent", "mozilla/_ipdltest/TestSanity.h"),
+
+    ("PTestSelfManage", "child"): (
+        "TestSelfManageChild", "mozilla/_ipdltest/TestSelfManageRoot.h"
+    ),
+    ("PTestSelfManage", "parent"): (
+        "TestSelfManageParent", "mozilla/_ipdltest/TestSelfManageRoot.h"
+    ),
+    ("PTestSelfManageRoot", "child"): (
+        "TestSelfManageRootChild", "mozilla/_ipdltest/TestSelfManageRoot.h"
+    ),
+    ("PTestSelfManageRoot", "parent"): (
+        "TestSelfManageRootParent", "mozilla/_ipdltest/TestSelfManageRoot.h"
+    ),
+
+    ("PTestShmem", "child"): ("TestShmemChild", "mozilla/_ipdltest/TestShmem.h"),
+    ("PTestShmem", "parent"): ("TestShmemParent", "mozilla/_ipdltest/TestShmem.h"),
+
+    ("PTestShutdown", "child"): ("TestShutdownChild", "mozilla/_ipdltest/TestShutdown.h"),
+    ("PTestShutdown", "parent"): ("TestShutdownParent", "mozilla/_ipdltest/TestShutdown.h"),
+    ("PTestShutdownSub", "child"): ("TestShutdownSubChild", "mozilla/_ipdltest/TestShutdown.h"),
+    ("PTestShutdownSub", "parent"): ("TestShutdownSubParent", "mozilla/_ipdltest/TestShutdown.h"),
+    ("PTestShutdownSubsub", "child"): (
+        "TestShutdownSubsubChild", "mozilla/_ipdltest/TestShutdown.h"
+    ),
+    ("PTestShutdownSubsub", "parent"): (
+        "TestShutdownSubsubParent", "mozilla/_ipdltest/TestShutdown.h"
+    ),
+
+    ("PTestStackHooks", "child"): ("TestStackHooksChild", "mozilla/_ipdltest/TestStackHooks.h"),
+    ("PTestStackHooks", "parent"): ("TestStackHooksParent", "mozilla/_ipdltest/TestStackHooks.h"),
+
+    ("PTestSyncError", "child"): ("TestSyncErrorChild", "mozilla/_ipdltest/TestSyncError.h"),
+    ("PTestSyncError", "parent"): ("TestSyncErrorParent", "mozilla/_ipdltest/TestSyncError.h"),
+
+    ("PTestSyncHang", "child"): ("TestSyncHangChild", "mozilla/_ipdltest/TestSyncHang.h"),
+    ("PTestSyncHang", "parent"): ("TestSyncHangParent", "mozilla/_ipdltest/TestSyncHang.h"),
+
+    ("PTestSyncWakeup", "child"): ("TestSyncWakeupChild", "mozilla/_ipdltest/TestSyncWakeup.h"),
+    ("PTestSyncWakeup", "parent"): ("TestSyncWakeupParent", "mozilla/_ipdltest/TestSyncWakeup.h"),
+
+    ("PTestUniquePtrIPC", "child"): (
+        "TestUniquePtrIPCChild", "mozilla/_ipdltest/TestUniquePtrIPC.h"
+    ),
+    ("PTestUniquePtrIPC", "parent"): (
+        "TestUniquePtrIPCParent", "mozilla/_ipdltest/TestUniquePtrIPC.h"
+    ),
+
+    ("PTestUrgency", "child"): ("TestUrgencyChild", "mozilla/_ipdltest/TestUrgency.h"),
+    ("PTestUrgency", "parent"): ("TestUrgencyParent", "mozilla/_ipdltest/TestUrgency.h"),
+
+    ("PTestUrgentHangs", "child"): ("TestUrgentHangsChild", "mozilla/_ipdltest/TestUrgentHangs.h"),
+    ("PTestUrgentHangs", "parent"): (
+        "TestUrgentHangsParent", "mozilla/_ipdltest/TestUrgentHangs.h"
+    ),
 }
 
 # Our long term goal is to burn this list down, so new entries should be added
 # extremely sparingly and only with a very good reason! You must have an IPC
 # peer's r+ to add something new!
 
 # set() of (Protocol, side)
 VIRTUAL_CALL_CLASSES = set([
@@ -319,9 +611,20 @@ VIRTUAL_CALL_CLASSES = set([
     ("PGMPVideoDecoder", "parent"),
     ("PGMPVideoEncoder", "parent"),
     ("PWebRenderBridge", "parent"),
 
     # Not actually subclassed
     ("PLoginReputation", "child"),
     ("PPluginSurface", "child"),
     ("PTestShellCommand", "child"),
+
+    # _ipdltest
+    # Not actually subclassed
+    ("PTestIndirectProtocolParamFirst", "child"),
+    ("PTestIndirectProtocolParamFirst", "parent"),
+    ("PTestIndirectProtocolParamManage", "child"),
+    ("PTestIndirectProtocolParamManage", "parent"),
+    ("PTestIndirectProtocolParamSecond", "child"),
+    ("PTestIndirectProtocolParamSecond", "parent"),
+    ("PTestPriority", "child"),
+    ("PTestPriority", "parent"),
 ])
--- a/ipc/ipdl/test/cxx/PTestShmem.ipdl
+++ b/ipc/ipdl/test/cxx/PTestShmem.ipdl
@@ -1,17 +1,17 @@
 namespace mozilla {
 namespace _ipdltest {
 
 protocol PTestShmem {
 child:
-    async Give(Shmem mem, Shmem unsafe, size_t expectedSize);
+    async Give(Shmem mem, Shmem unsafe, uint32_t expectedSize);
 
 parent:
-    async Take(Shmem mem, Shmem unsafe, size_t expectedSize);
+    async Take(Shmem mem, Shmem unsafe, uint32_t expectedSize);
     async __delete__();
 
 /*
 state GIVING:
     send Give goto TAKING;
 
 state TAKING:
     recv Take goto TAKING;
--- a/ipc/ipdl/test/cxx/TestActorPunning.h
+++ b/ipc/ipdl/test/cxx/TestActorPunning.h
@@ -9,33 +9,33 @@
 #include "mozilla/_ipdltest/PTestActorPunningChild.h"
 #include "mozilla/_ipdltest/PTestActorPunningPunnedChild.h"
 #include "mozilla/_ipdltest/PTestActorPunningSubChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestActorPunningParent : public PTestActorPunningParent {
+  friend class PTestActorPunningParent;
+
  public:
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
-  PTestActorPunningPunnedParent* AllocPTestActorPunningPunnedParent() override;
-  bool DeallocPTestActorPunningPunnedParent(
-      PTestActorPunningPunnedParent* a) override;
+  PTestActorPunningPunnedParent* AllocPTestActorPunningPunnedParent();
+  bool DeallocPTestActorPunningPunnedParent(PTestActorPunningPunnedParent* a);
 
-  PTestActorPunningSubParent* AllocPTestActorPunningSubParent() override;
-  bool DeallocPTestActorPunningSubParent(
-      PTestActorPunningSubParent* a) override;
+  PTestActorPunningSubParent* AllocPTestActorPunningSubParent();
+  bool DeallocPTestActorPunningSubParent(PTestActorPunningSubParent* a);
 
-  virtual mozilla::ipc::IPCResult RecvPun(PTestActorPunningSubParent* a,
-                                          const Bad& bad) override;
+  mozilla::ipc::IPCResult RecvPun(PTestActorPunningSubParent* a,
+                                  const Bad& bad);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown == why) fail("should have died from error!");
     passed("ok");
     QuitParent();
   }
 
   virtual void HandleFatalError(const char* aErrorMsg) const override;
@@ -55,29 +55,30 @@ class TestActorPunningSubParent : public
   TestActorPunningSubParent() {}
   virtual ~TestActorPunningSubParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 };
 
 class TestActorPunningChild : public PTestActorPunningChild {
+  friend class PTestActorPunningChild;
+
  public:
   TestActorPunningChild() {}
   virtual ~TestActorPunningChild() {}
 
  protected:
-  PTestActorPunningPunnedChild* AllocPTestActorPunningPunnedChild() override;
-  bool DeallocPTestActorPunningPunnedChild(
-      PTestActorPunningPunnedChild* a) override;
+  PTestActorPunningPunnedChild* AllocPTestActorPunningPunnedChild();
+  bool DeallocPTestActorPunningPunnedChild(PTestActorPunningPunnedChild* a);
 
-  PTestActorPunningSubChild* AllocPTestActorPunningSubChild() override;
-  bool DeallocPTestActorPunningSubChild(PTestActorPunningSubChild* a) override;
+  PTestActorPunningSubChild* AllocPTestActorPunningSubChild();
+  bool DeallocPTestActorPunningSubChild(PTestActorPunningSubChild* a);
 
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     fail("should have been killed off!");
   }
 };
 
 class TestActorPunningPunnedChild : public PTestActorPunningPunnedChild {
  public:
@@ -85,15 +86,15 @@ class TestActorPunningPunnedChild : publ
   virtual ~TestActorPunningPunnedChild() {}
 };
 
 class TestActorPunningSubChild : public PTestActorPunningSubChild {
  public:
   TestActorPunningSubChild() {}
   virtual ~TestActorPunningSubChild() {}
 
-  virtual mozilla::ipc::IPCResult RecvBad() override;
+  mozilla::ipc::IPCResult RecvBad();
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
 
 #endif  // ifndef mozilla__ipdltest_TestActorPunning_h
--- a/ipc/ipdl/test/cxx/TestAsyncReturns.h
+++ b/ipc/ipdl/test/cxx/TestAsyncReturns.h
@@ -5,43 +5,47 @@
 
 #include "mozilla/_ipdltest/PTestAsyncReturnsParent.h"
 #include "mozilla/_ipdltest/PTestAsyncReturnsChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestAsyncReturnsParent : public PTestAsyncReturnsParent {
+  friend class PTestAsyncReturnsParent;
+
  public:
   TestAsyncReturnsParent();
   virtual ~TestAsyncReturnsParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  mozilla::ipc::IPCResult RecvPong(PongResolver&& aResolve) override;
+  mozilla::ipc::IPCResult RecvPong(PongResolver&& aResolve);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestAsyncReturnsChild : public PTestAsyncReturnsChild {
+  friend class PTestAsyncReturnsChild;
+
  public:
   TestAsyncReturnsChild();
   virtual ~TestAsyncReturnsChild();
 
  protected:
-  mozilla::ipc::IPCResult RecvPing(PingResolver&& aResolve) override;
-  mozilla::ipc::IPCResult RecvNoReturn(NoReturnResolver&& aResolve) override;
+  mozilla::ipc::IPCResult RecvPing(PingResolver&& aResolve);
+  mozilla::ipc::IPCResult RecvNoReturn(NoReturnResolver&& aResolve);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestBadActor.h
+++ b/ipc/ipdl/test/cxx/TestBadActor.h
@@ -8,16 +8,18 @@
 
 #include "mozilla/_ipdltest/PTestBadActorSubParent.h"
 #include "mozilla/_ipdltest/PTestBadActorSubChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestBadActorParent : public PTestBadActorParent {
+  friend class PTestBadActorParent;
+
  public:
   TestBadActorParent() {}
   virtual ~TestBadActorParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
@@ -26,36 +28,39 @@ class TestBadActorParent : public PTestB
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (AbnormalShutdown != why) fail("unexpected destruction");
     passed("ok");
     QuitParent();
   }
 
   virtual void HandleFatalError(const char* aErrorMsg) const override;
 
-  virtual PTestBadActorSubParent* AllocPTestBadActorSubParent() override;
+  PTestBadActorSubParent* AllocPTestBadActorSubParent();
 
-  virtual bool DeallocPTestBadActorSubParent(
-      PTestBadActorSubParent* actor) override {
+  bool DeallocPTestBadActorSubParent(PTestBadActorSubParent* actor) {
     delete actor;
     return true;
   }
 };
 
 class TestBadActorSubParent : public PTestBadActorSubParent {
+  friend class PTestBadActorSubParent;
+
  public:
   TestBadActorSubParent() {}
   virtual ~TestBadActorSubParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
-  virtual mozilla::ipc::IPCResult RecvPing() override;
+  mozilla::ipc::IPCResult RecvPing();
 };
 
 class TestBadActorChild : public PTestBadActorChild {
+  friend class PTestBadActorChild;
+
  public:
   TestBadActorChild() {}
   virtual ~TestBadActorChild() {}
 
  protected:
   virtual PTestBadActorSubChild* AllocPTestBadActorSubChild();
 
   virtual bool DeallocPTestBadActorSubChild(PTestBadActorSubChild* actor) {
--- a/ipc/ipdl/test/cxx/TestCancel.h
+++ b/ipc/ipdl/test/cxx/TestCancel.h
@@ -14,41 +14,41 @@ class TestCancelParent : public PTestCan
   TestCancelParent();
   virtual ~TestCancelParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
-  virtual mozilla::ipc::IPCResult RecvDone1() override;
-  virtual mozilla::ipc::IPCResult RecvTest2_1() override;
-  virtual mozilla::ipc::IPCResult RecvStart3() override;
-  virtual mozilla::ipc::IPCResult RecvTest3_2() override;
-  virtual mozilla::ipc::IPCResult RecvDone() override;
+  mozilla::ipc::IPCResult RecvDone1();
+  mozilla::ipc::IPCResult RecvTest2_1();
+  mozilla::ipc::IPCResult RecvStart3();
+  mozilla::ipc::IPCResult RecvTest3_2();
+  mozilla::ipc::IPCResult RecvDone();
 
-  virtual mozilla::ipc::IPCResult RecvCheckParent(uint32_t *reply) override;
+  mozilla::ipc::IPCResult RecvCheckParent(uint32_t *reply);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     passed("ok");
     QuitParent();
   }
 };
 
 class TestCancelChild : public PTestCancelChild {
  public:
   TestCancelChild();
   virtual ~TestCancelChild();
 
-  virtual mozilla::ipc::IPCResult RecvTest1_1() override;
-  virtual mozilla::ipc::IPCResult RecvStart2() override;
-  virtual mozilla::ipc::IPCResult RecvTest2_2() override;
-  virtual mozilla::ipc::IPCResult RecvTest3_1() override;
+  mozilla::ipc::IPCResult RecvTest1_1();
+  mozilla::ipc::IPCResult RecvStart2();
+  mozilla::ipc::IPCResult RecvTest2_2();
+  mozilla::ipc::IPCResult RecvTest3_1();
 
-  virtual mozilla::ipc::IPCResult RecvCheckChild(uint32_t *reply) override;
+  mozilla::ipc::IPCResult RecvCheckChild(uint32_t *reply);
 
   virtual void ActorDestroy(ActorDestroyReason why) override { QuitChild(); }
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
 
 #endif  // ifndef mozilla__ipdltest_TestCancel_h
--- a/ipc/ipdl/test/cxx/TestCrashCleanup.h
+++ b/ipc/ipdl/test/cxx/TestCrashCleanup.h
@@ -24,22 +24,24 @@ class TestCrashCleanupParent : public PT
     if (AbnormalShutdown != why) fail("unexpected destruction!");
     mCleanedUp = true;
   }
 
   bool mCleanedUp;
 };
 
 class TestCrashCleanupChild : public PTestCrashCleanupChild {
+  friend class PTestCrashCleanupChild;
+
  public:
   TestCrashCleanupChild();
   virtual ~TestCrashCleanupChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerDIEDIEDIE() override;
+  mozilla::ipc::IPCResult AnswerDIEDIEDIE();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     fail("should have 'crashed'!");
   }
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
--- a/ipc/ipdl/test/cxx/TestDataStructures.h
+++ b/ipc/ipdl/test/cxx/TestDataStructures.h
@@ -25,143 +25,131 @@ class TestDataStructuresSub : public PTe
   }
   uint32_t mI;
 };
 
 //-----------------------------------------------------------------------------
 // Main actors
 
 class TestDataStructuresParent : public PTestDataStructuresParent {
+  friend class PTestDataStructuresParent;
+
  public:
   TestDataStructuresParent();
   virtual ~TestDataStructuresParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual PTestDataStructuresSubParent* AllocPTestDataStructuresSubParent(
-      const int& i) override {
+  PTestDataStructuresSubParent* AllocPTestDataStructuresSubParent(
+      const int& i) {
     PTestDataStructuresSubParent* actor = new TestDataStructuresSub(i);
     mKids.AppendElement(actor);
     return actor;
   }
 
-  virtual bool DeallocPTestDataStructuresSubParent(
-      PTestDataStructuresSubParent* actor) override;
+  bool DeallocPTestDataStructuresSubParent(PTestDataStructuresSubParent* actor);
 
-  virtual mozilla::ipc::IPCResult RecvTest1(InfallibleTArray<int>&& i1,
-                                            InfallibleTArray<int>* o1) override;
+  mozilla::ipc::IPCResult RecvTest1(InfallibleTArray<int>&& i1,
+                                    InfallibleTArray<int>* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest2(
+  mozilla::ipc::IPCResult RecvTest2(
       InfallibleTArray<PTestDataStructuresSubParent*>&& i1,
-      InfallibleTArray<PTestDataStructuresSubParent*>* o1) override;
+      InfallibleTArray<PTestDataStructuresSubParent*>* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest3(const IntDouble& i1,
-                                            const IntDouble& i2, IntDouble* o1,
-                                            IntDouble* o2) override;
+  mozilla::ipc::IPCResult RecvTest3(const IntDouble& i1, const IntDouble& i2,
+                                    IntDouble* o1, IntDouble* o2);
 
-  virtual mozilla::ipc::IPCResult RecvTest4(
-      InfallibleTArray<IntDouble>&& i1,
-      InfallibleTArray<IntDouble>* o1) override;
+  mozilla::ipc::IPCResult RecvTest4(InfallibleTArray<IntDouble>&& i1,
+                                    InfallibleTArray<IntDouble>* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest5(const IntDoubleArrays& i1,
-                                            const IntDoubleArrays& i2,
-                                            const IntDoubleArrays& i3,
-                                            IntDoubleArrays* o1,
-                                            IntDoubleArrays* o2,
-                                            IntDoubleArrays* o3) override;
+  mozilla::ipc::IPCResult RecvTest5(const IntDoubleArrays& i1,
+                                    const IntDoubleArrays& i2,
+                                    const IntDoubleArrays& i3,
+                                    IntDoubleArrays* o1, IntDoubleArrays* o2,
+                                    IntDoubleArrays* o3);
 
-  virtual mozilla::ipc::IPCResult RecvTest6(
-      InfallibleTArray<IntDoubleArrays>&& i1,
-      InfallibleTArray<IntDoubleArrays>* o1) override;
+  mozilla::ipc::IPCResult RecvTest6(InfallibleTArray<IntDoubleArrays>&& i1,
+                                    InfallibleTArray<IntDoubleArrays>* o1);
+
+  mozilla::ipc::IPCResult RecvTest7_0(const ActorWrapper& i1, ActorWrapper* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest7_0(const ActorWrapper& i1,
-                                              ActorWrapper* o1) override;
-
-  virtual mozilla::ipc::IPCResult RecvTest7(const Actors& i1, const Actors& i2,
-                                            const Actors& i3, Actors* o1,
-                                            Actors* o2, Actors* o3) override;
+  mozilla::ipc::IPCResult RecvTest7(const Actors& i1, const Actors& i2,
+                                    const Actors& i3, Actors* o1, Actors* o2,
+                                    Actors* o3);
 
-  virtual mozilla::ipc::IPCResult RecvTest8(
-      InfallibleTArray<Actors>&& i1, InfallibleTArray<Actors>* o1) override;
+  mozilla::ipc::IPCResult RecvTest8(InfallibleTArray<Actors>&& i1,
+                                    InfallibleTArray<Actors>* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest9(const Unions& i1, const Unions& i2,
-                                            const Unions& i3, const Unions& i4,
-                                            Unions* o1, Unions* o2, Unions* o3,
-                                            Unions* o4) override;
+  mozilla::ipc::IPCResult RecvTest9(const Unions& i1, const Unions& i2,
+                                    const Unions& i3, const Unions& i4,
+                                    Unions* o1, Unions* o2, Unions* o3,
+                                    Unions* o4);
 
-  virtual mozilla::ipc::IPCResult RecvTest10(
-      InfallibleTArray<Unions>&& i1, InfallibleTArray<Unions>* o1) override;
+  mozilla::ipc::IPCResult RecvTest10(InfallibleTArray<Unions>&& i1,
+                                     InfallibleTArray<Unions>* o1);
 
-  virtual mozilla::ipc::IPCResult RecvTest11(const SIntDouble& i,
-                                             SIntDouble* o) override;
+  mozilla::ipc::IPCResult RecvTest11(const SIntDouble& i, SIntDouble* o);
 
-  virtual mozilla::ipc::IPCResult RecvTest12(const SIntDoubleArrays& i,
-                                             SIntDoubleArrays* o) override;
+  mozilla::ipc::IPCResult RecvTest12(const SIntDoubleArrays& i,
+                                     SIntDoubleArrays* o);
 
-  virtual mozilla::ipc::IPCResult RecvTest13(const SActors& i,
-                                             SActors* o) override;
+  mozilla::ipc::IPCResult RecvTest13(const SActors& i, SActors* o);
 
-  virtual mozilla::ipc::IPCResult RecvTest14(const Structs& i,
-                                             Structs* o) override;
+  mozilla::ipc::IPCResult RecvTest14(const Structs& i, Structs* o);
 
-  virtual mozilla::ipc::IPCResult RecvTest15(
+  mozilla::ipc::IPCResult RecvTest15(
       const WithStructs& i1, const WithStructs& i2, const WithStructs& i3,
       const WithStructs& i4, const WithStructs& i5, WithStructs* o1,
-      WithStructs* o2, WithStructs* o3, WithStructs* o4,
-      WithStructs* o5) override;
+      WithStructs* o2, WithStructs* o3, WithStructs* o4, WithStructs* o5);
 
-  virtual mozilla::ipc::IPCResult RecvTest16(const WithUnions& i,
-                                             WithUnions* o) override;
+  mozilla::ipc::IPCResult RecvTest16(const WithUnions& i, WithUnions* o);
 
-  virtual mozilla::ipc::IPCResult RecvTest17(
-      InfallibleTArray<Op>&& sa) override;
+  mozilla::ipc::IPCResult RecvTest17(InfallibleTArray<Op>&& sa);
 
-  virtual mozilla::ipc::IPCResult RecvTest18(
-      InfallibleTArray<nsIntRegion>&& ra) override;
+  mozilla::ipc::IPCResult RecvTest18(InfallibleTArray<nsIntRegion>&& ra);
 
-  virtual mozilla::ipc::IPCResult RecvDummy(const ShmemUnion& su,
-                                            ShmemUnion* rsu) override {
+  mozilla::ipc::IPCResult RecvDummy(const ShmemUnion& su, ShmemUnion* rsu) {
     *rsu = su;
     return IPC_OK();
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
  private:
   InfallibleTArray<PTestDataStructuresSubParent*> mKids;
 };
 
 class TestDataStructuresChild : public PTestDataStructuresChild {
+  friend class PTestDataStructuresChild;
+
  public:
   TestDataStructuresChild();
   virtual ~TestDataStructuresChild();
 
  protected:
-  virtual PTestDataStructuresSubChild* AllocPTestDataStructuresSubChild(
-      const int& i) override {
+  PTestDataStructuresSubChild* AllocPTestDataStructuresSubChild(const int& i) {
     PTestDataStructuresSubChild* actor = new TestDataStructuresSub(i);
     mKids.AppendElement(actor);
     return actor;
   }
 
-  virtual bool DeallocPTestDataStructuresSubChild(
-      PTestDataStructuresSubChild* actor) override {
+  bool DeallocPTestDataStructuresSubChild(PTestDataStructuresSubChild* actor) {
     delete actor;
     return true;
   }
 
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 
  private:
   void Test1();
--- a/ipc/ipdl/test/cxx/TestDemon.h
+++ b/ipc/ipdl/test/cxx/TestDemon.h
@@ -24,22 +24,22 @@ class TestDemonParent : public PTestDemo
 #ifdef DEBUG
   bool ShouldContinueFromReplyTimeout() override;
   bool ArtificialTimeout() override;
 
   bool NeedArtificialSleep() override { return true; }
   void ArtificialSleep() override;
 #endif
 
-  mozilla::ipc::IPCResult RecvAsyncMessage(const int& n) override;
-  mozilla::ipc::IPCResult RecvHiPrioSyncMessage() override;
+  mozilla::ipc::IPCResult RecvAsyncMessage(const int& n);
+  mozilla::ipc::IPCResult RecvHiPrioSyncMessage();
 
-  mozilla::ipc::IPCResult RecvSyncMessage(const int& n) override;
-  mozilla::ipc::IPCResult RecvUrgentAsyncMessage(const int& n) override;
-  mozilla::ipc::IPCResult RecvUrgentSyncMessage(const int& n) override;
+  mozilla::ipc::IPCResult RecvSyncMessage(const int& n);
+  mozilla::ipc::IPCResult RecvUrgentAsyncMessage(const int& n);
+  mozilla::ipc::IPCResult RecvUrgentSyncMessage(const int& n);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     mDone = true;
     printf("Parent ActorDestroy\n");
     passed("ok");
     QuitParent();
   }
 
@@ -57,25 +57,25 @@ class TestDemonParent : public PTestDemo
   bool DoAction(int flags = 0);
 };
 
 class TestDemonChild : public PTestDemonChild {
  public:
   TestDemonChild();
   virtual ~TestDemonChild();
 
-  mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
 #ifdef DEBUG
   bool NeedArtificialSleep() override { return true; }
   void ArtificialSleep() override;
 #endif
 
-  mozilla::ipc::IPCResult RecvAsyncMessage(const int& n) override;
-  mozilla::ipc::IPCResult RecvHiPrioSyncMessage() override;
+  mozilla::ipc::IPCResult RecvAsyncMessage(const int& n);
+  mozilla::ipc::IPCResult RecvHiPrioSyncMessage();
 
   virtual void ActorDestroy(ActorDestroyReason why) override { _exit(0); }
 
   virtual void IntentionalCrash() override { _exit(0); }
 
  private:
   int mIncoming[3];
   int mOutgoing[3];
--- a/ipc/ipdl/test/cxx/TestDesc.h
+++ b/ipc/ipdl/test/cxx/TestDesc.h
@@ -14,82 +14,86 @@
 
 namespace mozilla {
 namespace _ipdltest {
 
 //-----------------------------------------------------------------------------
 // Top-level
 //
 class TestDescParent : public PTestDescParent {
+  friend class PTestDescParent;
+
  public:
   TestDescParent() {}
   virtual ~TestDescParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
-  virtual mozilla::ipc::IPCResult RecvOk(PTestDescSubsubParent* a) override;
+  mozilla::ipc::IPCResult RecvOk(PTestDescSubsubParent* a);
 
  protected:
-  virtual PTestDescSubParent* AllocPTestDescSubParent(
-      PTestDescSubsubParent*) override;
-  virtual bool DeallocPTestDescSubParent(PTestDescSubParent* actor) override;
+  PTestDescSubParent* AllocPTestDescSubParent(PTestDescSubsubParent*);
+  bool DeallocPTestDescSubParent(PTestDescSubParent* actor);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestDescChild : public PTestDescChild {
+  friend class PTestDescChild;
+
  public:
   TestDescChild() {}
   virtual ~TestDescChild() {}
 
  protected:
-  virtual PTestDescSubChild* AllocPTestDescSubChild(
-      PTestDescSubsubChild*) override;
+  PTestDescSubChild* AllocPTestDescSubChild(PTestDescSubsubChild*);
 
-  virtual bool DeallocPTestDescSubChild(PTestDescSubChild* actor) override;
+  bool DeallocPTestDescSubChild(PTestDescSubChild* actor);
 
-  virtual mozilla::ipc::IPCResult RecvTest(PTestDescSubsubChild* a) override;
+  mozilla::ipc::IPCResult RecvTest(PTestDescSubsubChild* a);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 //-----------------------------------------------------------------------------
 // First descendent
 //
 class TestDescSubParent : public PTestDescSubParent {
+  friend class PTestDescSubParent;
+
  public:
   TestDescSubParent() {}
   virtual ~TestDescSubParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
-  virtual PTestDescSubsubParent* AllocPTestDescSubsubParent() override;
-  virtual bool DeallocPTestDescSubsubParent(
-      PTestDescSubsubParent* actor) override;
+  PTestDescSubsubParent* AllocPTestDescSubsubParent();
+  bool DeallocPTestDescSubsubParent(PTestDescSubsubParent* actor);
 };
 
 class TestDescSubChild : public PTestDescSubChild {
+  friend class PTestDescSubChild;
+
  public:
   TestDescSubChild() {}
   virtual ~TestDescSubChild() {}
 
  protected:
-  virtual PTestDescSubsubChild* AllocPTestDescSubsubChild() override;
-  virtual bool DeallocPTestDescSubsubChild(
-      PTestDescSubsubChild* actor) override;
+  PTestDescSubsubChild* AllocPTestDescSubsubChild();
+  bool DeallocPTestDescSubsubChild(PTestDescSubsubChild* actor);
 };
 
 //-----------------------------------------------------------------------------
 // Grand-descendent
 //
 class TestDescSubsubParent : public PTestDescSubsubParent {
  public:
   TestDescSubsubParent() {}
--- a/ipc/ipdl/test/cxx/TestEndpointBridgeMain.h
+++ b/ipc/ipdl/test/cxx/TestEndpointBridgeMain.h
@@ -17,103 +17,114 @@
 
 namespace mozilla {
 namespace _ipdltest {
 
 //-----------------------------------------------------------------------------
 // "Main" process
 //
 class TestEndpointBridgeMainParent : public PTestEndpointBridgeMainParent {
+  friend class PTestEndpointBridgeMainParent;
+
  public:
   TestEndpointBridgeMainParent() {}
   virtual ~TestEndpointBridgeMainParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
   mozilla::ipc::IPCResult RecvBridged(
-      mozilla::ipc::Endpoint<PTestEndpointBridgeMainSubParent>&& endpoint)
-      override;
+      mozilla::ipc::Endpoint<PTestEndpointBridgeMainSubParent>&& endpoint);
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 class TestEndpointBridgeMainSubParent
     : public PTestEndpointBridgeMainSubParent {
+  friend class PTestEndpointBridgeMainSubParent;
+
  public:
   explicit TestEndpointBridgeMainSubParent() {}
   virtual ~TestEndpointBridgeMainSubParent() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvHello() override;
-  virtual mozilla::ipc::IPCResult RecvHelloSync() override;
-  virtual mozilla::ipc::IPCResult AnswerHelloRpc() override;
+  mozilla::ipc::IPCResult RecvHello();
+  mozilla::ipc::IPCResult RecvHelloSync();
+  mozilla::ipc::IPCResult AnswerHelloRpc();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 //-----------------------------------------------------------------------------
 // "Sub" process --- child of "main"
 //
 class TestEndpointBridgeSubParent;
 
 class TestEndpointBridgeMainChild : public PTestEndpointBridgeMainChild {
+  friend class PTestEndpointBridgeMainChild;
+
  public:
   TestEndpointBridgeMainChild();
   virtual ~TestEndpointBridgeMainChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   IPDLUnitTestSubprocess* mSubprocess;
 };
 
 class TestEndpointBridgeSubParent : public PTestEndpointBridgeSubParent {
+  friend class PTestEndpointBridgeSubParent;
+
  public:
   TestEndpointBridgeSubParent() {}
   virtual ~TestEndpointBridgeSubParent() {}
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvBridgeEm() override;
+  mozilla::ipc::IPCResult RecvBridgeEm();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 //-----------------------------------------------------------------------------
 // "Subsub" process --- child of "sub"
 //
 class TestEndpointBridgeSubChild : public PTestEndpointBridgeSubChild {
+  friend class PTestEndpointBridgeSubChild;
+
  public:
   TestEndpointBridgeSubChild();
   virtual ~TestEndpointBridgeSubChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvPing() override;
+  mozilla::ipc::IPCResult RecvPing();
 
   mozilla::ipc::IPCResult RecvBridged(
-      Endpoint<PTestEndpointBridgeMainSubChild>&& endpoint) override;
+      Endpoint<PTestEndpointBridgeMainSubChild>&& endpoint);
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 class TestEndpointBridgeMainSubChild : public PTestEndpointBridgeMainSubChild {
+  friend class PTestEndpointBridgeMainSubChild;
+
  public:
   explicit TestEndpointBridgeMainSubChild() : mGotHi(false) {}
   virtual ~TestEndpointBridgeMainSubChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvHi() override;
-  virtual mozilla::ipc::IPCResult AnswerHiRpc() override;
+  mozilla::ipc::IPCResult RecvHi();
+  mozilla::ipc::IPCResult AnswerHiRpc();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   bool mGotHi;
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
--- a/ipc/ipdl/test/cxx/TestEndpointOpens.h
+++ b/ipc/ipdl/test/cxx/TestEndpointOpens.h
@@ -14,79 +14,86 @@
 
 namespace mozilla {
 
 // parent process
 
 namespace _ipdltest {
 
 class TestEndpointOpensParent : public PTestEndpointOpensParent {
+  friend class PTestEndpointOpensParent;
+
  public:
   TestEndpointOpensParent() {}
   virtual ~TestEndpointOpensParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStartSubprotocol(
-      mozilla::ipc::Endpoint<PTestEndpointOpensOpenedParent>&& endpoint)
-      override;
+  mozilla::ipc::IPCResult RecvStartSubprotocol(
+      mozilla::ipc::Endpoint<PTestEndpointOpensOpenedParent>&& endpoint);
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 }  // namespace _ipdltest
 
 namespace _ipdltest2 {
 
 class TestEndpointOpensOpenedParent : public PTestEndpointOpensOpenedParent {
+  friend class PTestEndpointOpensOpenedParent;
+
  public:
   explicit TestEndpointOpensOpenedParent() {}
   virtual ~TestEndpointOpensOpenedParent() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvHello() override;
-  virtual mozilla::ipc::IPCResult RecvHelloSync() override;
-  virtual mozilla::ipc::IPCResult AnswerHelloRpc() override;
+  mozilla::ipc::IPCResult RecvHello();
+  mozilla::ipc::IPCResult RecvHelloSync();
+  mozilla::ipc::IPCResult AnswerHelloRpc();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 }  // namespace _ipdltest2
 
 // child process
 
 namespace _ipdltest {
 
 class TestEndpointOpensChild : public PTestEndpointOpensChild {
+  friend class PTestEndpointOpensChild;
+
  public:
   TestEndpointOpensChild();
   virtual ~TestEndpointOpensChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 }  // namespace _ipdltest
 
 namespace _ipdltest2 {
 
 class TestEndpointOpensOpenedChild : public PTestEndpointOpensOpenedChild {
+  friend class PTestEndpointOpensOpenedChild;
+
  public:
   explicit TestEndpointOpensOpenedChild() : mGotHi(false) {}
   virtual ~TestEndpointOpensOpenedChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvHi() override;
-  virtual mozilla::ipc::IPCResult AnswerHiRpc() override;
+  mozilla::ipc::IPCResult RecvHi();
+  mozilla::ipc::IPCResult AnswerHiRpc();
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   bool mGotHi;
 };
 
 }  // namespace _ipdltest2
 
--- a/ipc/ipdl/test/cxx/TestFailedCtor.h
+++ b/ipc/ipdl/test/cxx/TestFailedCtor.h
@@ -14,97 +14,99 @@
 
 namespace mozilla {
 namespace _ipdltest {
 
 //-----------------------------------------------------------------------------
 // Top-level
 //
 class TestFailedCtorParent : public PTestFailedCtorParent {
+  friend class PTestFailedCtorParent;
+
  public:
   TestFailedCtorParent() {}
   virtual ~TestFailedCtorParent() {}
 
   static bool RunTestInProcesses() { return true; }
 
   // FIXME/bug 703322 Disabled because child calls exit() to end
   //                  test, not clear how to handle failed ctor in
   //                  threaded mode.
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
-  virtual PTestFailedCtorSubParent* AllocPTestFailedCtorSubParent() override;
-  virtual bool DeallocPTestFailedCtorSubParent(
-      PTestFailedCtorSubParent* actor) override;
+  PTestFailedCtorSubParent* AllocPTestFailedCtorSubParent();
+  bool DeallocPTestFailedCtorSubParent(PTestFailedCtorSubParent* actor);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (AbnormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestFailedCtorChild : public PTestFailedCtorChild {
+  friend class PTestFailedCtorChild;
+
  public:
   TestFailedCtorChild() {}
   virtual ~TestFailedCtorChild() {}
 
  protected:
-  virtual PTestFailedCtorSubChild* AllocPTestFailedCtorSubChild() override;
+  PTestFailedCtorSubChild* AllocPTestFailedCtorSubChild();
 
-  virtual mozilla::ipc::IPCResult AnswerPTestFailedCtorSubConstructor(
+  mozilla::ipc::IPCResult AnswerPTestFailedCtorSubConstructor(
       PTestFailedCtorSubChild* actor) override;
 
-  virtual bool DeallocPTestFailedCtorSubChild(
-      PTestFailedCtorSubChild* actor) override;
+  bool DeallocPTestFailedCtorSubChild(PTestFailedCtorSubChild* actor);
 
   virtual void ProcessingError(Result aCode, const char* aReason) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     fail("should have _exit()ed");
   }
 };
 
 //-----------------------------------------------------------------------------
 // First descendent
 //
 class TestFailedCtorSubsub;
 
 class TestFailedCtorSubParent : public PTestFailedCtorSubParent {
+  friend class PTestFailedCtorSubParent;
+
  public:
   TestFailedCtorSubParent() : mOne(nullptr), mTwo(nullptr), mThree(nullptr) {}
   virtual ~TestFailedCtorSubParent();
 
  protected:
-  virtual PTestFailedCtorSubsubParent* AllocPTestFailedCtorSubsubParent()
-      override;
+  PTestFailedCtorSubsubParent* AllocPTestFailedCtorSubsubParent();
 
-  virtual bool DeallocPTestFailedCtorSubsubParent(
-      PTestFailedCtorSubsubParent* actor) override;
-  virtual mozilla::ipc::IPCResult RecvSync() override { return IPC_OK(); }
+  bool DeallocPTestFailedCtorSubsubParent(PTestFailedCtorSubsubParent* actor);
+  mozilla::ipc::IPCResult RecvSync() { return IPC_OK(); }
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
   TestFailedCtorSubsub* mOne;
   TestFailedCtorSubsub* mTwo;
   TestFailedCtorSubsub* mThree;
 };
 
 class TestFailedCtorSubChild : public PTestFailedCtorSubChild {
+  friend class PTestFailedCtorSubChild;
+
  public:
   TestFailedCtorSubChild() {}
   virtual ~TestFailedCtorSubChild() {}
 
  protected:
-  virtual PTestFailedCtorSubsubChild* AllocPTestFailedCtorSubsubChild()
-      override;
-  virtual bool DeallocPTestFailedCtorSubsubChild(
-      PTestFailedCtorSubsubChild* actor) override;
+  PTestFailedCtorSubsubChild* AllocPTestFailedCtorSubsubChild();
+  bool DeallocPTestFailedCtorSubsubChild(PTestFailedCtorSubsubChild* actor);
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 //-----------------------------------------------------------------------------
 // Grand-descendent
 //
 class TestFailedCtorSubsub : public PTestFailedCtorSubsubParent,
--- a/ipc/ipdl/test/cxx/TestHangs.h
+++ b/ipc/ipdl/test/cxx/TestHangs.h
@@ -5,64 +5,68 @@
 
 #include "mozilla/_ipdltest/PTestHangsParent.h"
 #include "mozilla/_ipdltest/PTestHangsChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestHangsParent : public PTestHangsParent {
+  friend class PTestHangsParent;
+
  public:
   TestHangsParent();
   virtual ~TestHangsParent();
 
   static bool RunTestInProcesses() { return true; }
 
   // FIXME/bug 703320 Disabled because parent kills child proc, not
   //                  clear how that should work in threads.
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
   virtual bool ShouldContinueFromReplyTimeout() override;
 
-  virtual mozilla::ipc::IPCResult RecvNonce() override { return IPC_OK(); }
+  mozilla::ipc::IPCResult RecvNonce() { return IPC_OK(); }
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (AbnormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
   void CleanUp();
 
   bool mDetectedHang;
   int32_t mNumAnswerStackFrame;
 };
 
 class TestHangsChild : public PTestHangsChild {
+  friend class PTestHangsChild;
+
  public:
   TestHangsChild();
   virtual ~TestHangsChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override {
+  mozilla::ipc::IPCResult RecvStart() {
     if (!SendNonce()) fail("sending Nonce");
     return IPC_OK();
   }
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override {
+  mozilla::ipc::IPCResult AnswerStackFrame() {
     if (CallStackFrame()) fail("should have failed");
     return IPC_OK();
   }
 
-  virtual mozilla::ipc::IPCResult AnswerHang() override;
+  mozilla::ipc::IPCResult AnswerHang();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (AbnormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestHighestPrio.h
+++ b/ipc/ipdl/test/cxx/TestHighestPrio.h
@@ -14,20 +14,20 @@ class TestHighestPrioParent : public PTe
   TestHighestPrioParent();
   virtual ~TestHighestPrioParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
-  mozilla::ipc::IPCResult RecvMsg1() override;
-  mozilla::ipc::IPCResult RecvMsg2() override;
-  mozilla::ipc::IPCResult RecvMsg3() override;
-  mozilla::ipc::IPCResult RecvMsg4() override;
+  mozilla::ipc::IPCResult RecvMsg1();
+  mozilla::ipc::IPCResult RecvMsg2();
+  mozilla::ipc::IPCResult RecvMsg3();
+  mozilla::ipc::IPCResult RecvMsg4();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     if (msg_num_ != 4) fail("missed IPC call");
     passed("ok");
     QuitParent();
   }
 
@@ -35,18 +35,18 @@ class TestHighestPrioParent : public PTe
   int msg_num_;
 };
 
 class TestHighestPrioChild : public PTestHighestPrioChild {
  public:
   TestHighestPrioChild();
   virtual ~TestHighestPrioChild();
 
-  mozilla::ipc::IPCResult RecvStart() override;
-  mozilla::ipc::IPCResult RecvStartInner() override;
+  mozilla::ipc::IPCResult RecvStart();
+  mozilla::ipc::IPCResult RecvStartInner();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestInterruptErrorCleanup.h
+++ b/ipc/ipdl/test/cxx/TestInterruptErrorCleanup.h
@@ -27,22 +27,24 @@ class TestInterruptErrorCleanupParent
   }
 
   virtual void ProcessingError(Result aCode, const char* aReason) override;
 
   bool mGotProcessingError;
 };
 
 class TestInterruptErrorCleanupChild : public PTestInterruptErrorCleanupChild {
+  friend class PTestInterruptErrorCleanupChild;
+
  public:
   TestInterruptErrorCleanupChild();
   virtual ~TestInterruptErrorCleanupChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerError() override;
+  mozilla::ipc::IPCResult AnswerError();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     fail("should have 'crashed'!");
   }
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
--- a/ipc/ipdl/test/cxx/TestInterruptRaces.h
+++ b/ipc/ipdl/test/cxx/TestInterruptRaces.h
@@ -9,41 +9,42 @@
 namespace mozilla {
 namespace _ipdltest {
 
 mozilla::ipc::RacyInterruptPolicy MediateRace(
     const mozilla::ipc::MessageChannel::MessageInfo& parent,
     const mozilla::ipc::MessageChannel::MessageInfo& child);
 
 class TestInterruptRacesParent : public PTestInterruptRacesParent {
+  friend class PTestInterruptRacesParent;
+
  public:
   TestInterruptRacesParent()
       : mHasReply(false), mChildHasReply(false), mAnsweredParent(false) {}
   virtual ~TestInterruptRacesParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStartRace() override;
+  mozilla::ipc::IPCResult RecvStartRace();
 
-  virtual mozilla::ipc::IPCResult AnswerRace(bool* hasRace) override;
+  mozilla::ipc::IPCResult AnswerRace(bool* hasRace);
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame3() override;
+  mozilla::ipc::IPCResult AnswerStackFrame3();
 
-  virtual mozilla::ipc::IPCResult AnswerParent() override;
+  mozilla::ipc::IPCResult AnswerParent();
 
-  virtual mozilla::ipc::IPCResult RecvGetAnsweredParent(
-      bool* answeredParent) override;
+  mozilla::ipc::IPCResult RecvGetAnsweredParent(bool* answeredParent);
 
-  virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
+  mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override {
     return MediateRace(parent, child);
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     if (!(mHasReply && mChildHasReply)) fail("both sides should have replies!");
     passed("ok");
@@ -57,34 +58,36 @@ class TestInterruptRacesParent : public 
   void Test3();
 
   bool mHasReply;
   bool mChildHasReply;
   bool mAnsweredParent;
 };
 
 class TestInterruptRacesChild : public PTestInterruptRacesChild {
+  friend class PTestInterruptRacesChild;
+
  public:
   TestInterruptRacesChild() : mHasReply(false) {}
   virtual ~TestInterruptRacesChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult AnswerRace(bool* hasRace) override;
+  mozilla::ipc::IPCResult AnswerRace(bool* hasRace);
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame3() override;
+  mozilla::ipc::IPCResult AnswerStackFrame3();
 
-  virtual mozilla::ipc::IPCResult RecvWakeup() override;
+  mozilla::ipc::IPCResult RecvWakeup();
 
-  virtual mozilla::ipc::IPCResult RecvWakeup3() override;
+  mozilla::ipc::IPCResult RecvWakeup3();
 
-  virtual mozilla::ipc::IPCResult AnswerChild() override;
+  mozilla::ipc::IPCResult AnswerChild();
 
   virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override {
     return MediateRace(parent, child);
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
--- a/ipc/ipdl/test/cxx/TestInterruptShutdownRace.h
+++ b/ipc/ipdl/test/cxx/TestInterruptShutdownRace.h
@@ -16,37 +16,39 @@ class TestInterruptShutdownRaceParent
   virtual ~TestInterruptShutdownRaceParent();
 
   static bool RunTestInProcesses() { return true; }
   // FIXME/bug 703323 Could work if modified
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
-  virtual mozilla::ipc::IPCResult RecvStartDeath() override;
+  mozilla::ipc::IPCResult RecvStartDeath();
 
-  virtual mozilla::ipc::IPCResult RecvOrphan() override;
+  mozilla::ipc::IPCResult RecvOrphan();
 
  protected:
   void StartShuttingDown();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (AbnormalShutdown != why) fail("unexpected destruction!");
   }
 };
 
 class TestInterruptShutdownRaceChild : public PTestInterruptShutdownRaceChild {
+  friend class PTestInterruptShutdownRaceChild;
+
  public:
   TestInterruptShutdownRaceChild();
   virtual ~TestInterruptShutdownRaceChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult AnswerExit() override;
+  mozilla::ipc::IPCResult AnswerExit();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     fail("should have 'crashed'!");
   }
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
--- a/ipc/ipdl/test/cxx/TestJSON.h
+++ b/ipc/ipdl/test/cxx/TestJSON.h
@@ -17,34 +17,35 @@ class TestHandleParent : public PTestHan
   TestHandleParent() {}
   virtual ~TestHandleParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 };
 
 class TestJSONParent : public PTestJSONParent {
+  friend class PTestJSONParent;
+
  public:
   TestJSONParent() {}
   virtual ~TestJSONParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvTest(const JSONVariant& i,
-                                           JSONVariant* o) override;
+  mozilla::ipc::IPCResult RecvTest(const JSONVariant& i, JSONVariant* o);
 
-  virtual PTestHandleParent* AllocPTestHandleParent() override {
+  PTestHandleParent* AllocPTestHandleParent() {
     return mKid = new TestHandleParent();
   }
 
-  virtual bool DeallocPTestHandleParent(PTestHandleParent* actor) override {
+  bool DeallocPTestHandleParent(PTestHandleParent* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
@@ -55,28 +56,30 @@ class TestJSONParent : public PTestJSONP
 
 class TestHandleChild : public PTestHandleChild {
  public:
   TestHandleChild() {}
   virtual ~TestHandleChild() {}
 };
 
 class TestJSONChild : public PTestJSONChild {
+  friend class PTestJSONChild;
+
  public:
   TestJSONChild() {}
   virtual ~TestJSONChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual PTestHandleChild* AllocPTestHandleChild() override {
+  PTestHandleChild* AllocPTestHandleChild() {
     return mKid = new TestHandleChild();
   }
 
-  virtual bool DeallocPTestHandleChild(PTestHandleChild* actor) override {
+  bool DeallocPTestHandleChild(PTestHandleChild* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
--- a/ipc/ipdl/test/cxx/TestLatency.h
+++ b/ipc/ipdl/test/cxx/TestLatency.h
@@ -10,32 +10,34 @@
 
 #define NR_TRIALS 10000
 #define NR_SPAMS 25000
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestLatencyParent : public PTestLatencyParent {
+  friend class PTestLatencyParent;
+
  private:
   typedef mozilla::TimeStamp TimeStamp;
   typedef mozilla::TimeDuration TimeDuration;
 
  public:
   TestLatencyParent();
   virtual ~TestLatencyParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvPong() override;
-  virtual mozilla::ipc::IPCResult RecvPong5() override;
+  mozilla::ipc::IPCResult RecvPong();
+  mozilla::ipc::IPCResult RecvPong5();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
 
     passed(
         "\n"
         "  average #ping-pong/sec:        %g\n"
         "  average #ping5-pong5/sec:      %g\n"
@@ -68,30 +70,31 @@ class TestLatencyParent : public PTestLa
 
   int mPPTrialsToGo;
   int mPP5TrialsToGo;
   uint32_t mNumChildProcessedCompressedSpams;
   uint32_t mWhichPong5;
 };
 
 class TestLatencyChild : public PTestLatencyChild {
+  friend class PTestLatencyChild;
+
  public:
   TestLatencyChild();
   virtual ~TestLatencyChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvPing() override;
-  virtual mozilla::ipc::IPCResult RecvPing5() override;
-  virtual mozilla::ipc::IPCResult AnswerRpc() override;
-  virtual mozilla::ipc::IPCResult RecvSpam() override;
-  virtual mozilla::ipc::IPCResult AnswerSynchro() override;
-  virtual mozilla::ipc::IPCResult RecvCompressedSpam(
-      const uint32_t& seqno) override;
-  virtual mozilla::ipc::IPCResult AnswerSynchro2(
-      uint32_t* lastSeqno, uint32_t* numMessagesDispatched) override;
+  mozilla::ipc::IPCResult RecvPing();
+  mozilla::ipc::IPCResult RecvPing5();
+  mozilla::ipc::IPCResult AnswerRpc();
+  mozilla::ipc::IPCResult RecvSpam();
+  mozilla::ipc::IPCResult AnswerSynchro();
+  mozilla::ipc::IPCResult RecvCompressedSpam(const uint32_t& seqno);
+  mozilla::ipc::IPCResult AnswerSynchro2(uint32_t* lastSeqno,
+                                         uint32_t* numMessagesDispatched);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 
   uint32_t mLastSeqno;
   uint32_t mNumProcessedCompressedSpams;
--- a/ipc/ipdl/test/cxx/TestManyChildAllocs.h
+++ b/ipc/ipdl/test/cxx/TestManyChildAllocs.h
@@ -10,67 +10,69 @@
 #include "mozilla/_ipdltest/PTestManyChildAllocsSubChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 // top-level protocol
 
 class TestManyChildAllocsParent : public PTestManyChildAllocsParent {
+  friend class PTestManyChildAllocsParent;
+
  public:
   TestManyChildAllocsParent();
   virtual ~TestManyChildAllocsParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvDone() override;
-  virtual bool DeallocPTestManyChildAllocsSubParent(
-      PTestManyChildAllocsSubParent* __a) override;
-  virtual PTestManyChildAllocsSubParent* AllocPTestManyChildAllocsSubParent()
-      override;
+  mozilla::ipc::IPCResult RecvDone();
+  bool DeallocPTestManyChildAllocsSubParent(PTestManyChildAllocsSubParent* __a);
+  PTestManyChildAllocsSubParent* AllocPTestManyChildAllocsSubParent();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestManyChildAllocsChild : public PTestManyChildAllocsChild {
+  friend class PTestManyChildAllocsChild;
+
  public:
   TestManyChildAllocsChild();
   virtual ~TestManyChildAllocsChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvGo() override;
-  virtual bool DeallocPTestManyChildAllocsSubChild(
-      PTestManyChildAllocsSubChild* __a) override;
-  virtual PTestManyChildAllocsSubChild* AllocPTestManyChildAllocsSubChild()
-      override;
+  mozilla::ipc::IPCResult RecvGo();
+  bool DeallocPTestManyChildAllocsSubChild(PTestManyChildAllocsSubChild* __a);
+  PTestManyChildAllocsSubChild* AllocPTestManyChildAllocsSubChild();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 // do-nothing sub-protocol actors
 
 class TestManyChildAllocsSubParent : public PTestManyChildAllocsSubParent {
+  friend class PTestManyChildAllocsSubParent;
+
  public:
   TestManyChildAllocsSubParent() {}
   virtual ~TestManyChildAllocsSubParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
-  virtual mozilla::ipc::IPCResult RecvHello() override { return IPC_OK(); }
+  mozilla::ipc::IPCResult RecvHello() { return IPC_OK(); }
 };
 
 class TestManyChildAllocsSubChild : public PTestManyChildAllocsSubChild {
  public:
   TestManyChildAllocsSubChild() {}
   virtual ~TestManyChildAllocsSubChild() {}
 };
 
--- a/ipc/ipdl/test/cxx/TestMultiMgrs.h
+++ b/ipc/ipdl/test/cxx/TestMultiMgrs.h
@@ -24,92 +24,92 @@ class TestMultiMgrsBottomParent : public
   TestMultiMgrsBottomParent() {}
   virtual ~TestMultiMgrsBottomParent() {}
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 };
 
 class TestMultiMgrsLeftParent : public PTestMultiMgrsLeftParent {
+  friend class PTestMultiMgrsLeftParent;
+
  public:
   TestMultiMgrsLeftParent() {}
   virtual ~TestMultiMgrsLeftParent() {}
 
   bool HasChild(TestMultiMgrsBottomParent* c) {
     return ManagedPTestMultiMgrsBottomParent().Contains(c);
   }
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 
-  virtual PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent()
-      override {
+  PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent() {
     return new TestMultiMgrsBottomParent();
   }
 
-  virtual bool DeallocPTestMultiMgrsBottomParent(
-      PTestMultiMgrsBottomParent* actor) override {
+  bool DeallocPTestMultiMgrsBottomParent(PTestMultiMgrsBottomParent* actor) {
     delete actor;
     return true;
   }
 };
 
 class TestMultiMgrsRightParent : public PTestMultiMgrsRightParent {
+  friend class PTestMultiMgrsRightParent;
+
  public:
   TestMultiMgrsRightParent() {}
   virtual ~TestMultiMgrsRightParent() {}
 
   bool HasChild(TestMultiMgrsBottomParent* c) {
     return ManagedPTestMultiMgrsBottomParent().Contains(c);
   }
 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 
-  virtual PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent()
-      override {
+  PTestMultiMgrsBottomParent* AllocPTestMultiMgrsBottomParent() {
     return new TestMultiMgrsBottomParent();
   }
 
-  virtual bool DeallocPTestMultiMgrsBottomParent(
-      PTestMultiMgrsBottomParent* actor) override {
+  bool DeallocPTestMultiMgrsBottomParent(PTestMultiMgrsBottomParent* actor) {
     delete actor;
     return true;
   }
 };
 
 class TestMultiMgrsParent : public PTestMultiMgrsParent {
+  friend class PTestMultiMgrsParent;
+
  public:
   TestMultiMgrsParent() {}
   virtual ~TestMultiMgrsParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvOK() override;
+  mozilla::ipc::IPCResult RecvOK();
 
-  virtual PTestMultiMgrsLeftParent* AllocPTestMultiMgrsLeftParent() override {
+  PTestMultiMgrsLeftParent* AllocPTestMultiMgrsLeftParent() {
     return new TestMultiMgrsLeftParent();
   }
 
-  virtual bool DeallocPTestMultiMgrsLeftParent(
-      PTestMultiMgrsLeftParent* actor) override {
+  bool DeallocPTestMultiMgrsLeftParent(PTestMultiMgrsLeftParent* actor) {
     delete actor;
     return true;
   }
 
-  virtual PTestMultiMgrsRightParent* AllocPTestMultiMgrsRightParent() override {
+  PTestMultiMgrsRightParent* AllocPTestMultiMgrsRightParent() {
     return new TestMultiMgrsRightParent();
   }
 
-  virtual bool DeallocPTestMultiMgrsRightParent(
-      PTestMultiMgrsRightParent* actor) override {
+  bool DeallocPTestMultiMgrsRightParent(PTestMultiMgrsRightParent* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
@@ -122,92 +122,94 @@ class TestMultiMgrsParent : public PTest
 
 class TestMultiMgrsBottomChild : public PTestMultiMgrsBottomChild {
  public:
   TestMultiMgrsBottomChild() {}
   virtual ~TestMultiMgrsBottomChild() {}
 };
 
 class TestMultiMgrsLeftChild : public PTestMultiMgrsLeftChild {
+  friend class PTestMultiMgrsLeftChild;
+
  public:
   TestMultiMgrsLeftChild() {}
   virtual ~TestMultiMgrsLeftChild() {}
 
   bool HasChild(PTestMultiMgrsBottomChild* c) {
     return ManagedPTestMultiMgrsBottomChild().Contains(c);
   }
 
  protected:
   virtual mozilla::ipc::IPCResult RecvPTestMultiMgrsBottomConstructor(
       PTestMultiMgrsBottomChild* actor) override;
 
-  virtual PTestMultiMgrsBottomChild* AllocPTestMultiMgrsBottomChild() override {
+  PTestMultiMgrsBottomChild* AllocPTestMultiMgrsBottomChild() {
     return new TestMultiMgrsBottomChild();
   }
 
-  virtual bool DeallocPTestMultiMgrsBottomChild(
-      PTestMultiMgrsBottomChild* actor) override {
+  bool DeallocPTestMultiMgrsBottomChild(PTestMultiMgrsBottomChild* actor) {
     delete actor;
     return true;
   }
 };
 
 class TestMultiMgrsRightChild : public PTestMultiMgrsRightChild {
+  friend class PTestMultiMgrsRightChild;
+
  public:
   TestMultiMgrsRightChild() {}
   virtual ~TestMultiMgrsRightChild() {}
 
   bool HasChild(PTestMultiMgrsBottomChild* c) {
     return ManagedPTestMultiMgrsBottomChild().Contains(c);
   }
 
  protected:
   virtual mozilla::ipc::IPCResult RecvPTestMultiMgrsBottomConstructor(
       PTestMultiMgrsBottomChild* actor) override;
 
-  virtual PTestMultiMgrsBottomChild* AllocPTestMultiMgrsBottomChild() override {
+  PTestMultiMgrsBottomChild* AllocPTestMultiMgrsBottomChild() {
     return new TestMultiMgrsBottomChild();
   }
 
-  virtual bool DeallocPTestMultiMgrsBottomChild(
-      PTestMultiMgrsBottomChild* actor) override {
+  bool DeallocPTestMultiMgrsBottomChild(PTestMultiMgrsBottomChild* actor) {
     delete actor;
     return true;
   }
 };
 
 class TestMultiMgrsChild : public PTestMultiMgrsChild {
+  friend class PTestMultiMgrsChild;
+
  public:
   TestMultiMgrsChild() {}
   virtual ~TestMultiMgrsChild() {}
 
   void Main();
 
   PTestMultiMgrsBottomChild* mBottomL;
   PTestMultiMgrsBottomChild* mBottomR;
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvCheck() override;
+  mozilla::ipc::IPCResult RecvCheck();
 
-  virtual PTestMultiMgrsLeftChild* AllocPTestMultiMgrsLeftChild() override {
+  PTestMultiMgrsLeftChild* AllocPTestMultiMgrsLeftChild() {
     return new TestMultiMgrsLeftChild();
   }
 
-  virtual bool DeallocPTestMultiMgrsLeftChild(
-      PTestMultiMgrsLeftChild* actor) override {
+  bool DeallocPTestMultiMgrsLeftChild(PTestMultiMgrsLeftChild* actor) {
     delete actor;
     return true;
   }
 
-  virtual PTestMultiMgrsRightChild* AllocPTestMultiMgrsRightChild() override {
+  PTestMultiMgrsRightChild* AllocPTestMultiMgrsRightChild() {
     return new TestMultiMgrsRightChild();
   }
 
-  virtual bool DeallocPTestMultiMgrsRightChild(
-      PTestMultiMgrsRightChild* actor) override {
+  bool DeallocPTestMultiMgrsRightChild(PTestMultiMgrsRightChild* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitChild();
--- a/ipc/ipdl/test/cxx/TestNestedLoops.h
+++ b/ipc/ipdl/test/cxx/TestNestedLoops.h
@@ -5,48 +5,52 @@
 
 #include "mozilla/_ipdltest/PTestNestedLoopsParent.h"
 #include "mozilla/_ipdltest/PTestNestedLoopsChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestNestedLoopsParent : public PTestNestedLoopsParent {
+  friend class PTestNestedLoopsParent;
+
  public:
   TestNestedLoopsParent();
   virtual ~TestNestedLoopsParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvNonce() override;
+  mozilla::ipc::IPCResult RecvNonce();
 
   void BreakNestedLoop();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
   bool mBreakNestedLoop;
 };
 
 class TestNestedLoopsChild : public PTestNestedLoopsChild {
+  friend class PTestNestedLoopsChild;
+
  public:
   TestNestedLoopsChild();
   virtual ~TestNestedLoopsChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult AnswerR() override;
+  mozilla::ipc::IPCResult AnswerR();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestOffMainThreadPainting.h
+++ b/ipc/ipdl/test/cxx/TestOffMainThreadPainting.h
@@ -21,20 +21,20 @@ class TestOffMainThreadPaintingParent fi
   static bool RunTestInThreads() { return false; }
   static bool RunTestInProcesses() { return true; }
 
   void Main();
 
   MOZ_IMPLICIT TestOffMainThreadPaintingParent();
   ~TestOffMainThreadPaintingParent() override;
 
-  ipc::IPCResult RecvFinishedLayout(const uint64_t& aTxnId) override;
-  ipc::IPCResult RecvAsyncMessage(const uint64_t& aTxnId) override;
-  ipc::IPCResult RecvSyncMessage(const uint64_t& aTxnId) override;
-  ipc::IPCResult RecvEndTest() override;
+  ipc::IPCResult RecvFinishedLayout(const uint64_t& aTxnId);
+  ipc::IPCResult RecvAsyncMessage(const uint64_t& aTxnId);
+  ipc::IPCResult RecvSyncMessage(const uint64_t& aTxnId);
+  ipc::IPCResult RecvEndTest();
   void ActorDestroy(ActorDestroyReason aWhy) override;
 
   void NotifyFinishedPaint(const uint64_t& aTxnId);
 
  private:
   RefPtr<TestPaintThreadParent> mPaintActor;
   Maybe<uint64_t> mCompletedTxn;
   Maybe<uint64_t> mPaintedTxn;
@@ -44,17 +44,17 @@ class TestOffMainThreadPaintingParent fi
 
 // Analagous to LayerTransactionChild.
 class TestOffMainThreadPaintingChild final : public PTestLayoutThreadChild {
  public:
   TestOffMainThreadPaintingChild();
   ~TestOffMainThreadPaintingChild() override;
 
   ipc::IPCResult RecvStartTest(
-      ipc::Endpoint<PTestPaintThreadChild>&& aEndpoint) override;
+      ipc::Endpoint<PTestPaintThreadChild>&& aEndpoint);
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void ProcessingError(Result aCode, const char* aReason) override;
 
  private:
   void IssueTransaction();
 
  private:
   UniquePtr<base::Thread> mPaintThread;
@@ -68,17 +68,17 @@ class TestOffMainThreadPaintingChild fin
 
 class TestPaintThreadParent final : public PTestPaintThreadParent {
  public:
   explicit TestPaintThreadParent(TestOffMainThreadPaintingParent* aMainBridge);
 
   NS_INLINE_DECL_THREADSAFE_REFCOUNTING(TestPaintThreadParent);
 
   bool Bind(ipc::Endpoint<PTestPaintThreadParent>&& aEndpoint);
-  ipc::IPCResult RecvFinishedPaint(const uint64_t& aTxnId) override;
+  ipc::IPCResult RecvFinishedPaint(const uint64_t& aTxnId);
   void ActorDestroy(ActorDestroyReason aWhy) override;
   void DeallocPTestPaintThreadParent() override;
 
  private:
   ~TestPaintThreadParent() override;
 
  private:
   TestOffMainThreadPaintingParent* mMainBridge;
--- a/ipc/ipdl/test/cxx/TestRPC.h
+++ b/ipc/ipdl/test/cxx/TestRPC.h
@@ -14,20 +14,20 @@ class TestRPCParent : public PTestRPCPar
   TestRPCParent();
   virtual ~TestRPCParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
-  mozilla::ipc::IPCResult RecvTest1_Start(uint32_t* aResult) override;
-  mozilla::ipc::IPCResult RecvTest1_InnerEvent(uint32_t* aResult) override;
-  mozilla::ipc::IPCResult RecvTest2_Start() override;
-  mozilla::ipc::IPCResult RecvTest2_OutOfOrder() override;
+  mozilla::ipc::IPCResult RecvTest1_Start(uint32_t* aResult);
+  mozilla::ipc::IPCResult RecvTest1_InnerEvent(uint32_t* aResult);
+  mozilla::ipc::IPCResult RecvTest2_Start();
+  mozilla::ipc::IPCResult RecvTest2_OutOfOrder();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     if (!reentered_) fail("never processed raced RPC call!");
     if (!resolved_first_cpow_) fail("never resolved first CPOW!");
     passed("ok");
     QuitParent();
   }
@@ -37,21 +37,21 @@ class TestRPCParent : public PTestRPCPar
   bool resolved_first_cpow_;
 };
 
 class TestRPCChild : public PTestRPCChild {
  public:
   TestRPCChild();
   virtual ~TestRPCChild();
 
-  mozilla::ipc::IPCResult RecvStart() override;
-  mozilla::ipc::IPCResult RecvTest1_InnerQuery(uint32_t* aResult) override;
-  mozilla::ipc::IPCResult RecvTest1_NoReenter(uint32_t* aResult) override;
-  mozilla::ipc::IPCResult RecvTest2_FirstUrgent() override;
-  mozilla::ipc::IPCResult RecvTest2_SecondUrgent() override;
+  mozilla::ipc::IPCResult RecvStart();
+  mozilla::ipc::IPCResult RecvTest1_InnerQuery(uint32_t* aResult);
+  mozilla::ipc::IPCResult RecvTest1_NoReenter(uint32_t* aResult);
+  mozilla::ipc::IPCResult RecvTest2_FirstUrgent();
+  mozilla::ipc::IPCResult RecvTest2_SecondUrgent();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestRaceDeadlock.h
+++ b/ipc/ipdl/test/cxx/TestRaceDeadlock.h
@@ -5,54 +5,58 @@
 
 #include "mozilla/_ipdltest/PTestRaceDeadlockParent.h"
 #include "mozilla/_ipdltest/PTestRaceDeadlockChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestRaceDeadlockParent : public PTestRaceDeadlockParent {
+  friend class PTestRaceDeadlockParent;
+
  public:
   TestRaceDeadlockParent();
   virtual ~TestRaceDeadlockParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
   virtual bool ShouldContinueFromReplyTimeout() override;
 
   void Test1();
 
-  virtual mozilla::ipc::IPCResult RecvStartRace() override;
-  virtual mozilla::ipc::IPCResult AnswerLose() override;
+  mozilla::ipc::IPCResult RecvStartRace();
+  mozilla::ipc::IPCResult AnswerLose();
 
   virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestRaceDeadlockChild : public PTestRaceDeadlockChild {
+  friend class PTestRaceDeadlockChild;
+
  public:
   TestRaceDeadlockChild();
   virtual ~TestRaceDeadlockChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStartRace() override;
+  mozilla::ipc::IPCResult RecvStartRace();
 
-  virtual mozilla::ipc::IPCResult AnswerWin() override;
+  mozilla::ipc::IPCResult AnswerWin();
 
-  virtual mozilla::ipc::IPCResult AnswerRpc() override;
+  mozilla::ipc::IPCResult AnswerRpc();
 
   virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
--- a/ipc/ipdl/test/cxx/TestRaceDeferral.h
+++ b/ipc/ipdl/test/cxx/TestRaceDeferral.h
@@ -5,53 +5,57 @@
 
 #include "mozilla/_ipdltest/PTestRaceDeferralParent.h"
 #include "mozilla/_ipdltest/PTestRaceDeferralChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestRaceDeferralParent : public PTestRaceDeferralParent {
+  friend class PTestRaceDeferralParent;
+
  public:
   TestRaceDeferralParent();
   virtual ~TestRaceDeferralParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
   void Test1();
 
-  virtual mozilla::ipc::IPCResult AnswerLose() override;
+  mozilla::ipc::IPCResult AnswerLose();
 
   virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
   bool mProcessedLose;
 };
 
 class TestRaceDeferralChild : public PTestRaceDeferralChild {
+  friend class PTestRaceDeferralChild;
+
  public:
   TestRaceDeferralChild();
   virtual ~TestRaceDeferralChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStartRace() override;
+  mozilla::ipc::IPCResult RecvStartRace();
 
-  virtual mozilla::ipc::IPCResult AnswerWin() override;
+  mozilla::ipc::IPCResult AnswerWin();
 
-  virtual mozilla::ipc::IPCResult AnswerRpc() override;
+  mozilla::ipc::IPCResult AnswerRpc();
 
   virtual mozilla::ipc::RacyInterruptPolicy MediateInterruptRace(
       const MessageInfo& parent, const MessageInfo& child) override;
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
--- a/ipc/ipdl/test/cxx/TestRacyInterruptReplies.h
+++ b/ipc/ipdl/test/cxx/TestRacyInterruptReplies.h
@@ -5,51 +5,55 @@
 
 #include "mozilla/_ipdltest/PTestRacyInterruptRepliesParent.h"
 #include "mozilla/_ipdltest/PTestRacyInterruptRepliesChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestRacyInterruptRepliesParent : public PTestRacyInterruptRepliesParent {
+  friend class PTestRacyInterruptRepliesParent;
+
  public:
   TestRacyInterruptRepliesParent();
   virtual ~TestRacyInterruptRepliesParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvA_() override;
+  mozilla::ipc::IPCResult RecvA_();
 
-  virtual mozilla::ipc::IPCResult Answer_R(int* replyNum) override;
+  mozilla::ipc::IPCResult Answer_R(int* replyNum);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
  private:
   int mReplyNum;
 };
 
 class TestRacyInterruptRepliesChild : public PTestRacyInterruptRepliesChild {
+  friend class PTestRacyInterruptRepliesChild;
+
  public:
   TestRacyInterruptRepliesChild();
   virtual ~TestRacyInterruptRepliesChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerR_(int* replyNum) override;
+  mozilla::ipc::IPCResult AnswerR_(int* replyNum);
 
-  virtual mozilla::ipc::IPCResult RecvChildTest() override;
+  mozilla::ipc::IPCResult RecvChildTest();
 
-  virtual mozilla::ipc::IPCResult Recv_A() override;
+  mozilla::ipc::IPCResult Recv_A();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 
  private:
   int mReplyNum;
--- a/ipc/ipdl/test/cxx/TestRacyReentry.h
+++ b/ipc/ipdl/test/cxx/TestRacyReentry.h
@@ -5,48 +5,52 @@
 
 #include "mozilla/_ipdltest/PTestRacyReentryParent.h"
 #include "mozilla/_ipdltest/PTestRacyReentryChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestRacyReentryParent : public PTestRacyReentryParent {
+  friend class PTestRacyReentryParent;
+
  public:
   TestRacyReentryParent();
   virtual ~TestRacyReentryParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerE() override;
+  mozilla::ipc::IPCResult AnswerE();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
   bool mRecvdE;
 };
 
 class TestRacyReentryChild : public PTestRacyReentryChild {
+  friend class PTestRacyReentryChild;
+
  public:
   TestRacyReentryChild();
   virtual ~TestRacyReentryChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult RecvN() override;
+  mozilla::ipc::IPCResult RecvN();
 
-  virtual mozilla::ipc::IPCResult AnswerH() override;
+  mozilla::ipc::IPCResult AnswerH();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestRacyUndefer.h
+++ b/ipc/ipdl/test/cxx/TestRacyUndefer.h
@@ -5,51 +5,55 @@
 
 #include "mozilla/_ipdltest/PTestRacyUndeferParent.h"
 #include "mozilla/_ipdltest/PTestRacyUndeferChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestRacyUndeferParent : public PTestRacyUndeferParent {
+  friend class PTestRacyUndeferParent;
+
  public:
   TestRacyUndeferParent();
   virtual ~TestRacyUndeferParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerSpam() override;
+  mozilla::ipc::IPCResult AnswerSpam();
 
-  virtual mozilla::ipc::IPCResult AnswerRaceWinTwice() override;
+  mozilla::ipc::IPCResult AnswerRaceWinTwice();
 
-  virtual mozilla::ipc::IPCResult RecvDone() override;
+  mozilla::ipc::IPCResult RecvDone();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestRacyUndeferChild : public PTestRacyUndeferChild {
+  friend class PTestRacyUndeferChild;
+
  public:
   TestRacyUndeferChild();
   virtual ~TestRacyUndeferChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult RecvAwakenSpam() override;
-  virtual mozilla::ipc::IPCResult RecvAwakenRaceWinTwice() override;
+  mozilla::ipc::IPCResult RecvAwakenSpam();
+  mozilla::ipc::IPCResult RecvAwakenRaceWinTwice();
 
-  virtual mozilla::ipc::IPCResult AnswerRace() override;
+  mozilla::ipc::IPCResult AnswerRace();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestSanity.h
+++ b/ipc/ipdl/test/cxx/TestSanity.h
@@ -5,46 +5,48 @@
 
 #include "mozilla/_ipdltest/PTestSanityParent.h"
 #include "mozilla/_ipdltest/PTestSanityChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestSanityParent : public PTestSanityParent {
+  friend class PTestSanityParent;
+
  public:
   TestSanityParent();
   virtual ~TestSanityParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvPong(const int& one,
-                                           const float& zeroPtTwoFive,
-                                           const uint8_t& dummy) override;
+  mozilla::ipc::IPCResult RecvPong(const int& one, const float& zeroPtTwoFive,
+                                   const uint8_t& dummy);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestSanityChild : public PTestSanityChild {
+  friend class PTestSanityChild;
+
  public:
   TestSanityChild();
   virtual ~TestSanityChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvPing(const int& zero,
-                                           const float& zeroPtFive,
-                                           const int8_t& dummy) override;
+  mozilla::ipc::IPCResult RecvPing(const int& zero, const float& zeroPtFive,
+                                   const int8_t& dummy);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestSelfManageRoot.h
+++ b/ipc/ipdl/test/cxx/TestSelfManageRoot.h
@@ -10,98 +10,102 @@
 
 namespace mozilla {
 namespace _ipdltest {
 
 //-----------------------------------------------------------------------------
 // Parent side
 
 class TestSelfManageParent : public PTestSelfManageParent {
+  friend class PTestSelfManageParent;
+
  public:
   TestSelfManageParent() { MOZ_COUNT_CTOR(TestSelfManageParent); }
   virtual ~TestSelfManageParent() { MOZ_COUNT_DTOR(TestSelfManageParent); }
 
   ActorDestroyReason mWhy;
 
  protected:
-  virtual PTestSelfManageParent* AllocPTestSelfManageParent() override {
+  PTestSelfManageParent* AllocPTestSelfManageParent() {
     return new TestSelfManageParent();
   }
 
-  virtual bool DeallocPTestSelfManageParent(PTestSelfManageParent* a) override {
-    return true;
-  }
+  bool DeallocPTestSelfManageParent(PTestSelfManageParent* a) { return true; }
 
   virtual void ActorDestroy(ActorDestroyReason why) override { mWhy = why; }
 };
 
 class TestSelfManageRootParent : public PTestSelfManageRootParent {
+  friend class PTestSelfManageRootParent;
+
  public:
   TestSelfManageRootParent() { MOZ_COUNT_CTOR(TestSelfManageRootParent); }
   virtual ~TestSelfManageRootParent() {
     MOZ_COUNT_DTOR(TestSelfManageRootParent);
   }
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual PTestSelfManageParent* AllocPTestSelfManageParent() override {
+  PTestSelfManageParent* AllocPTestSelfManageParent() {
     return new TestSelfManageParent();
   }
 
-  virtual bool DeallocPTestSelfManageParent(PTestSelfManageParent* a) override {
-    return true;
-  }
+  bool DeallocPTestSelfManageParent(PTestSelfManageParent* a) { return true; }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 //-----------------------------------------------------------------------------
 // Child side
 
 class TestSelfManageChild : public PTestSelfManageChild {
+  friend class PTestSelfManageChild;
+
  public:
   TestSelfManageChild() { MOZ_COUNT_CTOR(TestSelfManageChild); }
   virtual ~TestSelfManageChild() { MOZ_COUNT_DTOR(TestSelfManageChild); }
 
  protected:
-  virtual PTestSelfManageChild* AllocPTestSelfManageChild() override {
+  PTestSelfManageChild* AllocPTestSelfManageChild() {
     return new TestSelfManageChild();
   }
 
-  virtual bool DeallocPTestSelfManageChild(PTestSelfManageChild* a) override {
+  bool DeallocPTestSelfManageChild(PTestSelfManageChild* a) {
     delete a;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {}
 };
 
 class TestSelfManageRootChild : public PTestSelfManageRootChild {
+  friend class PTestSelfManageRootChild;
+
  public:
   TestSelfManageRootChild() { MOZ_COUNT_CTOR(TestSelfManageRootChild); }
   virtual ~TestSelfManageRootChild() {
     MOZ_COUNT_DTOR(TestSelfManageRootChild);
   }
 
   void Main();
 
  protected:
-  virtual PTestSelfManageChild* AllocPTestSelfManageChild() override {
+  PTestSelfManageChild* AllocPTestSelfManageChild() {
     return new TestSelfManageChild();
   }
 
-  virtual bool DeallocPTestSelfManageChild(PTestSelfManageChild* a) override {
+  bool DeallocPTestSelfManageChild(PTestSelfManageChild* a) {
     delete a;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
--- a/ipc/ipdl/test/cxx/TestShmem.h
+++ b/ipc/ipdl/test/cxx/TestShmem.h
@@ -5,44 +5,48 @@
 
 #include "mozilla/_ipdltest/PTestShmemParent.h"
 #include "mozilla/_ipdltest/PTestShmemChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestShmemParent : public PTestShmemParent {
+  friend class PTestShmemParent;
+
  public:
   TestShmemParent() {}
   virtual ~TestShmemParent() {}
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvTake(Shmem&& mem, Shmem&& unsafe,
-                                           const size_t& expectedSize) override;
+  mozilla::ipc::IPCResult RecvTake(Shmem&& mem, Shmem&& unsafe,
+                                   const size_t& expectedSize);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestShmemChild : public PTestShmemChild {
+  friend class PTestShmemChild;
+
  public:
   TestShmemChild() {}
   virtual ~TestShmemChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvGive(Shmem&& mem, Shmem&& unsafe,
-                                           const size_t& expectedSize) override;
+  mozilla::ipc::IPCResult RecvGive(Shmem&& mem, Shmem&& unsafe,
+                                   const size_t& expectedSize);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestShutdown.h
+++ b/ipc/ipdl/test/cxx/TestShutdown.h
@@ -28,72 +28,73 @@ class TestShutdownSubsubParent : public 
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
  private:
   bool mExpectParentDeleted;
 };
 
 class TestShutdownSubParent : public PTestShutdownSubParent {
+  friend class PTestShutdownSubParent;
+
  public:
   explicit TestShutdownSubParent(bool expectCrash)
       : mExpectCrash(expectCrash), mDeletedCount(0) {}
 
   virtual ~TestShutdownSubParent() {
     if (2 != mDeletedCount) fail("managees outliving manager!");
   }
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override {
+  mozilla::ipc::IPCResult AnswerStackFrame() {
     if (!CallStackFrame()) {
       return IPC_FAIL_NO_REASON(this);
     }
     return IPC_OK();
   }
 
-  virtual PTestShutdownSubsubParent* AllocPTestShutdownSubsubParent(
-      const bool& expectParentDelete) override {
+  PTestShutdownSubsubParent* AllocPTestShutdownSubsubParent(
+      const bool& expectParentDelete) {
     return new TestShutdownSubsubParent(expectParentDelete);
   }
 
-  virtual bool DeallocPTestShutdownSubsubParent(
-      PTestShutdownSubsubParent* actor) override {
+  bool DeallocPTestShutdownSubsubParent(PTestShutdownSubsubParent* actor) {
     delete actor;
     ++mDeletedCount;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
  private:
   bool mExpectCrash;
   int mDeletedCount;
 };
 
 class TestShutdownParent : public PTestShutdownParent {
+  friend class PTestShutdownParent;
+
  public:
   TestShutdownParent() {}
   virtual ~TestShutdownParent() {}
 
   static bool RunTestInProcesses() { return true; }
   // FIXME/bug 703323 Could work if modified
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvSync() override { return IPC_OK(); }
+  mozilla::ipc::IPCResult RecvSync() { return IPC_OK(); }
 
-  virtual PTestShutdownSubParent* AllocPTestShutdownSubParent(
-      const bool& expectCrash) override {
+  PTestShutdownSubParent* AllocPTestShutdownSubParent(const bool& expectCrash) {
     return new TestShutdownSubParent(expectCrash);
   }
 
-  virtual bool DeallocPTestShutdownSubParent(
-      PTestShutdownSubParent* actor) override {
+  bool DeallocPTestShutdownSubParent(PTestShutdownSubParent* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 //-----------------------------------------------------------------------------
@@ -108,56 +109,57 @@ class TestShutdownSubsubChild : public P
  protected:
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
  private:
   bool mExpectParentDeleted;
 };
 
 class TestShutdownSubChild : public PTestShutdownSubChild {
+  friend class PTestShutdownSubChild;
+
  public:
   explicit TestShutdownSubChild(bool expectCrash) : mExpectCrash(expectCrash) {}
 
   virtual ~TestShutdownSubChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
-  virtual PTestShutdownSubsubChild* AllocPTestShutdownSubsubChild(
-      const bool& expectParentDelete) override {
+  PTestShutdownSubsubChild* AllocPTestShutdownSubsubChild(
+      const bool& expectParentDelete) {
     return new TestShutdownSubsubChild(expectParentDelete);
   }
 
-  virtual bool DeallocPTestShutdownSubsubChild(
-      PTestShutdownSubsubChild* actor) override {
+  bool DeallocPTestShutdownSubsubChild(PTestShutdownSubsubChild* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 
  private:
   bool mExpectCrash;
 };
 
 class TestShutdownChild : public PTestShutdownChild {
+  friend class PTestShutdownChild;
+
  public:
   TestShutdownChild() {}
   virtual ~TestShutdownChild() {}
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual PTestShutdownSubChild* AllocPTestShutdownSubChild(
-      const bool& expectCrash) override {
+  PTestShutdownSubChild* AllocPTestShutdownSubChild(const bool& expectCrash) {
     return new TestShutdownSubChild(expectCrash);
   }
 
-  virtual bool DeallocPTestShutdownSubChild(
-      PTestShutdownSubChild* actor) override {
+  bool DeallocPTestShutdownSubChild(PTestShutdownSubChild* actor) {
     delete actor;
     return true;
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override;
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestStackHooks.h
+++ b/ipc/ipdl/test/cxx/TestStackHooks.h
@@ -5,42 +5,44 @@
 
 #include "mozilla/_ipdltest/PTestStackHooksParent.h"
 #include "mozilla/_ipdltest/PTestStackHooksChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestStackHooksParent : public PTestStackHooksParent {
+  friend class PTestStackHooksParent;
+
  public:
   TestStackHooksParent();
   virtual ~TestStackHooksParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvAsync() override {
+  mozilla::ipc::IPCResult RecvAsync() {
     if (!mOnStack) fail("not on C++ stack?!");
     return IPC_OK();
   }
 
-  virtual mozilla::ipc::IPCResult RecvSync() override {
+  mozilla::ipc::IPCResult RecvSync() {
     if (!mOnStack) fail("not on C++ stack?!");
     return IPC_OK();
   }
 
-  virtual mozilla::ipc::IPCResult AnswerRpc() override {
+  mozilla::ipc::IPCResult AnswerRpc() {
     if (!mOnStack) fail("not on C++ stack?!");
     return IPC_OK();
   }
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 
   virtual void EnteredCxxStack() override { mOnStack = true; }
@@ -50,26 +52,28 @@ class TestStackHooksParent : public PTes
   virtual void ExitedCall() override { --mIncallDepth; }
 
  private:
   bool mOnStack;
   int mIncallDepth;
 };
 
 class TestStackHooksChild : public PTestStackHooksChild {
+  friend class PTestStackHooksChild;
+
  public:
   TestStackHooksChild();
   virtual ~TestStackHooksChild();
 
   void RunTests();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
 
     if (mEntered != mExited) fail("unbalanced enter/exit notifications");
 
     if (mOnStack)
       fail("computing mOnStack went awry; should have failed above assertion");
--- a/ipc/ipdl/test/cxx/TestSyncError.h
+++ b/ipc/ipdl/test/cxx/TestSyncError.h
@@ -5,46 +5,50 @@
 
 #include "mozilla/_ipdltest/PTestSyncErrorParent.h"
 #include "mozilla/_ipdltest/PTestSyncErrorChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestSyncErrorParent : public PTestSyncErrorParent {
+  friend class PTestSyncErrorParent;
+
  public:
   TestSyncErrorParent();
   virtual ~TestSyncErrorParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvError() override;
+  mozilla::ipc::IPCResult RecvError();
 
   virtual void ProcessingError(Result aCode, const char* aReason) override {
     // Ignore errors
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestSyncErrorChild : public PTestSyncErrorChild {
+  friend class PTestSyncErrorChild;
+
  public:
   TestSyncErrorChild();
   virtual ~TestSyncErrorChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
   virtual void ProcessingError(Result aCode, const char* aReason) override {
     // Ignore errors
   }
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
--- a/ipc/ipdl/test/cxx/TestSyncHang.h
+++ b/ipc/ipdl/test/cxx/TestSyncHang.h
@@ -24,22 +24,24 @@ class TestSyncHangParent : public PTestS
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestSyncHangChild : public PTestSyncHangChild {
+  friend class PTestSyncHangChild;
+
  public:
   TestSyncHangChild();
   virtual ~TestSyncHangChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvUnusedMessage() override;
+  mozilla::ipc::IPCResult RecvUnusedMessage();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestSyncWakeup.h
+++ b/ipc/ipdl/test/cxx/TestSyncWakeup.h
@@ -5,52 +5,56 @@
 
 #include "mozilla/_ipdltest/PTestSyncWakeupParent.h"
 #include "mozilla/_ipdltest/PTestSyncWakeupChild.h"
 
 namespace mozilla {
 namespace _ipdltest {
 
 class TestSyncWakeupParent : public PTestSyncWakeupParent {
+  friend class PTestSyncWakeupParent;
+
  public:
   TestSyncWakeupParent();
   virtual ~TestSyncWakeupParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return true; }
 
   void Main();
 
  protected:
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
-  virtual mozilla::ipc::IPCResult RecvSync1() override;
+  mozilla::ipc::IPCResult RecvSync1();
 
-  virtual mozilla::ipc::IPCResult RecvSync2() override;
+  mozilla::ipc::IPCResult RecvSync2();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     passed("ok");
     QuitParent();
   }
 };
 
 class TestSyncWakeupChild : public PTestSyncWakeupChild {
+  friend class PTestSyncWakeupChild;
+
  public:
   TestSyncWakeupChild();
   virtual ~TestSyncWakeupChild();
 
  protected:
-  virtual mozilla::ipc::IPCResult RecvStart() override;
+  mozilla::ipc::IPCResult RecvStart();
 
-  virtual mozilla::ipc::IPCResult RecvNote1() override;
+  mozilla::ipc::IPCResult RecvNote1();
 
-  virtual mozilla::ipc::IPCResult AnswerStackFrame() override;
+  mozilla::ipc::IPCResult AnswerStackFrame();
 
-  virtual mozilla::ipc::IPCResult RecvNote2() override;
+  mozilla::ipc::IPCResult RecvNote2();
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) fail("unexpected destruction!");
     QuitChild();
   }
 
  private:
   bool mDone;
--- a/ipc/ipdl/test/cxx/TestUniquePtrIPC.h
+++ b/ipc/ipdl/test/cxx/TestUniquePtrIPC.h
@@ -38,20 +38,19 @@ class TestUniquePtrIPCParent : public PT
 class TestUniquePtrIPCChild : public PTestUniquePtrIPCChild {
  public:
   TestUniquePtrIPCChild() { MOZ_COUNT_CTOR(TestUniquePtrIPCChild); }
   virtual ~TestUniquePtrIPCChild() { MOZ_COUNT_DTOR(TestUniquePtrIPCChild); }
 
   mozilla::ipc::IPCResult RecvTestMessage(UniquePtr<int>&& aA1,
                                           UniquePtr<DummyStruct>&& aA2,
                                           const DummyStruct& aA3,
-                                          UniquePtr<int>&& aA4) override;
+                                          UniquePtr<int>&& aA4);
 
-  mozilla::ipc::IPCResult RecvTestSendReference(
-      UniquePtr<DummyStruct>&& aA) override;
+  mozilla::ipc::IPCResult RecvTestSendReference(UniquePtr<DummyStruct>&& aA);
 
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (NormalShutdown != why) {
       fail("Abnormal shutdown of child");
     }
     QuitChild();
   }
 };
--- a/ipc/ipdl/test/cxx/TestUrgency.h
+++ b/ipc/ipdl/test/cxx/TestUrgency.h
@@ -14,41 +14,41 @@ class TestUrgencyParent : public PTestUr
   TestUrgencyParent();
   virtual ~TestUrgencyParent();
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
 
-  mozilla::ipc::IPCResult RecvTest1(uint32_t *value) override;
-  mozilla::ipc::IPCResult RecvTest2() override;
-  mozilla::ipc::IPCResult RecvTest3(uint32_t *value) override;
+  mozilla::ipc::IPCResult RecvTest1(uint32_t *value);
+  mozilla::ipc::IPCResult RecvTest2();
+  mozilla::ipc::IPCResult RecvTest3(uint32_t *value);
   mozilla::ipc::IPCResult RecvTest4_Begin();
   mozilla::ipc::IPCResult RecvTest4_NestedSync();
-  mozilla::ipc::IPCResult RecvFinalTest_Begin() override;
+  mozilla::ipc::IPCResult RecvFinalTest_Begin();
 
   bool ShouldContinueFromReplyTimeout() override { return false; }
   virtual void ActorDestroy(ActorDestroyReason why) override {
     passed("ok");
     QuitParent();
   }
 
  private:
   bool inreply_;
 };
 
 class TestUrgencyChild : public PTestUrgencyChild {
  public:
   TestUrgencyChild();
   virtual ~TestUrgencyChild();
 
-  mozilla::ipc::IPCResult RecvStart() override;
-  mozilla::ipc::IPCResult RecvReply1(uint32_t *reply) override;
-  mozilla::ipc::IPCResult RecvReply2(uint32_t *reply) override;
+  mozilla::ipc::IPCResult RecvStart();
+  mozilla::ipc::IPCResult RecvReply1(uint32_t *reply);
+  mozilla::ipc::IPCResult RecvReply2(uint32_t *reply);
 
   virtual void ActorDestroy(ActorDestroyReason why) override { QuitChild(); }
 
  private:
   uint32_t test_;
 };
 
 }  // namespace _ipdltest
--- a/ipc/ipdl/test/cxx/TestUrgentHangs.h
+++ b/ipc/ipdl/test/cxx/TestUrgentHangs.h
@@ -16,19 +16,19 @@ class TestUrgentHangsParent : public PTe
 
   static bool RunTestInProcesses() { return true; }
   static bool RunTestInThreads() { return false; }
 
   void Main();
   void SecondStage();
   void ThirdStage();
 
-  mozilla::ipc::IPCResult RecvTest1_2() override;
-  mozilla::ipc::IPCResult RecvTestInner() override;
-  mozilla::ipc::IPCResult RecvTestInnerUrgent() override;
+  mozilla::ipc::IPCResult RecvTest1_2();
+  mozilla::ipc::IPCResult RecvTestInner();
+  mozilla::ipc::IPCResult RecvTestInnerUrgent();
 
   bool ShouldContinueFromReplyTimeout() override { return false; }
   virtual void ActorDestroy(ActorDestroyReason why) override {
     if (mInnerCount != 1) {
       fail("wrong mInnerCount");
     }
     if (mInnerUrgentCount != 2) {
       fail("wrong mInnerUrgentCount");
@@ -41,24 +41,24 @@ class TestUrgentHangsParent : public PTe
   size_t mInnerCount, mInnerUrgentCount;
 };
 
 class TestUrgentHangsChild : public PTestUrgentHangsChild {
  public:
   TestUrgentHangsChild();
   virtual ~TestUrgentHangsChild();
 
-  mozilla::ipc::IPCResult RecvTest1_1() override;
-  mozilla::ipc::IPCResult RecvTest1_3() override;
-  mozilla::ipc::IPCResult RecvTest2() override;
-  mozilla::ipc::IPCResult RecvTest3() override;
-  mozilla::ipc::IPCResult RecvTest4() override;
-  mozilla::ipc::IPCResult RecvTest4_1() override;
-  mozilla::ipc::IPCResult RecvTest5() override;
-  mozilla::ipc::IPCResult RecvTest5_1() override;
+  mozilla::ipc::IPCResult RecvTest1_1();
+  mozilla::ipc::IPCResult RecvTest1_3();
+  mozilla::ipc::IPCResult RecvTest2();
+  mozilla::ipc::IPCResult RecvTest3();
+  mozilla::ipc::IPCResult RecvTest4();
+  mozilla::ipc::IPCResult RecvTest4_1();
+  mozilla::ipc::IPCResult RecvTest5();
+  mozilla::ipc::IPCResult RecvTest5_1();
 
   virtual void ActorDestroy(ActorDestroyReason why) override { QuitChild(); }
 };
 
 }  // namespace _ipdltest
 }  // namespace mozilla
 
 #endif  // ifndef mozilla__ipdltest_TestUrgentHangs_h
--- a/ipc/ipdl/test/cxx/moz.build
+++ b/ipc/ipdl/test/cxx/moz.build
@@ -6,16 +6,55 @@
 
 DIRS += ['app']
 
 EXPORTS.mozilla._ipdltest += [
     'IPDLUnitTestProcessChild.h',
     'IPDLUnitTests.h',
     'IPDLUnitTestTypes.h',
     'IPDLUnitTestUtils.h',
+    'TestActorPunning.h',
+    'TestAsyncReturns.h',
+    'TestBadActor.h',
+    'TestCancel.h',
+    'TestCrashCleanup.h',
+    'TestDataStructures.h',
+    'TestDemon.h',
+    'TestDesc.h',
+    'TestEndpointBridgeMain.h',
+    'TestEndpointOpens.h',
+    'TestFailedCtor.h',
+    'TestHangs.h',
+    'TestHighestPrio.h',
+    'TestInterruptErrorCleanup.h',
+    'TestInterruptRaces.h',
+    'TestInterruptShutdownRace.h',
+    'TestJSON.h',
+    'TestLatency.h',
+    'TestManyChildAllocs.h',
+    'TestMultiMgrs.h',
+    'TestNestedLoops.h',
+    'TestOffMainThreadPainting.h',
+    'TestRaceDeadlock.h',
+    'TestRaceDeferral.h',
+    'TestRacyInterruptReplies.h',
+    'TestRacyReentry.h',
+    'TestRacyUndefer.h',
+    'TestRPC.h',
+    'TestSanity.h',
+    'TestSelfManageRoot.h',
+    'TestShmem.h',
+    'TestShutdown.h',
+    'TestStackHooks.h',
+    'TestSyncError.h',
+    'TestSyncHang.h',
+    'TestSyncWakeup.h',
+    'TestUniquePtrIPC.h',
+    'TestUrgency.h',
+    'TestUrgentHangs.h',
 ]
 
 SOURCES += [
     'TestActorPunning.cpp',
     'TestAsyncReturns.cpp',
     'TestBadActor.cpp',
     'TestCancel.cpp',
     'TestCrashCleanup.cpp',
--- a/ipc/ipdl/test/ipdl/error/Nullable.ipdl
+++ b/ipc/ipdl/test/ipdl/error/Nullable.ipdl
@@ -1,6 +1,6 @@
 //error: `nullable' qualifier for type `int' makes no sense
 
-protocol Nullable {
+protocol PNullable {
 child:
     async Msg(nullable int i);
 };
rename from ipc/ipdl/test/ipdl/error/asyncMessageListed.ipdl
rename to ipc/ipdl/test/ipdl/error/PasyncMessageListed.ipdl
--- a/ipc/ipdl/test/ipdl/error/asyncMessageListed.ipdl
+++ b/ipc/ipdl/test/ipdl/error/PasyncMessageListed.ipdl
@@ -1,6 +1,6 @@
-//error: IPC message asyncMessageListed::Msg is async, can be delisted
+//error: IPC message PasyncMessageListed::Msg is async, can be delisted
 
-protocol asyncMessageListed {
+protocol PasyncMessageListed {
 parent:
     async Msg();
 };
rename from ipc/ipdl/test/ipdl/ok/AsyncReturn.ipdl
rename to ipc/ipdl/test/ipdl/ok/PAsyncReturn.ipdl
--- a/ipc/ipdl/test/ipdl/ok/AsyncReturn.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PAsyncReturn.ipdl
@@ -1,8 +1,8 @@
 // Async messages are not allowed to return values.
 
 //error: asynchronous message `Msg' declares return values
 
-protocol AsyncReturn {
+protocol PAsyncReturn {
 child:
     async Msg() returns(int32_t aNumber);
 };
rename from ipc/ipdl/test/ipdl/ok/Delete.ipdl
rename to ipc/ipdl/test/ipdl/ok/PDelete.ipdl
--- a/ipc/ipdl/test/ipdl/ok/Delete.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PDelete.ipdl
@@ -1,8 +1,8 @@
-include protocol DeleteSub;
+include protocol PDeleteSub;
 
-sync protocol Delete {
-    manages DeleteSub;
+sync protocol PDelete {
+    manages PDeleteSub;
 
 child:
-    async DeleteSub();
+    async PDeleteSub();
 };
rename from ipc/ipdl/test/ipdl/ok/DeleteSub.ipdl
rename to ipc/ipdl/test/ipdl/ok/PDeleteSub.ipdl
--- a/ipc/ipdl/test/ipdl/ok/DeleteSub.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PDeleteSub.ipdl
@@ -1,10 +1,10 @@
-include protocol Delete;
+include protocol PDelete;
 
-sync protocol DeleteSub {
-    manager Delete;
+sync protocol PDeleteSub {
+    manager PDelete;
 
 parent:
     sync __delete__(int x) returns (double d);
 
 };
 
rename from ipc/ipdl/test/ipdl/ok/EndpointDecl.ipdl
rename to ipc/ipdl/test/ipdl/ok/PEndpointDecl.ipdl
--- a/ipc/ipdl/test/ipdl/ok/EndpointDecl.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PEndpointDecl.ipdl
@@ -1,18 +1,18 @@
 
 // Basic test that Endpoint types are declared for protocols, within
 // that protocol.
 
 struct Whatever {
-  Endpoint<EndpointDeclParent> par;
-  Endpoint<EndpointDeclChild> chi;
+  Endpoint<PEndpointDeclParent> par;
+  Endpoint<PEndpointDeclChild> chi;
 };
 
 namespace mozilla {
 
-protocol EndpointDecl {
+protocol PEndpointDecl {
   child:
-    async Message(Endpoint<EndpointDeclParent> aEndpointParent,
-                  Endpoint<EndpointDeclChild> aEndpointChild);
+    async Message(Endpoint<PEndpointDeclParent> aEndpointParent,
+                  Endpoint<PEndpointDeclChild> aEndpointChild);
 };
 
 }
rename from ipc/ipdl/test/ipdl/ok/EndpointUse.ipdl
rename to ipc/ipdl/test/ipdl/ok/PEndpointUse.ipdl
--- a/ipc/ipdl/test/ipdl/ok/EndpointUse.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PEndpointUse.ipdl
@@ -1,9 +1,9 @@
-include protocol EndpointDecl;
+include protocol PEndpointDecl;
 
 // Basic test that Endpoint types are declared for included protocols.
 
-protocol EndpointUse {
+protocol PEndpointUse {
   child:
-    async Message(Endpoint<EndpointDeclParent> aEndpointParent,
-                  Endpoint<EndpointDeclChild> aEndpointChild);
+    async Message(Endpoint<PEndpointDeclParent> aEndpointParent,
+                  Endpoint<PEndpointDeclChild> aEndpointChild);
 };
rename from ipc/ipdl/test/ipdl/ok/Nullable.ipdl
rename to ipc/ipdl/test/ipdl/ok/PNullable.ipdl
--- a/ipc/ipdl/test/ipdl/ok/Nullable.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PNullable.ipdl
@@ -1,11 +1,11 @@
 union Union {
-    nullable Nullable;
-    nullable Nullable[];
+    nullable PNullable;
+    nullable PNullable[];
 };
 
-protocol Nullable {
+protocol PNullable {
 child:
-    async Msg(nullable Nullable n);
-    async Msg2(nullable Nullable[] N);
+    async Msg(nullable PNullable n);
+    async Msg2(nullable PNullable[] N);
     async Msg3(Union u);
 };
rename from ipc/ipdl/test/ipdl/ok/Struct.ipdl
rename to ipc/ipdl/test/ipdl/ok/PStruct.ipdl
--- a/ipc/ipdl/test/ipdl/ok/Struct.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PStruct.ipdl
@@ -1,10 +1,10 @@
 struct S {
     int i;
     double d;
 };
 
-sync protocol Struct {
+sync protocol PStruct {
 parent:
     sync test(S s) returns (S ss);
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/SyncSyncManagee.ipdl
rename to ipc/ipdl/test/ipdl/ok/PSyncSyncManagee.ipdl
--- a/ipc/ipdl/test/ipdl/ok/SyncSyncManagee.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PSyncSyncManagee.ipdl
@@ -1,7 +1,7 @@
-include protocol SyncSyncManager;
+include protocol PSyncSyncManager;
 
-sync protocol SyncSyncManagee {
-    manager SyncSyncManager;
+sync protocol PSyncSyncManagee {
+    manager PSyncSyncManager;
 child:
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/SyncSyncManager.ipdl
rename to ipc/ipdl/test/ipdl/ok/PSyncSyncManager.ipdl
--- a/ipc/ipdl/test/ipdl/ok/SyncSyncManager.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PSyncSyncManager.ipdl
@@ -1,11 +1,11 @@
-include protocol SyncSyncManagee;
+include protocol PSyncSyncManagee;
 
 /* The main reason for this test is that it would have caught a bug
  * in the Rust IPDL parser that was treating "sync" like "async" in the
  * nested case.
  */
-nested(upto not) sync protocol SyncSyncManager {
-    manages SyncSyncManagee;
+nested(upto not) sync protocol PSyncSyncManager {
+    manages PSyncSyncManagee;
 parent:
-    async SyncSyncManagee();
+    async PSyncSyncManagee();
 };
rename from ipc/ipdl/test/ipdl/ok/actorparam.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pactorparam.ipdl
--- a/ipc/ipdl/test/ipdl/ok/actorparam.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pactorparam.ipdl
@@ -1,5 +1,5 @@
-protocol actorparam {
+protocol Pactorparam {
 
-child: async Msg(actorparam p);
+child: async Msg(Pactorparam p);
 
 };
rename from ipc/ipdl/test/ipdl/ok/actorreturn.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pactorreturn.ipdl
--- a/ipc/ipdl/test/ipdl/ok/actorreturn.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pactorreturn.ipdl
@@ -1,6 +1,6 @@
-sync protocol actorreturn {
+sync protocol Pactorreturn {
 
 parent:
-    sync Msg(actorreturn p) returns (actorreturn r);
+    sync Msg(Pactorreturn p) returns (Pactorreturn r);
 
 };
rename from ipc/ipdl/test/ipdl/ok/array_Basic.ipdl
rename to ipc/ipdl/test/ipdl/ok/Parray_Basic.ipdl
--- a/ipc/ipdl/test/ipdl/ok/array_Basic.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Parray_Basic.ipdl
@@ -1,4 +1,4 @@
-protocol array_Basic {
+protocol Parray_Basic {
 child:
     async Msg(int[] array);
 };
rename from ipc/ipdl/test/ipdl/ok/array_OfActors.ipdl
rename to ipc/ipdl/test/ipdl/ok/Parray_OfActors.ipdl
--- a/ipc/ipdl/test/ipdl/ok/array_OfActors.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Parray_OfActors.ipdl
@@ -1,10 +1,10 @@
-include protocol array_OfActorsSub;
+include protocol Parray_OfActorsSub;
 
-protocol array_OfActors {
-    manages array_OfActorsSub;
+protocol Parray_OfActors {
+    manages Parray_OfActorsSub;
 
 child:
-    async Msg(array_OfActorsSub[] p);
+    async Msg(Parray_OfActorsSub[] p);
 
-    async array_OfActorsSub();
+    async Parray_OfActorsSub();
 };
rename from ipc/ipdl/test/ipdl/ok/array_OfActorsSub.ipdl
rename to ipc/ipdl/test/ipdl/ok/Parray_OfActorsSub.ipdl
--- a/ipc/ipdl/test/ipdl/ok/array_OfActorsSub.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Parray_OfActorsSub.ipdl
@@ -1,7 +1,7 @@
-include protocol array_OfActors;
+include protocol Parray_OfActors;
 
-protocol array_OfActorsSub {
-    manager array_OfActors;
+protocol Parray_OfActorsSub {
+    manager Parray_OfActors;
 
 child: async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/array_Union.ipdl
rename to ipc/ipdl/test/ipdl/ok/Parray_Union.ipdl
--- a/ipc/ipdl/test/ipdl/ok/array_Union.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Parray_Union.ipdl
@@ -1,10 +1,10 @@
 union Union {
     int[];
     int;
     double;
 };
 
-sync protocol array_Union {
+sync protocol Parray_Union {
 parent:
     sync Msg(Union u, Union[] au) returns (Union r);
 };
rename from ipc/ipdl/test/ipdl/ok/basicUsing.ipdl
rename to ipc/ipdl/test/ipdl/ok/PbasicUsing.ipdl
--- a/ipc/ipdl/test/ipdl/ok/basicUsing.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PbasicUsing.ipdl
@@ -11,12 +11,12 @@ union SomeUnion
   SomeType;
   SomeClass;
   SomeStruct;
   SomeRefcountedType;
   SomeRefcountedClass;
   SomeRefcountedStruct;
 };
 
-protocol basicUsing {
+protocol PbasicUsing {
 child:
     async Msg(SomeUnion foo);
 };
rename from ipc/ipdl/test/ipdl/ok/builtins.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pbuiltins.ipdl
--- a/ipc/ipdl/test/ipdl/ok/builtins.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pbuiltins.ipdl
@@ -1,9 +1,9 @@
-protocol builtins {
+protocol Pbuiltins {
 
     // sanity-check that "essential" builtins are being declared
 
 child: async Msg(bool b,
            char c,
            int i,
            long l,
 
rename from ipc/ipdl/test/ipdl/ok/bytebuf.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pbytebuf.ipdl
--- a/ipc/ipdl/test/ipdl/ok/bytebuf.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pbytebuf.ipdl
@@ -1,13 +1,13 @@
 union Foo {
     int;
     ByteBuf;
 };
 
-intr protocol bytebuf {
+intr protocol Pbytebuf {
 parent:
     async Msg(ByteBuf s, Foo f);
     sync SyncMsg(ByteBuf s, Foo f)
         returns (ByteBuf t, Foo g);
     intr InterruptMsg(ByteBuf s, Foo f)
         returns (ByteBuf t, Foo g);
 };
rename from ipc/ipdl/test/ipdl/ok/empty.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pempty.ipdl
--- a/ipc/ipdl/test/ipdl/ok/empty.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pempty.ipdl
@@ -1,3 +1,3 @@
-protocol empty {
+protocol Pempty {
 child: async Msg();
 };
rename from ipc/ipdl/test/ipdl/ok/emptyStruct.ipdl
rename to ipc/ipdl/test/ipdl/ok/PemptyStruct.ipdl
--- a/ipc/ipdl/test/ipdl/ok/emptyStruct.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PemptyStruct.ipdl
@@ -1,3 +1,3 @@
 struct empty { };
 
-protocol emptyStruct { child:  async __delete__(); };
+protocol PemptyStruct { child:  async __delete__(); };
rename from ipc/ipdl/test/ipdl/ok/headerProto.ipdl
rename to ipc/ipdl/test/ipdl/ok/PheaderProto.ipdl
--- a/ipc/ipdl/test/ipdl/ok/headerProto.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PheaderProto.ipdl
@@ -1,10 +1,10 @@
 include header;
 
 namespace c {
 
-protocol headerProto {
+protocol PheaderProto {
 child:
     async __delete__(foo a, baz b, Inner1 c, Inner2 d, X x);
 };
 
 }
rename from ipc/ipdl/test/ipdl/ok/intrProtocol.ipdl
rename to ipc/ipdl/test/ipdl/ok/PintrProtocol.ipdl
--- a/ipc/ipdl/test/ipdl/ok/intrProtocol.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PintrProtocol.ipdl
@@ -1,9 +1,9 @@
-intr protocol intrProtocol {
+intr protocol PintrProtocol {
 
     // sanity check of Interrupt protocols
 child:
     async AsyncMsg();
 
 parent:
     sync SyncMsg(int i) returns (int r);
 
rename from ipc/ipdl/test/ipdl/ok/jetpack.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pjetpack.ipdl
--- a/ipc/ipdl/test/ipdl/ok/jetpack.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pjetpack.ipdl
@@ -1,5 +1,5 @@
-sync protocol jetpack {
+sync protocol Pjetpack {
 child:
     async __delete__();
 
 };
rename from ipc/ipdl/test/ipdl/ok/manageSelf.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmanageSelf.ipdl
--- a/ipc/ipdl/test/ipdl/ok/manageSelf.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmanageSelf.ipdl
@@ -1,10 +1,10 @@
-include protocol manageSelf_Toplevel;
+include protocol PmanageSelf_Toplevel;
 
-protocol manageSelf {
-    manager manageSelf_Toplevel or manageSelf;
-    manages manageSelf;
+protocol PmanageSelf {
+    manager PmanageSelf_Toplevel or PmanageSelf;
+    manages PmanageSelf;
 
 child:
-    async manageSelf();
+    async PmanageSelf();
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/manageSelf_Toplevel.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmanageSelf_Toplevel.ipdl
--- a/ipc/ipdl/test/ipdl/ok/manageSelf_Toplevel.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmanageSelf_Toplevel.ipdl
@@ -1,9 +1,9 @@
-include protocol manageSelf;
+include protocol PmanageSelf;
 
-protocol manageSelf_Toplevel {
-    manages manageSelf;
+protocol PmanageSelf_Toplevel {
+    manages PmanageSelf;
 
 child:
-    async manageSelf();
+    async PmanageSelf();
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/managedProtocol.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmanagedProtocol.ipdl
--- a/ipc/ipdl/test/ipdl/ok/managedProtocol.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmanagedProtocol.ipdl
@@ -1,8 +1,8 @@
-include protocol managerProtocol;
+include protocol PmanagerProtocol;
 
-protocol managedProtocol {
-    manager managerProtocol;
+protocol PmanagedProtocol {
+    manager PmanagerProtocol;
 
 child:
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/managerProtocol.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmanagerProtocol.ipdl
--- a/ipc/ipdl/test/ipdl/ok/managerProtocol.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmanagerProtocol.ipdl
@@ -1,11 +1,11 @@
-include protocol managedProtocol;
+include protocol PmanagedProtocol;
 
 // sanity check of managed/manager protocols
 
-protocol managerProtocol {
-    manages managedProtocol;
+protocol PmanagerProtocol {
+    manages PmanagedProtocol;
 
 parent:
-    async managedProtocol(int i);
+    async PmanagedProtocol(int i);
 
 };
rename from ipc/ipdl/test/ipdl/ok/maybe_Basic.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pmaybe_Basic.ipdl
--- a/ipc/ipdl/test/ipdl/ok/maybe_Basic.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pmaybe_Basic.ipdl
@@ -1,4 +1,4 @@
-protocol maybe_Basic {
+protocol Pmaybe_Basic {
 child:
     async Msg(int? maybe);
 };
rename from ipc/ipdl/test/ipdl/ok/maybe_OfActors.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pmaybe_OfActors.ipdl
--- a/ipc/ipdl/test/ipdl/ok/maybe_OfActors.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pmaybe_OfActors.ipdl
@@ -1,10 +1,10 @@
-include protocol maybe_OfActorsSub;
+include protocol Pmaybe_OfActorsSub;
 
-protocol maybe_OfActors {
-    manages maybe_OfActorsSub;
+protocol Pmaybe_OfActors {
+    manages Pmaybe_OfActorsSub;
 
 child:
-    async Msg(maybe_OfActorsSub? p);
+    async Msg(Pmaybe_OfActorsSub? p);
 
-    async maybe_OfActorsSub();
+    async Pmaybe_OfActorsSub();
 };
rename from ipc/ipdl/test/ipdl/ok/maybe_OfActorsSub.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pmaybe_OfActorsSub.ipdl
--- a/ipc/ipdl/test/ipdl/ok/maybe_OfActorsSub.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pmaybe_OfActorsSub.ipdl
@@ -1,7 +1,7 @@
-include protocol maybe_OfActors;
+include protocol Pmaybe_OfActors;
 
-protocol maybe_OfActorsSub {
-    manager maybe_OfActors;
+protocol Pmaybe_OfActorsSub {
+    manager Pmaybe_OfActors;
 
 child: async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/maybe_Union.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pmaybe_Union.ipdl
--- a/ipc/ipdl/test/ipdl/ok/maybe_Union.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pmaybe_Union.ipdl
@@ -1,10 +1,10 @@
 union MaybeUnion {
     int[];
     int;
     double;
 };
 
-sync protocol maybe_Union {
+sync protocol Pmaybe_Union {
 parent:
     async Msg(MaybeUnion u, MaybeUnion? au) returns (MaybeUnion r);
 };
rename from ipc/ipdl/test/ipdl/ok/media.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pmedia.ipdl
--- a/ipc/ipdl/test/ipdl/ok/media.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pmedia.ipdl
@@ -1,5 +1,5 @@
-sync protocol media {
+sync protocol Pmedia {
 child:
     async __delete__();
 
 };
rename from ipc/ipdl/test/ipdl/ok/messageCompress.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmessageCompress.ipdl
--- a/ipc/ipdl/test/ipdl/ok/messageCompress.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmessageCompress.ipdl
@@ -1,4 +1,4 @@
-intr protocol messageCompress {
+intr protocol PmessageCompress {
 child:
     async foo() compress;
 };
rename from ipc/ipdl/test/ipdl/ok/messageVerify.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmessageVerify.ipdl
--- a/ipc/ipdl/test/ipdl/ok/messageVerify.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmessageVerify.ipdl
@@ -1,12 +1,12 @@
-include protocol messageVerifyTopLevel;
+include protocol PmessageVerifyTopLevel;
 
-intr protocol messageVerify {
-  manager messageVerifyTopLevel;
+intr protocol PmessageVerify {
+  manager PmessageVerifyTopLevel;
 
 parent:
     sync __delete__(uint32_t x) returns (double rv1) verify;
     async msg1() verify;
     async msg2(uint32_t aParam1) verify;
     sync msg3()
       returns (uint32_t rv1) verify;
     sync msg4(uint32_t aParam1)
rename from ipc/ipdl/test/ipdl/ok/messageVerifyTopLevel.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmessageVerifyTopLevel.ipdl
--- a/ipc/ipdl/test/ipdl/ok/messageVerifyTopLevel.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmessageVerifyTopLevel.ipdl
@@ -1,7 +1,7 @@
-include protocol messageVerify;
+include protocol PmessageVerify;
 
-intr protocol messageVerifyTopLevel{
-  manages messageVerify;
+intr protocol PmessageVerifyTopLevel{
+  manages PmessageVerify;
   parent:
-    sync messageVerify(uint32_t aParam1) returns (double rv1) verify;
+    sync PmessageVerify(uint32_t aParam1) returns (double rv1) verify;
 };
rename from ipc/ipdl/test/ipdl/ok/multiManaged.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmultiManaged.ipdl
--- a/ipc/ipdl/test/ipdl/ok/multiManaged.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmultiManaged.ipdl
@@ -1,9 +1,9 @@
-include protocol multiManager1;
-include protocol multiManager2;
+include protocol PmultiManager1;
+include protocol PmultiManager2;
 
-protocol multiManaged {
-    manager multiManager1 or multiManager2;
+protocol PmultiManaged {
+    manager PmultiManager1 or PmultiManager2;
 
 child:
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/multiManager1.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmultiManager1.ipdl
--- a/ipc/ipdl/test/ipdl/ok/multiManager1.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmultiManager1.ipdl
@@ -1,8 +1,8 @@
-include protocol multiManaged;
+include protocol PmultiManaged;
 
-protocol multiManager1 {
-    manages multiManaged;
+protocol PmultiManager1 {
+    manages PmultiManaged;
 
 child:
-    async multiManaged();
+    async PmultiManaged();
 };
rename from ipc/ipdl/test/ipdl/ok/multiManager2.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmultiManager2.ipdl
--- a/ipc/ipdl/test/ipdl/ok/multiManager2.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmultiManager2.ipdl
@@ -1,8 +1,8 @@
-include protocol multiManaged;
+include protocol PmultiManaged;
 
-protocol multiManager2 {
-    manages multiManaged;
+protocol PmultiManager2 {
+    manages PmultiManaged;
 
 child:
-    async multiManaged();
+    async PmultiManaged();
 };
rename from ipc/ipdl/test/ipdl/ok/multipleUsingCxxTypes.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmultipleUsingCxxTypes.ipdl
--- a/ipc/ipdl/test/ipdl/ok/multipleUsingCxxTypes.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmultipleUsingCxxTypes.ipdl
@@ -1,7 +1,7 @@
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 using struct mozilla::void_t from "ipc/IPCMessageUtils.h";
 
-protocol multipleUsingCxxTypes {
+protocol PmultipleUsingCxxTypes {
 child:
     async Msg(void_t foo);
 };
rename from ipc/ipdl/test/ipdl/ok/mutualRecStructUnion.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmutualRecStructUnion.ipdl
--- a/ipc/ipdl/test/ipdl/ok/mutualRecStructUnion.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmutualRecStructUnion.ipdl
@@ -9,13 +9,13 @@ union Y {
     Z;
 };
 
 struct Z {
     X x;
     Y y;
 };
 
-protocol mutualRecStructUnion {
+protocol PmutualRecStructUnion {
 child:
     async Test(X x, Y y, Z z);
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/mutualRecUnion.ipdl
rename to ipc/ipdl/test/ipdl/ok/PmutualRecUnion.ipdl
--- a/ipc/ipdl/test/ipdl/ok/mutualRecUnion.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PmutualRecUnion.ipdl
@@ -9,13 +9,13 @@ union Y {
     Z;
 };
 
 union Z {
     double;
     X;
 };
 
-protocol mutualRecUnion {
+protocol PmutualRecUnion {
 child:
     async Test(X x, Y y, Z z);
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/namespace_Basic.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pnamespace_Basic.ipdl
--- a/ipc/ipdl/test/ipdl/ok/namespace_Basic.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pnamespace_Basic.ipdl
@@ -1,12 +1,12 @@
 namespace basic {
 
 // sanity check of namespaced protocols
 
-protocol namespace_Basic {
+protocol Pnamespace_Basic {
 
 child:
     async Msg();
 
 };
 
 } // namespace basic
rename from ipc/ipdl/test/ipdl/ok/noRedeclCrossMessage.ipdl
rename to ipc/ipdl/test/ipdl/ok/PnoRedeclCrossMessage.ipdl
--- a/ipc/ipdl/test/ipdl/ok/noRedeclCrossMessage.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PnoRedeclCrossMessage.ipdl
@@ -1,9 +1,9 @@
-protocol noRedeclCrossMessage {
+protocol PnoRedeclCrossMessage {
 
     // each message has its own scope for param/return names
 
 child:
     async Msg1(int f);
     async Msg2(int f);
 
 };
rename from ipc/ipdl/test/ipdl/ok/plugin.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pplugin.ipdl
--- a/ipc/ipdl/test/ipdl/ok/plugin.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pplugin.ipdl
@@ -1,5 +1,5 @@
-intr protocol plugin {
+intr protocol Pplugin {
 child:
     async __delete__();
 
 };
rename from ipc/ipdl/test/ipdl/ok/selfRecUnion.ipdl
rename to ipc/ipdl/test/ipdl/ok/PselfRecUnion.ipdl
--- a/ipc/ipdl/test/ipdl/ok/selfRecUnion.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PselfRecUnion.ipdl
@@ -1,11 +1,11 @@
 union R {
     int;
     double;
     R;
 };
 
-protocol selfRecUnion {
+protocol PselfRecUnion {
 child:
     async Test(R r);
     async __delete__();
 };
rename from ipc/ipdl/test/ipdl/ok/shmem.ipdl
rename to ipc/ipdl/test/ipdl/ok/Pshmem.ipdl
--- a/ipc/ipdl/test/ipdl/ok/shmem.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Pshmem.ipdl
@@ -1,13 +1,13 @@
 union Foo {
     int;
     Shmem;
 };
 
-intr protocol shmem {
+intr protocol Pshmem {
 parent:
     async Msg(Shmem s, Foo f);
     sync SyncMsg(Shmem s, Foo f)
         returns (Shmem t, Foo g);
     intr InterruptMsg(Shmem s, Foo f)
         returns (Shmem t, Foo g);
 };
rename from ipc/ipdl/test/ipdl/ok/syncProtocol.ipdl
rename to ipc/ipdl/test/ipdl/ok/PsyncProtocol.ipdl
--- a/ipc/ipdl/test/ipdl/ok/syncProtocol.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PsyncProtocol.ipdl
@@ -1,9 +1,9 @@
-sync protocol syncProtocol {
+sync protocol PsyncProtocol {
 
     // sanity check of sync protocols
 
 child:
     async AsyncMsg();
 
 parent:
     sync SyncMsg() returns (int i);
rename from ipc/ipdl/test/ipdl/ok/threeDirections.ipdl
rename to ipc/ipdl/test/ipdl/ok/PthreeDirections.ipdl
--- a/ipc/ipdl/test/ipdl/ok/threeDirections.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/PthreeDirections.ipdl
@@ -1,9 +1,9 @@
-protocol threeDirections {
+protocol PthreeDirections {
 
     // sanity check that the three direction specifiers are being accepted
 child:
     async ChildMsg();
 
 parent:
     async ParentMsg();
 
rename from ipc/ipdl/test/ipdl/ok/union_Basic.ipdl
rename to ipc/ipdl/test/ipdl/ok/Punion_Basic.ipdl
--- a/ipc/ipdl/test/ipdl/ok/union_Basic.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Punion_Basic.ipdl
@@ -1,11 +1,11 @@
 union Basic {
     int;
     double;
 };
 
-sync protocol union_Basic {
+sync protocol Punion_Basic {
 
 parent:
     sync Msg(Basic p) returns (Basic r);
 
 };
rename from ipc/ipdl/test/ipdl/ok/union_Namespaced.ipdl
rename to ipc/ipdl/test/ipdl/ok/Punion_Namespaced.ipdl
--- a/ipc/ipdl/test/ipdl/ok/union_Namespaced.ipdl
+++ b/ipc/ipdl/test/ipdl/ok/Punion_Namespaced.ipdl
@@ -5,14 +5,14 @@ union Socks {
     double;
 };
 
 } // namespace kitties
 
 
 namespace puppies {
 
-protocol union_Namespaced {
+protocol Punion_Namespaced {
 child:
     async Msg(Socks s);
 };
 
 } // namespace puppies
--- a/ipc/ipdl/test/ipdl/sync-messages.ini
+++ b/ipc/ipdl/test/ipdl/sync-messages.ini
@@ -1,24 +1,24 @@
-[actorreturn::Msg]
-[array_Union::Msg]
-[union_Basic::Msg]
-[Struct::test]
-[intrProtocol::SyncMsg]
-[intrProtocol::InterruptMsg]
-[shmem::SyncMsg]
-[shmem::InterruptMsg]
-[bytebuf::SyncMsg]
-[bytebuf::InterruptMsg]
-[syncProtocol::SyncMsg]
-[messageVerify::__delete__]
-[messageVerify::msg3]
-[messageVerify::msg4]
-[messageVerifyTopLevel::messageVerify]
-[DeleteSub::__delete__]
-[intrMessageCompress::foo]
-[intrMessageCompress::bar]
-[syncMessageCompress::foo]
-[syncParentToChild::Msg]
-[tooWeakIntrSync::Msg]
-[tooWeakSyncAsync::Msg]
-[undeclReturnType::Msg]
-[asyncMessageListed::Msg]
+[Pactorreturn::Msg]
+[Parray_Union::Msg]
+[Punion_Basic::Msg]
+[PStruct::test]
+[PintrProtocol::SyncMsg]
+[PintrProtocol::InterruptMsg]
+[Pshmem::SyncMsg]
+[Pshmem::InterruptMsg]
+[Pbytebuf::SyncMsg]
+[Pbytebuf::InterruptMsg]
+[PsyncProtocol::SyncMsg]
+[PmessageVerify::__delete__]
+[PmessageVerify::msg3]
+[PmessageVerify::msg4]
+[PmessageVerifyTopLevel::PmessageVerify]
+[PDeleteSub::__delete__]
+[PintrMessageCompress::foo]
+[PintrMessageCompress::bar]
+[PsyncMessageCompress::foo]
+[PsyncParentToChild::Msg]
+[PtooWeakIntrSync::Msg]
+[PtooWeakSyncAsync::Msg]
+[PundeclReturnType::Msg]
+[PasyncMessageListed::Msg]
--- a/js/public/Value.h
+++ b/js/public/Value.h
@@ -59,20 +59,18 @@ enum JSValueType : uint8_t {
   JSVAL_TYPE_NULL = 0x04,
   JSVAL_TYPE_MAGIC = 0x05,
   JSVAL_TYPE_STRING = 0x06,
   JSVAL_TYPE_SYMBOL = 0x07,
   JSVAL_TYPE_PRIVATE_GCTHING = 0x08,
   JSVAL_TYPE_BIGINT = 0x09,
   JSVAL_TYPE_OBJECT = 0x0c,
 
-  // These never appear in a jsval; they are only provided as an out-of-band
-  // value.
-  JSVAL_TYPE_UNKNOWN = 0x20,
-  JSVAL_TYPE_MISSING = 0x21
+  // This type never appears in a Value; it's only an out-of-band value.
+  JSVAL_TYPE_UNKNOWN = 0x20
 };
 
 namespace JS {
 enum class ValueType : uint8_t {
   Double = JSVAL_TYPE_DOUBLE,
   Int32 = JSVAL_TYPE_INT32,
   Boolean = JSVAL_TYPE_BOOLEAN,
   Undefined = JSVAL_TYPE_UNDEFINED,
--- a/js/src/frontend/Parser.cpp
+++ b/js/src/frontend/Parser.cpp
@@ -6182,37 +6182,25 @@ GeneralParser<ParseHandler, Unit>::break
   MOZ_ASSERT(anyChars.isCurrentTokenType(TokenKind::Break));
   uint32_t begin = pos().begin;
 
   RootedPropertyName label(cx_);
   if (!matchLabel(yieldHandling, &label)) {
     return null();
   }
 
-  // Labeled 'break' statements target the nearest labeled statements (could
-  // be any kind) with the same label. Unlabeled 'break' statements target
-  // the innermost loop or switch statement.
-  if (label) {
-    auto hasSameLabel = [&label](ParseContext::LabelStatement* stmt) {
-      return stmt->label() == label;
-    };
-
-    if (!pc_->template findInnermostStatement<ParseContext::LabelStatement>(
-            hasSameLabel)) {
-      error(JSMSG_LABEL_NOT_FOUND);
-      return null();
-    }
-  } else {
-    auto isBreakTarget = [](ParseContext::Statement* stmt) {
-      return StatementKindIsUnlabeledBreakTarget(stmt->kind());
-    };
-
-    if (!pc_->findInnermostStatement(isBreakTarget)) {
-      errorAt(begin, JSMSG_TOUGH_BREAK);
-      return null();
+  auto validity = pc_->checkBreakStatement(label);
+  if (validity.isErr()) {
+    switch (validity.unwrapErr()) {
+      case ParseContext::BreakStatementError::ToughBreak:
+        errorAt(begin, JSMSG_TOUGH_BREAK);
+        return null();
+      case ParseContext::BreakStatementError::LabelNotFound:
+        error(JSMSG_LABEL_NOT_FOUND);
+        return null();
     }
   }
 
   if (!matchOrInsertSemicolon()) {
     return null();
   }
 
   return handler_.newBreakStatement(label, TokenPos(begin, pos().end));
--- a/js/src/frontend/Parser.h
+++ b/js/src/frontend/Parser.h
@@ -264,18 +264,21 @@ class MOZ_STACK_CLASS ParserSharedBase :
 
   // Root atoms and objects allocated for the parsed tree.
   AutoKeepAtoms keepAtoms_;
 
  private:
   // This is needed to cast a parser to JS::AutoGCRooter.
   friend void js::frontend::TraceParser(JSTracer* trc,
                                         JS::AutoGCRooter* parser);
+
+#if defined(JS_BUILD_BINAST)
   friend void js::frontend::TraceBinParser(JSTracer* trc,
                                            JS::AutoGCRooter* parser);
+#endif  // JS_BUILD_BINAST
 
  private:
   // Create a new traceable node and store it into the trace list.
   template <typename BoxT, typename ArgT>
   BoxT* newTraceListNode(ArgT* arg);
 
  public:
   // Create a new JSObject and store it into the trace list.
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..46f28b933007d2f697f1fa862632d0c0b19204cd
GIT binary patch
literal 209
zc$`I!y$ZrW5QM`aK_rhM!BWJ|#t7j!F)8lS1&cG;goXUESwUZ3JY#Xw?aar{TvUEF
zqLezxvP9pphJlgar%!Z9<{5~gHWlH-vKt?^Gu1f3&L!9my+hO2MBuJ*IC`_N)B>yJ
zRf9mWrwm($AG5z91KBQr_CQ#9BKp^rrqC*v#xDwmuw|js)LZc;a1x<d1?ynZ_WT7M
C$Vc%2
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..0a42bbe83fbcc1616e78c74537e7ca8a01e0edeb
GIT binary patch
literal 197
zc${<c^z#a4igpij^!0TNip@+(%`3?)skDB^W8_#|oLW?pni8B`lvz;Xo|B)Hm=m0w
zUy!N+l*vrb%LOWRttco;1@iLqOb~)0iACwDC7xiT(lS$v416+6Qi~FE{7Q3Ei!zfD
zdUzm4^SxcLFaGVexzWKPL7sl@!3bBdF)<}ZhXlF0B81d97=VC@i;0DSjR6ck*aHB%
C`$dre
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/binast/invalid/wtf-8-interface-name.dir
@@ -0,0 +1,1 @@
+// |jit-test| error:SyntaxError
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..141cce1ca9ca26983413081d98b729f44fb3c41a
GIT binary patch
literal 238
zc${61Jqp4=5QW1Mf=IBjw~!!~Vryf>5F(l)8*GBen2a*8`C+n(9!BsKmfpxaC=n6-
z%J+CbvmjhZk@%6jTDj4NGAuOd%cLthL$|JxHD+^66)<KY<T(C{GG(f?ugV=LnU)py
zXH;ZV9D=4|PspPsX=G60F-NA<J6DW#O=V$!!h<z1!A{|40QB2({<V@58An0r%ip=4
kWu1Tpbe^}z_IbZ1apZYFd)yMjFpW2&Z3x>GmeJr$Ul{CAF#rGn
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/binast/invalid/wtf-8-scope-name.dir
@@ -0,0 +1,1 @@
+// |jit-test| error:SyntaxError
new file mode 100644
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..ba221702d16b1d0f2ae670fe4e55774f99d78068
GIT binary patch
literal 215
zc${<c^z#a4igpij^!0TNip@+(%`3?)skHvbW8_#|oLW?pni8B`lvz;Xo|B)Hm=m0w
zUy!N+l*vrb%LOWRttco;1@iLqOb~)0iACwDC7xiT(lS$v)DWtIOA<>`L23+qGD}j6
z5_9}Yb5n~llMyO-Al5|(hXi^0xd$U$B*et`cEP^*x7+4MhXlF0A|%wf7=VC@jfsVU
Jg8>Xw8~|LiOp*Wq
new file mode 100644
--- /dev/null
+++ b/js/src/jit-test/tests/binast/invalid/wtf-8-variable-name.dir
@@ -0,0 +1,1 @@
+// |jit-test| error:SyntaxError
--- a/js/src/jsapi-tests/binast/invalid/lib/filter_utils.py
+++ b/js/src/jsapi-tests/binast/invalid/lib/filter_utils.py
@@ -76,16 +76,31 @@ def assert_interface(obj, expected_name)
            The name of the interface
     """
     assert_tagged_tuple(obj)
     actual_name = obj['@INTERFACE']
     if actual_name != expected_name:
         raise Exception('expected {}, got {}'.format(expected_name, actual_name))
 
 
+def set_interface_name(obj, name):
+    """
+    Set the tagged tuple's interface name
+
+    :param obj (dict)
+           The tagged tuple
+    :param name (string)
+           The name of the interface
+    """
+    assert_tagged_tuple(obj)
+    obj['@INTERFACE'] = name
+    if type(name) is not str and type(name) is not unicode:
+        raise Exception('passed value is not string: {}'.format(name))
+
+
 def get_field(obj, name):
     """
     Returns the field of the tagged tuple.
 
     :param obj (dict)
            The tagged tuple
     :param name (string)
            The name of the field to get
@@ -141,16 +156,39 @@ def remove_field(obj, name):
     for field in fields:
         if field['@FIELD_NAME'] == name:
             del fields[i]
             return
         i += 1
     raise Exception('No such field: {}'.format(name))
 
 
+def append_field(obj, name, value):
+    """
+    Append a field to the tagged tuple
+
+    :param obj (dict)
+           the tagged tuple
+    :param name (string)
+           the name of the field to add
+    :param value (dict)
+           the value of the field to add
+    """
+    assert_tagged_tuple(obj)
+    fields = obj['@FIELDS']
+    if type(name) is not str and type(name) is not unicode:
+        raise Exception('passed name is not string: {}'.format(name))
+    if type(value) is not dict:
+        raise Exception('passed value is not dict: {}'.format(value))
+    fields.append({
+        '@FIELD_NAME': name,
+        '@FIELD_VALUE': value,
+    })
+
+
 def get_element(obj, i):
     """
     Returns the element of the list.
 
     :param obj (dict)
            The list
     :param i (int)
            The indef of the element to get
@@ -251,26 +289,26 @@ def set_string(obj, value):
     Set string value
 
     :param obj (dict)
            the string object
     :param value (int)
            the value to set
     """
     assert_string(obj)
-    if type(value) is not str:
+    if type(value) is not str and type(value) is not unicode:
         raise Exception('passed value is not string: {}'.format(value))
     obj['@VALUE'] = value
 
 
 def set_identifier_name(obj, value):
     """
     Set identifier name value
 
     :param obj (dict)
            the identifier name object
     :param value (int)
            the value to set
     """
     assert_identifier_name(obj)
-    if type(value) is not str:
+    if type(value) is not str and type(value) is not unicode:
         raise Exception('passed value is not string: {}'.format(value))
     obj['@VALUE'] = value
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-field-name.js
@@ -0,0 +1,1 @@
+a = 10;
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-field-name.py
@@ -0,0 +1,18 @@
+def filter_ast(ast):
+    # Put WTF-8 string into field name.
+    # In multipart format, field name is not encoded into the file,
+    # so this has no effect.
+    import filter_utils as utils
+
+    utils.assert_interface(ast, 'Script')
+    global_stmts = utils.get_field(ast, 'statements')
+
+    expr_stmt = utils.get_element(global_stmts, 0)
+    utils.assert_interface(expr_stmt, 'ExpressionStatement')
+
+    field = utils.get_field(expr_stmt, 'expression')
+
+    utils.append_field(expr_stmt, u'\uD83E_\uDD9D', field)
+    utils.remove_field(expr_stmt, 'expression')
+
+    return ast
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-interface-name.js
@@ -0,0 +1,1 @@
+a = 1;
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-interface-name.py
@@ -0,0 +1,13 @@
+def filter_ast(ast):
+    # Put WTF-8 string into interface name.
+    import filter_utils as utils
+
+    utils.assert_interface(ast, 'Script')
+    global_stmts = utils.get_field(ast, 'statements')
+
+    expr_stmt = utils.get_element(global_stmts, 0)
+    utils.assert_interface(expr_stmt, 'ExpressionStatement')
+
+    utils.set_interface_name(expr_stmt, u'\uD83E_\uDD9D')
+
+    return ast
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-scope-name.js
@@ -0,0 +1,1 @@
+var a = 10;
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-scope-name.py
@@ -0,0 +1,18 @@
+def filter_ast(ast):
+    # Put WTF-8 string into scope name.
+    import filter_utils as utils
+
+    utils.assert_interface(ast, 'Script')
+
+    scope = utils.get_field(ast, 'scope')
+    utils.assert_interface(scope, 'AssertedScriptGlobalScope')
+
+    names = utils.get_field(scope, 'declaredNames')
+
+    decl_name = utils.get_element(names, 0)
+    utils.assert_interface(decl_name, 'AssertedDeclaredName')
+
+    name = utils.get_field(decl_name, 'name')
+    utils.set_identifier_name(name, u'\uD83E_\uDD9D')
+
+    return ast
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-variable-name.js
@@ -0,0 +1,1 @@
+a = 10;
new file mode 100644
--- /dev/null
+++ b/js/src/jsapi-tests/binast/invalid/tests/wtf-8-variable-name.py
@@ -0,0 +1,20 @@
+def filter_ast(ast):
+    # Put WTF-8 string into identifier name.
+    import filter_utils as utils
+
+    utils.assert_interface(ast, 'Script')
+    global_stmts = utils.get_field(ast, 'statements')
+
+    expr_stmt = utils.get_element(global_stmts, 0)
+    utils.assert_interface(expr_stmt, 'ExpressionStatement')
+
+    assign_expr = utils.get_field(expr_stmt, 'expression')
+    utils.assert_interface(assign_expr, 'AssignmentExpression')
+
+    binding = utils.get_field(assign_expr, 'binding')
+    utils.assert_interface(binding, 'AssignmentTargetIdentifier')
+
+    name = utils.get_field(binding, 'name')
+    utils.set_identifier_name(name, u'\uD83E_\uDD9D')
+
+    return ast
--- a/js/src/jsexn.cpp
+++ b/js/src/jsexn.cpp
@@ -954,17 +954,17 @@ bool ErrorReport::populateUncaughtExcept
   // XXXbz this assumes the stack we have right now is still
   // related to our exception object.  It would be better if we
   // could accept a passed-in stack of some sort instead.
   NonBuiltinFrameIter iter(cx, cx->realm()->principals());
   if (!iter.done()) {
     ownedReport.filename = iter.filename();
     uint32_t column;
     ownedReport.sourceId =
-      iter.script() ? iter.script()->scriptSource()->id() : 0;
+      iter.hasScript() ? iter.script()->scriptSource()->id() : 0;
     ownedReport.lineno = iter.computeLine(&column);
     ownedReport.column = FixupColumnForDisplay(column);
     ownedReport.isMuted = iter.mutedErrors();
   }
 
   if (!ExpandErrorArgumentsVA(cx, GetErrorMessage, nullptr,
                               JSMSG_UNCAUGHT_EXCEPTION, nullptr,
                               ArgumentsAreUTF8, &ownedReport, ap)) {
--- a/js/src/vm/JSFunction-inl.h
+++ b/js/src/vm/JSFunction-inl.h
@@ -39,16 +39,19 @@ inline bool CanReuseFunctionForClone(JSC
     }
     lazy->setHasBeenCloned();
   } else {
     JSScript* script = fun->nonLazyScript();
     if (script->hasBeenCloned()) {
       return false;
     }
     script->setHasBeenCloned();
+    if (LazyScript* lazy = script->maybeLazyScript()) {
+      lazy->setHasBeenCloned();
+    }
   }
   return true;
 }
 
 inline JSFunction* CloneFunctionObjectIfNotSingleton(
     JSContext* cx, HandleFunction fun, HandleObject parent,
     HandleObject proto = nullptr, NewObjectKind newKind = GenericObject) {
   /*
--- a/js/src/vm/JSObject.cpp
+++ b/js/src/vm/JSObject.cpp
@@ -3464,77 +3464,91 @@ void GetObjectSlotNameFunctor::operator(
 
 /*
  * Routines to print out values during debugging.  These are FRIEND_API to help
  * the debugger find them and to support temporarily hacking js::Dump* calls
  * into other code.
  */
 
 static void dumpValue(const Value& v, js::GenericPrinter& out) {
-  if (v.isNull()) {
-    out.put("null");
-  } else if (v.isUndefined()) {
-    out.put("undefined");
-  } else if (v.isInt32()) {
-    out.printf("%d", v.toInt32());
-  } else if (v.isDouble()) {
-    out.printf("%g", v.toDouble());
-  } else if (v.isString()) {
-    v.toString()->dumpNoNewline(out);
-  } else if (v.isSymbol()) {
-    v.toSymbol()->dump(out);
-  } else if (v.isBigInt()) {
-    v.toBigInt()->dump(out);
-  } else if (v.isObject() && v.toObject().is<JSFunction>()) {
-    JSFunction* fun = &v.toObject().as<JSFunction>();
-    if (fun->displayAtom()) {
-      out.put("<function ");
-      EscapedStringPrinter(out, fun->displayAtom(), 0);
-    } else {
-      out.put("<unnamed function");
-    }
-    if (fun->hasScript()) {
-      JSScript* script = fun->nonLazyScript();
-      out.printf(" (%s:%u)", script->filename() ? script->filename() : "",
-                 script->lineno());
-    }
-    out.printf(" at %p>", (void*)fun);
-  } else if (v.isObject()) {
-    JSObject* obj = &v.toObject();
-    const Class* clasp = obj->getClass();
-    out.printf("<%s%s at %p>", clasp->name,
-               (clasp == &PlainObject::class_) ? "" : " object", (void*)obj);
-  } else if (v.isBoolean()) {
-    if (v.toBoolean()) {
-      out.put("true");
-    } else {
-      out.put("false");
-    }
-  } else if (v.isMagic()) {
-    out.put("<invalid");
-    switch (v.whyMagic()) {
-      case JS_ELEMENTS_HOLE:
-        out.put(" elements hole");
-        break;
-      case JS_NO_ITER_VALUE:
-        out.put(" no iter value");
-        break;
-      case JS_GENERATOR_CLOSING:
-        out.put(" generator closing");
-        break;
-      case JS_OPTIMIZED_OUT:
-        out.put(" optimized out");
-        break;
-      default:
-        out.put(" ?!");
-        break;
-    }
-    out.putChar('>');
-  } else {
-    out.put("unexpected value");
+  switch (v.type()) {
+    case ValueType::Null:
+      out.put("null");
+      break;
+    case ValueType::Undefined:
+      out.put("undefined");
+      break;
+    case ValueType::Int32:
+      out.printf("%d", v.toInt32());
+      break;
+    case ValueType::Double:
+      out.printf("%g", v.toDouble());
+      break;
+    case ValueType::String:
+      v.toString()->dumpNoNewline(out);
+      break;
+    case ValueType::Symbol:
+      v.toSymbol()->dump(out);
+      break;
+    case ValueType::BigInt:
+      v.toBigInt()->dump(out);
+      break;
+    case ValueType::Object:
+      if (v.toObject().is<JSFunction>()) {
+        JSFunction* fun = &v.toObject().as<JSFunction>();
+        if (fun->displayAtom()) {
+          out.put("<function ");
+          EscapedStringPrinter(out, fun->displayAtom(), 0);
+        } else {
+          out.put("<unnamed function");
+        }
+        if (fun->hasScript()) {
+          JSScript* script = fun->nonLazyScript();
+          out.printf(" (%s:%u)", script->filename() ? script->filename() : "",
+                     script->lineno());
+        }
+        out.printf(" at %p>", (void*)fun);
+      } else {
+        JSObject* obj = &v.toObject();
+        const Class* clasp = obj->getClass();
+        out.printf("<%s%s at %p>", clasp->name,
+                   (clasp == &PlainObject::class_) ? "" : " object", (void*)obj);
+      }
+      break;
+    case ValueType::Boolean:
+      if (v.toBoolean()) {
+        out.put("true");
+      } else {
+        out.put("false");
+      }
+      break;
+    case ValueType::Magic:
+      out.put("<magic");
+      switch (v.whyMagic()) {
+        case JS_ELEMENTS_HOLE:
+          out.put(" elements hole");
+          break;
+        case JS_NO_ITER_VALUE:
+          out.put(" no iter value");
+          break;
+        case JS_GENERATOR_CLOSING:
+          out.put(" generator closing");
+          break;
+        case JS_OPTIMIZED_OUT:
+          out.put(" optimized out");
+          break;
+        default:
+          out.put(" ?!");
+          break;
+      }
+      out.putChar('>');
+      break;
+    case ValueType::PrivateGCThing:
+      out.printf("<PrivateGCThing %p>", v.toGCThing());
+      break;
   }
 }
 
 namespace js {
 
 // We don't want jsfriendapi.h to depend on GenericPrinter,
 // so these functions are declared directly in the cpp.
 
--- a/js/src/vm/JSScript.cpp
+++ b/js/src/vm/JSScript.cpp
@@ -277,17 +277,17 @@ static XDRResult XDRRelazificationInfo(X
     uint32_t sourceEnd = script->sourceEnd();
     uint32_t toStringStart = script->toStringStart();
     uint32_t toStringEnd = script->toStringEnd();
     uint32_t lineno = script->lineno();
     uint32_t column = script->column();
     uint32_t numFieldInitializers;
 
     if (mode == XDR_ENCODE) {
-      packedFields = lazy->packedFields();
+      packedFields = lazy->packedFieldsForXDR();
       MOZ_ASSERT(sourceStart == lazy->sourceStart());
       MOZ_ASSERT(sourceEnd == lazy->sourceEnd());
       MOZ_ASSERT(toStringStart == lazy->toStringStart());
       MOZ_ASSERT(toStringEnd == lazy->toStringEnd());
       MOZ_ASSERT(lineno == lazy->lineno());
       MOZ_ASSERT(column == lazy->column());
       // We can assert we have no inner functions because we don't
       // relazify scripts with inner functions.  See
@@ -313,21 +313,16 @@ static XDRResult XDRRelazificationInfo(X
         return xdr->fail(JS::TranscodeResult_Throw);
       }
 
       lazy->setToStringEnd(toStringEnd);
       if (numFieldInitializers != UINT32_MAX) {
         lazy->setFieldInitializers(
             FieldInitializers((size_t)numFieldInitializers));
       }
-
-      // As opposed to XDRLazyScript, we need to restore the runtime bits
-      // of the script, as we are trying to match the fact this function
-      // has already been parsed and that it would need to be re-lazified.
-      lazy->initRuntimeFields(packedFields);
     }
   }
 
   // Code binding names.
   MOZ_TRY(XDRLazyClosedOverBindings(xdr, lazy));
 
   // No need to do anything with inner functions, since we asserted we don't
   // have any.
@@ -1005,17 +1000,17 @@ XDRResult js::XDRLazyScript(XDRState<mod
       MOZ_ASSERT(fun == lazy->functionNonDelazifying());
 
       sourceStart = lazy->sourceStart();
       sourceEnd = lazy->sourceEnd();
       toStringStart = lazy->toStringStart();
       toStringEnd = lazy->toStringEnd();
       lineno = lazy->lineno();
       column = lazy->column();
-      packedFields = lazy->packedFields();
+      packedFields = lazy->packedFieldsForXDR();
       if (fun->kind() == JSFunction::FunctionKind::ClassConstructor) {
         numFieldInitializers =
             (uint32_t)lazy->getFieldInitializers().numFieldInitializers;
       } else {
         numFieldInitializers = UINT32_MAX;
       }
     }
 
@@ -4820,33 +4815,46 @@ ScriptSourceObject& LazyScript::sourceOb
 
 ScriptSource* LazyScript::maybeForwardedScriptSource() const {
   JSObject* source = MaybeForwarded(&sourceObject());
   return UncheckedUnwrapWithoutExpose(source)
       ->as<ScriptSourceObject>()
       .source();
 }
 
+uint64_t LazyScript::packedFieldsForXDR() const {
+  union {
+    PackedView p;
+    uint64_t packedFields;
+  };
+
+  packedFields = packedFields_;
+
+  // Reset runtime flags
+  p.hasBeenCloned = false;
+
+  return packedFields;
+}
+
 /* static */ LazyScript* LazyScript::CreateRaw(
     JSContext* cx, HandleFunction fun, HandleScriptSourceObject sourceObject,
     uint64_t packedFields, uint32_t sourceStart, uint32_t sourceEnd,
     uint32_t toStringStart, uint32_t lineno, uint32_t column) {
   cx->check(fun);
 
   MOZ_ASSERT(sourceObject);
   union {
     PackedView p;
     uint64_t packed;
   };
 
   packed = packedFields;
 
   // Reset runtime flags to obtain a fresh LazyScript.
   p.hasBeenCloned = false;
-  p.treatAsRunOnce = false;
 
   size_t bytes = (p.numClosedOverBindings * sizeof(JSAtom*)) +
                  (p.numInnerFunctions * sizeof(GCPtrFunction));
 
   UniquePtr<uint8_t, JS::FreePolicy> table;
   if (bytes) {
     table.reset(cx->pod_malloc<uint8_t>(bytes));
     if (!table) {
@@ -4884,16 +4892,17 @@ ScriptSource* LazyScript::maybeForwarded
   p.numClosedOverBindings = closedOverBindings.length();
   p.numInnerFunctions = innerFunctions.length();
   p.isGenerator = false;
   p.strict = false;
   p.bindingsAccessedDynamically = false;
   p.hasDebuggerStatement = false;
   p.hasDirectEval = false;
   p.isLikelyConstructorWrapper = false;
+  p.treatAsRunOnce = false;
   p.isDerivedClassConstructor = false;
   p.needsHomeObject = false;
   p.isBinAST = false;
   p.parseGoal = uint32_t(parseGoal);
 
   LazyScript* res =
       LazyScript::CreateRaw(cx, fun, sourceObject, packedFields, sourceStart,
                             sourceEnd, toStringStart, lineno, column);
@@ -4962,27 +4971,16 @@ ScriptSource* LazyScript::maybeForwarded
   MOZ_ASSERT(!res->hasScript());
   if (script) {
     res->initScript(script);
   }
 
   return res;
 }
 
-void LazyScript::initRuntimeFields(uint64_t packedFields) {
-  union {
-    PackedView p;
-    uint64_t packed;
-  };
-
-  packed = packedFields;
-  p_.hasBeenCloned = p.hasBeenCloned;
-  p_.treatAsRunOnce = p.treatAsRunOnce;
-}
-
 void JSScript::updateJitCodeRaw(JSRuntime* rt) {
   MOZ_ASSERT(rt);
   if (hasBaselineScript() && baseline->hasPendingIonBuilder()) {
     MOZ_ASSERT(!isIonCompilingOffThread());
     jitCodeRaw_ = rt->jitRuntime()->lazyLinkStub().value;
     jitCodeSkipArgCheck_ = jitCodeRaw_;
   } else if (hasIonScript()) {
     jitCodeRaw_ = ion->method()->raw();
--- a/js/src/vm/JSScript.h
+++ b/js/src/vm/JSScript.h
@@ -2968,22 +2968,24 @@ class LazyScript : public gc::TenuredCel
     // MSVC. If you add another boolean here, make sure to initialize it in
     // LazyScript::Create().
     uint32_t isGenerator : 1;
     uint32_t strict : 1;
     uint32_t bindingsAccessedDynamically : 1;
     uint32_t hasDebuggerStatement : 1;
     uint32_t hasDirectEval : 1;
     uint32_t isLikelyConstructorWrapper : 1;
-    uint32_t hasBeenCloned : 1;
     uint32_t treatAsRunOnce : 1;
     uint32_t isDerivedClassConstructor : 1;
     uint32_t needsHomeObject : 1;
     uint32_t hasRest : 1;
     uint32_t parseGoal : 1;
+
+    // Runtime flags
+    uint32_t hasBeenCloned : 1;
   };
 
   union {
     PackedView p_;
     uint64_t packedFields_;
   };
 
   FieldInitializers fieldInitializers_;
@@ -3039,18 +3041,16 @@ class LazyScript : public gc::TenuredCel
   static LazyScript* CreateForXDR(JSContext* cx, HandleFunction fun,
                                   HandleScript script,
                                   HandleScope enclosingScope,
                                   HandleScriptSourceObject sourceObject,
                                   uint64_t packedData, uint32_t begin,
                                   uint32_t end, uint32_t toStringStart,
                                   uint32_t lineno, uint32_t column);
 
-  void initRuntimeFields(uint64_t packedFields);
-
   static inline JSFunction* functionDelazifying(JSContext* cx,
                                                 Handle<LazyScript*>);
   JSFunction* functionNonDelazifying() const { return function_; }
 
   JS::Compartment* compartment() const;
   JS::Compartment* maybeCompartment() const { return compartment(); }
   Realm* realm() const;
 
@@ -3213,17 +3213,17 @@ class LazyScript : public gc::TenuredCel
   void finalize(js::FreeOp* fop);
 
   static const JS::TraceKind TraceKind = JS::TraceKind::LazyScript;
 
   size_t sizeOfExcludingThis(mozilla::MallocSizeOf mallocSizeOf) {
     return mallocSizeOf(table_);
   }
 
-  uint64_t packedFields() const { return packedFields_; }
+  uint64_t packedFieldsForXDR() const;
 };
 
 /* If this fails, add/remove padding within LazyScript. */
 static_assert(sizeof(LazyScript) % js::gc::CellAlignBytes == 0,
               "Size of LazyScript must be an integral multiple of "
               "js::gc::CellAlignBytes");
 
 struct ScriptAndCounts {
--- a/layout/base/ShapeUtils.cpp
+++ b/layout/base/ShapeUtils.cpp
@@ -135,17 +135,17 @@ nsSize ShapeUtils::ComputeEllipseRadii(c
   }
 
   return nsRect(x, y, width, height);
 }
 
 /* static */ bool ShapeUtils::ComputeInsetRadii(
     const StyleBasicShape& aBasicShape, const nsRect& aInsetRect,
     const nsRect& aRefBox, nscoord aRadii[8]) {
-  const nsStyleCorners& radius = aBasicShape.GetRadius();
+  const auto& radius = aBasicShape.GetRadius();
   return nsIFrame::ComputeBorderRadii(radius, aInsetRect.Size(), aRefBox.Size(),
                                       Sides(), aRadii);
 }
 
 /* static */ nsTArray<nsPoint> ShapeUtils::ComputePolygonVertices(
     const StyleBasicShape& aBasicShape, const nsRect& aRefBox) {
   MOZ_ASSERT(aBasicShape.GetShapeType() == StyleBasicShapeType::Polygon,
              "The basic shape must be polygon()!");
--- a/layout/base/nsLayoutUtils.cpp
+++ b/layout/base/nsLayoutUtils.cpp
@@ -6857,30 +6857,25 @@ static ImgDrawResult DrawImageInternal(
 
   if (aOrientation == StyleImageOrientation::FromImage) {
     img = ImageOps::Orient(img, img->GetOrientation());
   }
 
   return img.forget();
 }
 
-static bool NonZeroStyleCoord(const nsStyleCoord& aCoord) {
-  if (aCoord.IsCoordPercentCalcUnit()) {
-    // Since negative results are clamped to 0, check > 0.
-    return aCoord.ComputeCoordPercentCalc(nscoord_MAX) > 0 ||
-           aCoord.ComputeCoordPercentCalc(0) > 0;
-  }
-
-  return true;
+static bool NonZeroCorner(const LengthPercentage& aLength) {
+  // Since negative results are clamped to 0, check > 0.
+  return aLength.Resolve(nscoord_MAX) > 0 || aLength.Resolve(0) > 0;
 }
 
 /* static */ bool nsLayoutUtils::HasNonZeroCorner(
-    const nsStyleCorners& aCorners) {
+    const BorderRadius& aCorners) {
   NS_FOR_CSS_HALF_CORNERS(corner) {
-    if (NonZeroStyleCoord(aCorners.Get(corner))) return true;
+    if (NonZeroCorner(aCorners.Get(corner))) return true;
   }
   return false;
 }
 
 // aCorner is a "full corner" value, i.e. eCornerTopLeft etc.
 static bool IsCornerAdjacentToSide(uint8_t aCorner, Side aSide) {
   static_assert((int)eSideTop == eCornerTopLeft, "Check for Full Corner");
   static_assert((int)eSideRight == eCornerTopRight, "Check for Full Corner");
@@ -6895,17 +6890,17 @@ static bool IsCornerAdjacentToSide(uint8
                 "Check for Full Corner");
   static_assert((int)eSideLeft == ((eCornerTopLeft - 1) & 3),
                 "Check for Full Corner");
 
   return aSide == aCorner || aSide == ((aCorner - 1) & 3);
 }
 
 /* static */ bool nsLayoutUtils::HasNonZeroCornerOnSide(
-    const nsStyleCorners& aCorners, Side aSide) {
+    const BorderRadius& aCorners, Side aSide) {
   static_assert(eCornerTopLeftX / 2 == eCornerTopLeft,
                 "Check for Non Zero on side");
   static_assert(eCornerTopLeftY / 2 == eCornerTopLeft,
                 "Check for Non Zero on side");
   static_assert(eCornerTopRightX / 2 == eCornerTopRight,
                 "Check for Non Zero on side");
   static_assert(eCornerTopRightY / 2 == eCornerTopRight,
                 "Check for Non Zero on side");
@@ -6916,17 +6911,17 @@ static bool IsCornerAdjacentToSide(uint8
   static_assert(eCornerBottomLeftX / 2 == eCornerBottomLeft,
                 "Check for Non Zero on side");
   static_assert(eCornerBottomLeftY / 2 == eCornerBottomLeft,
                 "Check for Non Zero on side");
 
   NS_FOR_CSS_HALF_CORNERS(corner) {
     // corner is a "half corner" value, so dividing by two gives us a
     // "full corner" value.
-    if (NonZeroStyleCoord(aCorners.Get(corner)) &&
+    if (NonZeroCorner(aCorners.Get(corner)) &&
         IsCornerAdjacentToSide(corner / 2, aSide))
       return true;
   }
   return false;
 }
 
 /* static */ nsTransparencyMode nsLayoutUtils::GetFrameTransparency(
     nsIFrame* aBackgroundFrame, nsIFrame* aCSSRootFrame) {
--- a/layout/base/nsLayoutUtils.h
+++ b/layout/base/nsLayoutUtils.h
@@ -50,17 +50,16 @@ class nsDisplayItem;
 class nsFontMetrics;
 class nsFontFaceList;
 class nsIImageLoadingContent;
 class nsBlockFrame;
 class nsContainerFrame;
 class nsView;
 class nsIFrame;
 class nsStyleCoord;
-class nsStyleCorners;
 class nsPIDOMWindowOuter;
 class imgIRequest;
 struct nsStyleFont;
 struct nsOverflowAreas;
 
 namespace mozilla {
 class ComputedStyle;
 enum class PseudoStyleType : uint8_t;
@@ -1932,32 +1931,32 @@ class nsLayoutUtils {
    * @param aOrientation The desired orientation.
    */
   static already_AddRefed<imgIContainer> OrientImage(
       imgIContainer* aContainer,
       const mozilla::StyleImageOrientation& aOrientation);
 
   /**
    * Determine if any corner radius is of nonzero size
-   *   @param aCorners the |nsStyleCorners| object to check
+   *   @param aCorners the |BorderRadius| object to check
    *   @return true unless all the coordinates are 0%, 0 or null.
    *
    * A corner radius with one dimension zero and one nonzero is
    * treated as a nonzero-radius corner, even though it will end up
    * being rendered like a zero-radius corner.  This is because such
    * corners are not expected to appear outside of test cases, and it's
    * simpler to implement the test this way.
    */
-  static bool HasNonZeroCorner(const nsStyleCorners& aCorners);
+  static bool HasNonZeroCorner(const mozilla::BorderRadius& aCorners);
 
   /**
    * Determine if there is any corner radius on corners adjacent to the
    * given side.
    */
-  static bool HasNonZeroCornerOnSide(const nsStyleCorners& aCorners,
+  static bool HasNonZeroCornerOnSide(const mozilla::BorderRadius& aCorners,
                                      mozilla::Side aSide);
 
   /**
    * Determine if a widget is likely to require transparency or translucency.
    *   @param aBackgroundFrame The frame that the background is set on. For
    *                           <window>s, this will be the canvas frame.
    *   @param aCSSRootFrame    The frame that holds CSS properties affecting
    *                           the widget's transparency. For menupopups,
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -1639,35 +1639,25 @@ nsRect nsIFrame::GetContentRectRelativeT
   r.Deflate(bp);
   return r;
 }
 
 nsRect nsIFrame::GetContentRect() const {
   return GetContentRectRelativeToSelf() + GetPosition();
 }
 
-bool nsIFrame::ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
+bool nsIFrame::ComputeBorderRadii(const BorderRadius& aBorderRadius,
                                   const nsSize& aFrameSize,
                                   const nsSize& aBorderArea, Sides aSkipSides,
                                   nscoord aRadii[8]) {
   // Percentages are relative to whichever side they're on.
   NS_FOR_CSS_HALF_CORNERS(i) {
-    const nsStyleCoord c = aBorderRadius.Get(i);
+    const LengthPercentage& c = aBorderRadius.Get(i);
     nscoord axis = HalfCornerIsX(i) ? aFrameSize.width : aFrameSize.height;
-
-    if (c.IsCoordPercentCalcUnit()) {
-      aRadii[i] = c.ComputeCoordPercentCalc(axis);
-      if (aRadii[i] < 0) {
-        // clamp calc()
-        aRadii[i] = 0;
-      }
-    } else {
-      MOZ_ASSERT_UNREACHABLE("ComputeBorderRadii: bad unit");
-      aRadii[i] = 0;
-    }
+    aRadii[i] = std::max(0, c.Resolve(axis));
   }
 
   if (aSkipSides.Top()) {
     aRadii[eCornerTopLeftX] = 0;
     aRadii[eCornerTopLeftY] = 0;
     aRadii[eCornerTopRightX] = 0;
     aRadii[eCornerTopRightY] = 0;
   }
--- a/layout/generic/nsIFrame.h
+++ b/layout/generic/nsIFrame.h
@@ -1358,17 +1358,17 @@ class nsIFrame : public nsQueryFrame {
    * aBorderArea is used for the adjustment of radii that might be too
    * large.
    * FIXME: In the long run, we can probably get away with only one of
    * these, especially if we change the way we handle outline-radius (by
    * removing it and inflating the border radius)
    *
    * Return whether any radii are nonzero.
    */
-  static bool ComputeBorderRadii(const nsStyleCorners& aBorderRadius,
+  static bool ComputeBorderRadii(const mozilla::BorderRadius&,
                                  const nsSize& aFrameSize,
                                  const nsSize& aBorderArea, Sides aSkipSides,
                                  nscoord aRadii[8]);
 
   /*
    * Given a set of border radii for one box (e.g., border box), convert
    * it to the equivalent set of radii for another box (e.g., in to
    * padding box, out to outline box) by reducing radii or increasing
--- a/layout/reftests/xul/accesskey.xul
+++ b/layout/reftests/xul/accesskey.xul
@@ -20,24 +20,24 @@ function changeKeys()
 
   document.documentElement.className='';
 }
 
 ]]>
 </script>
 
 <hbox align="start">
-  <label control="b1">Label1</label><textbox id="b1" accesskey="L" size="2"/>
-  <label control="b2">Label2</label><textbox id="b2" accesskey="l" size="2"/>
-  <label control="b3">Label3</label><textbox id="b3" accesskey="b" size="2"/>
-  <label control="b4">Label4</label><textbox id="b4" accesskey="x" size="2"/>
-  <label control="b5" maxwidth="50">Quite a long label. Hopefully it will wrap</label><textbox id="b5" accesskey="l" size="2"/>
+  <label control="b1" accesskey="L">Label1</label><textbox id="b1" size="2"/>
+  <label control="b2" accesskey="l">Label2</label><textbox id="b2" size="2"/>
+  <label control="b3" accesskey="b">Label3</label><textbox id="b3" size="2"/>
+  <label control="b4" accesskey="x">Label4</label><textbox id="b4" size="2"/>
+  <label control="b5" accesskey="l" maxwidth="50">Quite a long label. Hopefully it will wrap</label><textbox id="b5" size="2"/>
 </hbox>
 
 <hbox id="d" align="start">
-  <label control="d1">Label1</label><textbox id="d1" accesskey="z" size="2"/>
+  <label control="d1" accesskey="z">Label1</label><textbox id="d1" size="2"/>
   <label control="d2">Label2</label><textbox id="d2" size="2"/>
-  <label control="d3">Label3</label><textbox id="d3" accesskey="t" size="2"/>
-  <label control="d4">Label4</label><textbox id="d4" accesskey="b" size="2"/>
-  <label control="d5" maxwidth="50">Quite a long label. Hopefully it will wrap</label><textbox id="d5" accesskey="l" size="2"/>
+  <label control="d3" accesskey="t">Label3</label><textbox id="d3" size="2"/>
+  <label control="d4" accesskey="b">Label4</label><textbox id="d4" size="2"/>
+  <label control="d5" accesskey="l" maxwidth="50">Quite a long label. Hopefully it will wrap</label><textbox id="d5" size="2"/>
 </hbox>
 
 </window>
--- a/layout/style/ServoBindings.h
+++ b/layout/style/ServoBindings.h
@@ -508,16 +508,18 @@ RawServoDeclarationBlockStrong Servo_Par
     RawGeckoURLExtraData* data, mozilla::ParsingMode parsing_mode,
     nsCompatibility quirks_mode, mozilla::css::Loader* loader);
 
 bool Servo_ParseEasing(const nsAString* easing, RawGeckoURLExtraData* data,
                        nsTimingFunctionBorrowedMut output);
 
 void Servo_SerializeEasing(nsTimingFunctionBorrowed easing, nsAString* output);
 
+void Servo_SerializeBorderRadius(const mozilla::StyleBorderRadius*, nsAString*);
+
 void Servo_GetComputedKeyframeValues(
     RawGeckoKeyframeListBorrowed keyframes, RawGeckoElementBorrowed element,
     ComputedStyleBorrowed style, RawServoStyleSetBorrowed set,
     RawGeckoComputedKeyframeValuesListBorrowedMut result);
 
 RawServoAnimationValueStrong Servo_ComputedValues_ExtractAnimationValue(
     ComputedStyleBorrowed computed_values, nsCSSPropertyID property);
 
--- a/layout/style/ServoBindings.toml
+++ b/layout/style/ServoBindings.toml
@@ -439,16 +439,17 @@ cbindgen-types = [
     { gecko = "StyleNonNegativeLength", servo = "values::computed::NonNegativeLength" },
     { gecko = "StyleNonNegativeNumber", servo = "values::computed::NonNegativeNumber" },
     { gecko = "StylePercentage", servo = "values::computed::Percentage" },
     { gecko = "StylePerspective", servo = "values::computed::Perspective" },
     { gecko = "StyleGenericPerspective", servo = "values::generics::box_::Perspective" },
     { gecko = "StyleZIndex", servo = "values::computed::ZIndex" },
     { gecko = "StyleGenericZIndex", servo = "values::generics::position::ZIndex" },
     { gecko = "StyleTransformOrigin", servo = "values::computed::TransformOrigin" },
+    { gecko = "StyleGenericBorderRadius", servo = "values::generics::border::BorderRadius" },
 ]
 
 mapped-generic-types = [
     { generic = true, gecko = "mozilla::RustCell", servo = "::std::cell::Cell" },
     { generic = false, gecko = "ServoNodeData", servo = "AtomicRefCell<ElementData>" },
     { generic = false, gecko = "mozilla::ServoWritingMode", servo = "::logical_geometry::WritingMode" },
     { generic = false, gecko = "mozilla::ServoCustomPropertiesMap", servo = "Option<::servo_arc::Arc<::custom_properties::CustomPropertiesMap>>" },
     { generic = false, gecko = "mozilla::ServoRuleNode", servo = "Option<::rule_tree::StrongRuleNode>" },
@@ -497,16 +498,17 @@ structs-types = [
     "mozilla::CORSMode",
     "mozilla::FontStretch",
     "mozilla::FontSlantStyle",
     "mozilla::FontWeight",
     "mozilla::MallocSizeOf",
     "mozilla::OriginFlags",
     "mozilla::StyleMotion",
     "mozilla::UniquePtr",
+    "mozilla::StyleBorderRadius",
     "mozilla::StyleDisplayMode",
     "mozilla::StylePrefersColorScheme",
     "mozilla::StyleIntersectionObserverRootMargin",
     "mozilla::StyleComputedFontStretchRange",
     "mozilla::StyleComputedFontStyleDescriptor",
     "mozilla::StyleComputedFontWeightRange",
     "mozilla::StyleFontDisplay",
     "mozilla::StyleUnicodeRange",
--- a/layout/style/nsComputedDOMStyle.cpp
+++ b/layout/style/nsComputedDOMStyle.cpp
@@ -1897,34 +1897,34 @@ already_AddRefed<CSSValue> nsComputedDOM
   return GetEllipseRadii(StyleOutline()->mOutlineRadius, eCornerTopLeft);
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::DoGetOutlineRadiusTopRight() {
   return GetEllipseRadii(StyleOutline()->mOutlineRadius, eCornerTopRight);
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::GetEllipseRadii(
-    const nsStyleCorners& aRadius, Corner aFullCorner) {
-  nsStyleCoord radiusX = aRadius.Get(FullToHalfCorner(aFullCorner, false));
-  nsStyleCoord radiusY = aRadius.Get(FullToHalfCorner(aFullCorner, true));
+    const BorderRadius& aRadius, Corner aFullCorner) {
+  const auto& radiusX = aRadius.Get(FullToHalfCorner(aFullCorner, false));
+  const auto& radiusY = aRadius.Get(FullToHalfCorner(aFullCorner, true));
 
   // for compatibility, return a single value if X and Y are equal
   if (radiusX == radiusY) {
     RefPtr<nsROCSSPrimitiveValue> val = new nsROCSSPrimitiveValue;
-    SetValueToCoord(val, radiusX, true);
+    SetValueToLengthPercentage(val, radiusX, true);
     return val.forget();
   }
 
   RefPtr<nsDOMCSSValueList> valueList = GetROCSSValueList(false);
 
   RefPtr<nsROCSSPrimitiveValue> valX = new nsROCSSPrimitiveValue;
   RefPtr<nsROCSSPrimitiveValue> valY = new nsROCSSPrimitiveValue;
 
-  SetValueToCoord(valX, radiusX, true);
-  SetValueToCoord(valY, radiusY, true);
+  SetValueToLengthPercentage(valX, radiusX, true);
+  SetValueToLengthPercentage(valY, radiusY, true);
 
   valueList->AppendCSSValue(valX.forget());
   valueList->AppendCSSValue(valY.forget());
 
   return valueList.forget();
 }
 
 already_AddRefed<CSSValue> nsComputedDOMStyle::GetCSSShadowArray(
@@ -3268,32 +3268,19 @@ void nsComputedDOMStyle::BoxValuesToStri
       if (value2 != value4) {
         aString.Append(' ');
         aString.Append(value4);
       }
     }
   }
 }
 
-void nsComputedDOMStyle::BasicShapeRadiiToString(
-    nsAString& aCssText, const nsStyleCorners& aCorners) {
-  nsTArray<nsStyleCoord> horizontal, vertical;
-  nsAutoString horizontalString, verticalString;
-  NS_FOR_CSS_FULL_CORNERS(corner) {
-    horizontal.AppendElement(aCorners.Get(FullToHalfCorner(corner, false)));
-    vertical.AppendElement(aCorners.Get(FullToHalfCorner(corner, true)));
-  }
-  BoxValuesToString(horizontalString, horizontal, true);
-  BoxValuesToString(verticalString, vertical, true);
-  aCssText.Append(horizontalString);
-  if (horizontalString == verticalString) {
-    return;
-  }
-  aCssText.AppendLiteral(" / ");
-  aCssText.Append(verticalString);
+void nsComputedDOMStyle::BasicShapeRadiiToString(nsAString& aCssText,
+                                                 const BorderRadius& aCorners) {
+  Servo_SerializeBorderRadius(&aCorners, &aCssText);
 }
 
 already_AddRefed<CSSValue>
 nsComputedDOMStyle::CreatePrimitiveValueForBasicShape(
     const UniquePtr<StyleBasicShape>& aStyleBasicShape) {
   MOZ_ASSERT(aStyleBasicShape, "Expect a valid basic shape pointer!");
 
   StyleBasicShapeType type = aStyleBasicShape->GetShapeType();
--- a/layout/style/nsComputedDOMStyle.h
+++ b/layout/style/nsComputedDOMStyle.h
@@ -36,17 +36,16 @@ struct ComputedGridTrackInfo;
 struct ComputedStyleMap;
 struct nsCSSKTableEntry;
 class nsIFrame;
 class nsIPresShell;
 class nsDOMCSSValueList;
 struct nsMargin;
 class nsROCSSPrimitiveValue;
 class nsStyleCoord;
-class nsStyleCorners;
 struct nsStyleFilter;
 class nsStyleGradient;
 struct nsStyleImage;
 class nsStyleSides;
 
 class nsComputedDOMStyle final : public nsDOMCSSDeclaration,
                                  public nsStubMutationObserver {
  private:
@@ -165,21 +164,20 @@ class nsComputedDOMStyle final : public 
 #undef STYLE_STRUCT
 
   /**
    * A method to get a percentage base for a percentage value.  Returns true
    * if a percentage base value was determined, false otherwise.
    */
   typedef bool (nsComputedDOMStyle::*PercentageBaseGetter)(nscoord&);
 
-  already_AddRefed<CSSValue> GetEllipseRadii(const nsStyleCorners& aRadius,
+  already_AddRefed<CSSValue> GetEllipseRadii(const mozilla::BorderRadius&,
                                              mozilla::Corner aFullCorner);
 
-  already_AddRefed<CSSValue> GetOffsetWidthFor(mozilla::Side aSide);
-
+  already_AddRefed<CSSValue> GetOffsetWidthFor(mozilla::Side);
   already_AddRefed<CSSValue> GetAbsoluteOffset(mozilla::Side);
   nscoord GetUsedAbsoluteOffset(mozilla::Side);
   already_AddRefed<CSSValue> GetNonStaticPositionOffset(
       mozilla::Side aSide, bool aResolveAuto, PercentageBaseGetter aWidthGetter,
       PercentageBaseGetter aHeightGetter);
 
   already_AddRefed<CSSValue> GetStaticOffset(mozilla::Side aSide);
 
@@ -291,16 +289,17 @@ class nsComputedDOMStyle final : public 
   already_AddRefed<CSSValue> DoGetBorderBottomWidth();
   already_AddRefed<CSSValue> DoGetBorderLeftWidth();
   already_AddRefed<CSSValue> DoGetBorderRightWidth();
   already_AddRefed<CSSValue> DoGetBorderBottomLeftRadius();
   already_AddRefed<CSSValue> DoGetBorderBottomRightRadius();
   already_AddRefed<CSSValue> DoGetBorderTopLeftRadius();
   already_AddRefed<CSSValue> DoGetBorderTopRightRadius();
 
+
   /* Border Image */
   already_AddRefed<CSSValue> DoGetBorderImageWidth();
 
   /* Box Shadow */
   already_AddRefed<CSSValue> DoGetBoxShadow();
 
   /* Margin Properties */
   already_AddRefed<CSSValue> DoGetMarginTopWidth();
@@ -310,16 +309,17 @@ class nsComputedDOMStyle final : public 
 
   /* Outline Properties */
   already_AddRefed<CSSValue> DoGetOutlineWidth();
   already_AddRefed<CSSValue> DoGetOutlineRadiusBottomLeft();
   already_AddRefed<CSSValue> DoGetOutlineRadiusBottomRight();
   already_AddRefed<CSSValue> DoGetOutlineRadiusTopLeft();
   already_AddRefed<CSSValue> DoGetOutlineRadiusTopRight();
 
+
   /* Text Properties */
   already_AddRefed<CSSValue> DoGetInitialLetter();
   already_AddRefed<CSSValue> DoGetLineHeight();
   already_AddRefed<CSSValue> DoGetTextDecoration();
   already_AddRefed<CSSValue> DoGetTextDecorationColor();
   already_AddRefed<CSSValue> DoGetTextDecorationLine();
   already_AddRefed<CSSValue> DoGetTextDecorationStyle();
   already_AddRefed<CSSValue> DoGetTextEmphasisPosition();
@@ -491,17 +491,17 @@ class nsComputedDOMStyle final : public 
 
   // Helper function for computing basic shape styles.
   already_AddRefed<CSSValue> CreatePrimitiveValueForBasicShape(
       const mozilla::UniquePtr<mozilla::StyleBasicShape>& aStyleBasicShape);
   void BoxValuesToString(nsAString& aString,
                          const nsTArray<nsStyleCoord>& aBoxValues,
                          bool aClampNegativeCalc);
   void BasicShapeRadiiToString(nsAString& aCssText,
-                               const nsStyleCorners& aCorners);
+                               const mozilla::BorderRadius&);
 
   // Find out if we can safely skip flushing for aDocument (i.e. pending
   // restyles does not affect mContent).
   bool NeedsToFlush(Document*) const;
 
   static ComputedStyleMap* GetComputedStyleMap();
 
   // We don't really have a good immutable representation of "presentation".
--- a/layout/style/nsStyleCoord.cpp
+++ b/layout/style/nsStyleCoord.cpp
@@ -198,52 +198,16 @@ bool nsStyleSides::operator==(const nsSt
   }
   return true;
 }
 
 void nsStyleSides::Reset() {
   NS_FOR_CSS_SIDES(i) { nsStyleCoord::Reset(mUnits[i], mValues[i]); }
 }
 
-nsStyleCorners::nsStyleCorners() {
-  NS_FOR_CSS_HALF_CORNERS(i) { mUnits[i] = eStyleUnit_Null; }
-  mozilla::PodArrayZero(mValues);
-}
-
-nsStyleCorners::nsStyleCorners(const nsStyleCorners& aOther) {
-  NS_FOR_CSS_HALF_CORNERS(i) { mUnits[i] = eStyleUnit_Null; }
-  *this = aOther;
-}
-
-nsStyleCorners::~nsStyleCorners() { Reset(); }
-
-nsStyleCorners& nsStyleCorners::operator=(const nsStyleCorners& aCopy) {
-  if (this != &aCopy) {
-    NS_FOR_CSS_HALF_CORNERS(i) {
-      nsStyleCoord::SetValue(mUnits[i], mValues[i], aCopy.mUnits[i],
-                             aCopy.mValues[i]);
-    }
-  }
-  return *this;
-}
-
-bool nsStyleCorners::operator==(const nsStyleCorners& aOther) const {
-  NS_FOR_CSS_HALF_CORNERS(i) {
-    if (nsStyleCoord(mValues[i], (nsStyleUnit)mUnits[i]) !=
-        nsStyleCoord(aOther.mValues[i], (nsStyleUnit)aOther.mUnits[i])) {
-      return false;
-    }
-  }
-  return true;
-}
-
-void nsStyleCorners::Reset() {
-  NS_FOR_CSS_HALF_CORNERS(i) { nsStyleCoord::Reset(mUnits[i], mValues[i]); }
-}
-
 // Validation of SideIsVertical.
 #define CASE(side, result) \
   static_assert(SideIsVertical(side) == result, "SideIsVertical is wrong")
 CASE(eSideTop, false);
 CASE(eSideRight, true);
 CASE(eSideBottom, false);
 CASE(eSideLeft, true);
 #undef CASE
--- a/layout/style/nsStyleCoord.h
+++ b/layout/style/nsStyleCoord.h
@@ -39,16 +39,17 @@ enum LogicalCorner {
   eLogicalCornerBEndIStart = 3
 };
 
 using LengthPercentage = StyleLengthPercentage;
 using LengthPercentageOrAuto = StyleLengthPercentageOrAuto;
 using NonNegativeLengthPercentage = StyleNonNegativeLengthPercentage;
 using NonNegativeLengthPercentageOrAuto =
     StyleNonNegativeLengthPercentageOrAuto;
+using BorderRadius = StyleBorderRadius;
 
 nscoord StyleCSSPixelLength::ToAppUnits() const {
   // We want to resolve the length part of the calc() expression rounding 0.5
   // away from zero, instead of the default behavior of NSToCoordRoundWithClamp
   // which is floor(x + 0.5).
   //
   // This is what the rust code in the app_units crate does, and not doing this
   // would regress bug 1323735, for example.
@@ -246,16 +247,24 @@ bool StyleRect<T>::All(Predicate aPredic
 }
 
 template <typename T>
 template <typename Predicate>
 bool StyleRect<T>::Any(Predicate aPredicate) const {
   return aPredicate(_0) || aPredicate(_1) || aPredicate(_2) || aPredicate(_3);
 }
 
+template <>
+inline const LengthPercentage& BorderRadius::Get(HalfCorner aCorner) const {
+  static_assert(sizeof(BorderRadius) == sizeof(LengthPercentage) * 8, "");
+  static_assert(alignof(BorderRadius) == alignof(LengthPercentage), "");
+  auto* self = reinterpret_cast<const LengthPercentage*>(this);
+  return self[aCorner];
+}
+
 }  // namespace mozilla
 
 enum nsStyleUnit : uint8_t {
   eStyleUnit_Null = 0,           // (no value) value is not specified
   eStyleUnit_Normal = 1,         // (no value)
   eStyleUnit_Auto = 2,           // (no value)
   eStyleUnit_None = 3,           // (no value)
   eStyleUnit_Percent = 10,       // (float) 1.0 == 100%
@@ -584,55 +593,16 @@ class nsStyleSides {
     return true;
   }
 
  protected:
   nsStyleUnit mUnits[4];
   nsStyleUnion mValues[4];
 };
 
-/**
- * Class that represents a set of top-left/top-right/bottom-right/bottom-left
- * nsStyleCoord pairs.  This is used to hold the dimensions of the
- * corners of a box (for, e.g., border-radius and outline-radius).
- */
-/** <div rustbindgen private accessor="unsafe"></div> */
-class nsStyleCorners {
- public:
-  nsStyleCorners();
-  nsStyleCorners(const nsStyleCorners&);
-  ~nsStyleCorners();
-
-  // use compiler's version
-  nsStyleCorners& operator=(const nsStyleCorners& aCopy);
-  bool operator==(const nsStyleCorners& aOther) const;
-  bool operator!=(const nsStyleCorners& aOther) const;
-
-  // aHalfCorner is always one of enum HalfCorner in gfx/2d/Types.h.
-  inline nsStyleUnit GetUnit(uint8_t aHalfCorner) const;
-
-  inline nsStyleCoord Get(uint8_t aHalfCorner) const;
-
-  // Sets each corner to null and releases any refcounted objects.  Only use
-  // this if the object is initialized (i.e. don't use it in nsStyleCorners
-  // constructors).
-  void Reset();
-
-  inline void Set(uint8_t aHalfCorner, const nsStyleCoord& aCoord);
-
- protected:
-  // Stored as:
-  // top-left.x, top-left.y,
-  // top-right.x, top-right.y,
-  // bottom-right.x, bottom-right.y,
-  // bottom-left.x, bottom-left.y
-  nsStyleUnit mUnits[8];
-  nsStyleUnion mValues[8];
-};
-
 // -------------------------
 // nsStyleCoord inlines
 //
 inline nsStyleCoord::nsStyleCoord(nscoord aValue, CoordConstructorType)
     : mUnit(eStyleUnit_Coord) {
   mValue.mInt = aValue;
 }
 
@@ -825,29 +795,9 @@ inline void nsStyleSides::SetTop(const n
 
 inline void nsStyleSides::SetRight(const nsStyleCoord& aCoord) {
   Set(mozilla::eSideRight, aCoord);
 }
 
 inline void nsStyleSides::SetBottom(const nsStyleCoord& aCoord) {
   Set(mozilla::eSideBottom, aCoord);
 }
-
-// -------------------------
-// nsStyleCorners inlines
-//
-inline bool nsStyleCorners::operator!=(const nsStyleCorners& aOther) const {
-  return !((*this) == aOther);
-}
-
-inline nsStyleUnit nsStyleCorners::GetUnit(uint8_t aCorner) const {
-  return (nsStyleUnit)mUnits[aCorner];
-}
-
-inline nsStyleCoord nsStyleCorners::Get(uint8_t aCorner) const {
-  return nsStyleCoord(mValues[aCorner], nsStyleUnit(mUnits[aCorner]));
-}
-
-inline void nsStyleCorners::Set(uint8_t aCorner, const nsStyleCoord& aCoord) {
-  nsStyleCoord::SetValue(mUnits[aCorner], mValues[aCorner], aCoord);
-}
-
 #endif /* nsStyleCoord_h___ */
--- a/layout/style/nsStyleStruct.cpp
+++ b/layout/style/nsStyleStruct.cpp
@@ -237,38 +237,40 @@ nsChangeHint nsStylePadding::CalcDiffere
   return NS_STYLE_HINT_REFLOW & ~nsChangeHint_ClearDescendantIntrinsics;
 }
 
 static nscoord TwipsPerPixel(const Document& aDocument) {
   auto* pc = aDocument.GetPresContext();
   return pc ? pc->AppUnitsPerDevPixel() : mozilla::AppUnitsPerCSSPixel();
 }
 
+static inline BorderRadius ZeroBorderRadius() {
+  auto zero = LengthPercentage::Zero();
+  return {{{zero, zero}}, {{zero, zero}}, {{zero, zero}}, {{zero, zero}}};
+}
+
 nsStyleBorder::nsStyleBorder(const Document& aDocument)
-    : mBorderImageOutset(
+    : mBorderRadius(ZeroBorderRadius()),
+      mBorderImageOutset(
           StyleRectWithAllSides(StyleNonNegativeLengthOrNumber::Number(0.))),
       mBorderImageSlice(
           {StyleRectWithAllSides(StyleNumberOrPercentage::Percentage({1.})),
            false}),
       mBorderImageRepeatH(StyleBorderImageRepeat::Stretch),
       mBorderImageRepeatV(StyleBorderImageRepeat::Stretch),
       mFloatEdge(StyleFloatEdge::ContentBox),
       mBoxDecorationBreak(StyleBoxDecorationBreak::Slice),
       mBorderTopColor(StyleComplexColor::CurrentColor()),
       mBorderRightColor(StyleComplexColor::CurrentColor()),
       mBorderBottomColor(StyleComplexColor::CurrentColor()),
       mBorderLeftColor(StyleComplexColor::CurrentColor()),
       mComputedBorder(0, 0, 0, 0),
       mTwipsPerPixel(TwipsPerPixel(aDocument)) {
   MOZ_COUNT_CTOR(nsStyleBorder);
 
-  NS_FOR_CSS_HALF_CORNERS(corner) {
-    mBorderRadius.Set(corner, nsStyleCoord(0, nsStyleCoord::CoordConstructor));
-  }
-
   nscoord medium = kMediumBorderWidth;
   NS_FOR_CSS_SIDES(side) {
     mBorderImageWidth.Set(side, nsStyleCoord(1.0f, eStyleUnit_Factor));
     mBorder.Side(side) = medium;
     mBorderStyle[side] = StyleBorderStyle::None;
   }
 }
 
@@ -395,26 +397,24 @@ nsChangeHint nsStyleBorder::CalcDifferen
       mBorderImageWidth != aNewData.mBorderImageWidth) {
     return nsChangeHint_NeutralChange;
   }
 
   return nsChangeHint(0);
 }
 
 nsStyleOutline::nsStyleOutline(const Document& aDocument)
-    : mOutlineWidth(kMediumBorderWidth),
+    : mOutlineRadius(ZeroBorderRadius()),
+      mOutlineWidth(kMediumBorderWidth),
       mOutlineOffset(0),
       mOutlineColor(StyleComplexColor::CurrentColor()),
       mOutlineStyle(StyleOutlineStyle::BorderStyle(StyleBorderStyle::None)),
       mActualOutlineWidth(0),
       mTwipsPerPixel(TwipsPerPixel(aDocument)) {
   MOZ_COUNT_CTOR(nsStyleOutline);
-  // spacing values not inherited
-  nsStyleCoord zero(0, nsStyleCoord::CoordConstructor);
-  NS_FOR_CSS_HALF_CORNERS(corner) { mOutlineRadius.Set(corner, zero); }
 }
 
 nsStyleOutline::nsStyleOutline(const nsStyleOutline& aSrc)
     : mOutlineRadius(aSrc.mOutlineRadius),
       mOutlineWidth(aSrc.mOutlineWidth),
       mOutlineOffset(aSrc.mOutlineOffset),
       mOutlineColor(aSrc.mOutlineColor),
       mOutlineStyle(aSrc.mOutlineStyle),
@@ -777,16 +777,22 @@ nsChangeHint nsStyleSVG::CalcDifference(
   }
 
   return hint;
 }
 
 // --------------------
 // StyleBasicShape
 
+StyleBasicShape::StyleBasicShape(StyleBasicShapeType aType)
+    : mType(aType),
+      mFillRule(StyleFillRule::Nonzero),
+      mPosition(Position::FromPercentage(0.5f)),
+      mRadius(ZeroBorderRadius()) {}
+
 nsCSSKeyword StyleBasicShape::GetShapeTypeName() const {
   switch (mType) {
     case StyleBasicShapeType::Polygon:
       return eCSSKeyword_polygon;
     case StyleBasicShapeType::Circle:
       return eCSSKeyword_circle;
     case StyleBasicShapeType::Ellipse:
       return eCSSKeyword_ellipse;
--- a/layout/style/nsStyleStruct.h
+++ b/layout/style/nsStyleStruct.h
@@ -938,17 +938,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   imgIRequest* GetBorderImageRequest() const {
     if (mBorderImageSource.GetType() == eStyleImageType_Image) {
       return mBorderImageSource.GetImageData();
     }
     return nullptr;
   }
 
  public:
-  nsStyleCorners mBorderRadius;  // coord, percent
+  mozilla::StyleBorderRadius mBorderRadius;  // coord, percent
   nsStyleImage mBorderImageSource;
   nsStyleSides mBorderImageWidth;  // length, factor, percent, auto
   mozilla::StyleNonNegativeLengthOrNumberRect mBorderImageOutset;
   mozilla::StyleBorderImageSlice mBorderImageSlice;  // factor, percent
   mozilla::StyleBorderImageRepeat mBorderImageRepeatH;
   mozilla::StyleBorderImageRepeat mBorderImageRepeatV;
   mozilla::StyleFloatEdge mFloatEdge;
   mozilla::StyleBoxDecorationBreak mBoxDecorationBreak;
@@ -1042,17 +1042,17 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   explicit nsStyleOutline(const mozilla::dom::Document&);
   nsStyleOutline(const nsStyleOutline& aOutline);
   ~nsStyleOutline() { MOZ_COUNT_DTOR(nsStyleOutline); }
   void TriggerImageLoads(mozilla::dom::Document&, const nsStyleOutline*) {}
   const static bool kHasTriggerImageLoads = false;
 
   nsChangeHint CalcDifference(const nsStyleOutline& aNewData) const;
 
-  nsStyleCorners mOutlineRadius;  // coord, percent, calc
+  mozilla::StyleBorderRadius mOutlineRadius;
 
   // This is the specified value of outline-width, but with length values
   // computed to absolute.  mActualOutlineWidth stores the outline-width
   // value used by layout.  (We must store mOutlineWidth for the same
   // style struct resolution reasons that we do nsStyleBorder::mBorder;
   // see that field's comment.)
   nscoord mOutlineWidth;
   nscoord mOutlineOffset;
@@ -1286,19 +1286,19 @@ struct MOZ_NEEDS_MEMMOVABLE_MEMBERS nsSt
   // mSpecifiedJustifyItems, except when the latter is AUTO -- in that case,
   // mJustifyItems is set to NORMAL, or to the parent ComputedStyle's
   // mJustifyItems if it has the legacy flag.
   //
   // This last part happens in ComputedStyle::ApplyStyleFixups.
   uint8_t mSpecifiedJustifyItems;
   uint8_t mJustifyItems;
   uint8_t mJustifySelf;
-  mozilla::StyleFlexDirection mFlexDirection;  
-  uint8_t mFlexWrap;       // NS_STYLE_FLEX_WRAP_*
-  uint8_t mObjectFit;      // NS_STYLE_OBJECT_FIT_*
+  mozilla::StyleFlexDirection mFlexDirection;
+  uint8_t mFlexWrap;   // NS_STYLE_FLEX_WRAP_*
+  uint8_t mObjectFit;  // NS_STYLE_OBJECT_FIT_*
   int32_t mOrder;
   float mFlexGrow;
   float mFlexShrink;
   mozilla::StyleZIndex mZIndex;
   mozilla::UniquePtr<nsStyleGridTemplate> mGridTemplateColumns;
   mozilla::UniquePtr<nsStyleGridTemplate> mGridTemplateRows;
 
   // nullptr for 'none'
@@ -1630,46 +1630,42 @@ struct StyleAnimation {
   dom::PlaybackDirection mDirection;
   dom::FillMode mFillMode;
   StyleAnimationPlayState mPlayState;
   float mIterationCount;  // mozilla::PositiveInfinity<float>() means infinite
 };
 
 class StyleBasicShape final {
  public:
-  explicit StyleBasicShape(StyleBasicShapeType type)
-      : mType(type),
-        mFillRule(StyleFillRule::Nonzero),
-        mPosition(Position::FromPercentage(0.5f)) {}
+  explicit StyleBasicShape(StyleBasicShapeType);
 
   StyleBasicShapeType GetShapeType() const { return mType; }
   nsCSSKeyword GetShapeTypeName() const;
 
   StyleFillRule GetFillRule() const { return mFillRule; }
 
   const mozilla::Position& GetPosition() const {
     MOZ_ASSERT(mType == StyleBasicShapeType::Circle ||
                    mType == StyleBasicShapeType::Ellipse,
                "expected circle or ellipse");
     return mPosition;
   }
 
   bool HasRadius() const {
     MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
-    nsStyleCoord zero;
-    zero.SetCoordValue(0);
     NS_FOR_CSS_HALF_CORNERS(corner) {
-      if (mRadius.Get(corner) != zero) {
+      auto& radius = mRadius.Get(corner);
+      if (radius.HasPercent() || radius.LengthInCSSPixels() != 0.0f) {
         return true;
       }
     }
     return false;
   }
 
-  const nsStyleCorners& GetRadius() const {
+  const mozilla::StyleBorderRadius& GetRadius() const {
     MOZ_ASSERT(mType == StyleBasicShapeType::Inset, "expected inset");
     return mRadius;
   }
 
   // mCoordinates has coordinates for polygon or radii for
   // ellipse and circle.
   const nsTArray<nsStyleCoord>& Coordinates() const { return mCoordinates; }
 
@@ -1688,17 +1684,17 @@ class StyleBasicShape final {
 
   // mCoordinates has coordinates for polygon or radii for
   // ellipse and circle.
   // (top, right, bottom, left) for inset
   nsTArray<nsStyleCoord> mCoordinates;
   // position of center for ellipse or circle
   mozilla::Position mPosition;
   // corner radii for inset (0 if not set)
-  nsStyleCorners mRadius;
+  mozilla::StyleBorderRadius mRadius;
 };
 
 struct StyleSVGPath final {
   const nsTArray<StylePathCommand>& Path() const { return mPath; }
 
   StyleFillRule FillRule() const { return mFillRule; }
 
   bool operator==(const StyleSVGPath& aOther) const {
--- a/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
+++ b/mobile/android/base/java/org/mozilla/gecko/IntentHelper.java
@@ -337,22 +337,22 @@ public final class IntentHelper implemen
         if ("intent".equals(scheme) || "android-app".equals(scheme)) {
             return IntentUtils.getSafeIntent(uri);
         }
 
         // Compute our most likely intent, then check to see if there are any
         // custom handlers that would apply.
         // Start with the original URI. If we end up modifying it, we'll
         // overwrite it.
-        final String extension = MimeTypeMap.getFileExtensionFromUrl(targetURI);
         final Intent intent = getIntentForActionString(action);
         intent.setData(uri);
 
         if ("file".equals(scheme)) {
             // Only set explicit mimeTypes on file://.
+            final String extension = MimeTypeMap.getFileExtensionFromUrl(targetURI);
             final String mimeType2 = GeckoAppShell.getMimeTypeFromExtension(extension);
             intent.setType(mimeType2);
             return intent;
         }
 
         // Have a special handling for SMS based schemes, as the query parameters
         // are not extracted from the URI automatically.
         if (!"sms".equals(scheme) && !"smsto".equals(scheme) && !"mms".equals(scheme) && !"mmsto".equals(scheme)) {
--- a/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java
+++ b/mobile/android/geckoview/src/main/java/org/mozilla/geckoview/PanZoomController.java
@@ -50,16 +50,18 @@ public class PanZoomController extends J
      * Specifies auto scrolling which jumps content to the desired scroll position.
      */
     public static final int SCROLL_BEHAVIOR_AUTO = 1;
 
     private SynthesizedEventState mPointerState;
 
     private ArrayList<Pair<Integer, MotionEvent>> mQueuedEvents;
 
+    private boolean mSynthesizedEvent = false;
+
     @WrapForJNI(calledFrom = "ui")
     private native boolean handleMotionEvent(
             int action, int actionIndex, long time, int metaState,  float screenX, float screenY,
             int pointerId[], float x[], float y[], float orientation[], float pressure[],
             float toolMajor[], float toolMinor[]);
 
     @WrapForJNI(calledFrom = "ui")
     private native boolean handleScrollEvent(
@@ -112,17 +114,20 @@ public class PanZoomController extends J
             toolMinor[i] = coords.toolMinor;
         }
 
         final float screenX = event.getRawX() - event.getX();
         final float screenY = event.getRawY() - event.getY();
 
         // Take this opportunity to update screen origin of session. This gets
         // dispatched to the gecko thread, so we also pass the new screen x/y directly to apz.
-        mSession.onScreenOriginChanged((int)screenX, (int)screenY);
+        // If this is a synthesized touch, the screen offset is bogus so ignore it.
+        if (!mSynthesizedEvent) {
+            mSession.onScreenOriginChanged((int)screenX, (int)screenY);
+        }
 
         return handleMotionEvent(action, event.getActionIndex(), event.getEventTime(),
                 event.getMetaState(), screenX, screenY, pointerId, x, y, orientation, pressure,
                 toolMajor, toolMinor);
     }
 
     private boolean handleScrollEvent(MotionEvent event) {
         if (!mAttached) {
@@ -515,17 +520,20 @@ public class PanZoomController extends J
             /*metaState*/ 0,
             /*buttonState*/ (isButtonDown ? MotionEvent.BUTTON_PRIMARY : 0),
             /*xPrecision*/ 0,
             /*yPrecision*/ 0,
             /*deviceId*/ 0,
             /*edgeFlags*/ 0,
             /*source*/ source,
             /*flags*/ 0);
+
+        mSynthesizedEvent = true;
         onTouchEvent(event);
+        mSynthesizedEvent = false;
 
         // Forget about removed pointers
         if (eventType == MotionEvent.ACTION_POINTER_UP ||
             eventType == MotionEvent.ACTION_UP ||
             eventType == MotionEvent.ACTION_CANCEL ||
             eventType == MotionEvent.ACTION_HOVER_MOVE)
         {
             mPointerState.pointers.remove(pointerIndex);
--- a/mobile/android/modules/HelperApps.jsm
+++ b/mobile/android/modules/HelperApps.jsm
@@ -15,99 +15,112 @@ ChromeUtils.defineModuleGetter(this, "Ev
                                "resource://gre/modules/Messaging.jsm");
 
 XPCOMUtils.defineLazyGetter(this, "ContentAreaUtils", function() {
   let ContentAreaUtils = {};
   Services.scriptloader.loadSubScript("chrome://global/content/contentAreaUtils.js", ContentAreaUtils);
   return ContentAreaUtils;
 });
 
+const NON_FILE_URI_IGNORED_MIME_TYPES = new Set([
+  "text/html",
+  "application/xhtml+xml",
+]);
+
 var EXPORTED_SYMBOLS = ["App", "HelperApps"];
 
-function App(data) {
-  this.name = data.name;
-  this.isDefault = data.isDefault;
-  this.packageName = data.packageName;
-  this.activityName = data.activityName;
-  this.iconUri = "-moz-icon://" + data.packageName;
-}
+class App {
+  constructor(data) {
+    this.name = data.name;
+    this.isDefault = data.isDefault;
+    this.packageName = data.packageName;
+    this.activityName = data.activityName;
+    this.iconUri = "-moz-icon://" + data.packageName;
+  }
 
-App.prototype = {
   // callback will be null if a result is not requested
-  launch: function(uri, callback) {
+  launch(uri, callback) {
     HelperApps._launchApp(this, uri, callback);
     return false;
-  },
-};
+  }
+}
 
 var HelperApps =  {
   get defaultBrowsers() {
     delete this.defaultBrowsers;
-    this.defaultBrowsers = this._getHandlers("http://www.example.com", {
+    this.defaultBrowsers = this._collectDefaultBrowsers();
+    return this.defaultBrowsers;
+  },
+
+  _collectDefaultBrowsers() {
+    let httpHandlers = this._getHandlers("http://www.example.com", {
       filterBrowsers: false,
       filterHtml: false,
     });
-    return this.defaultBrowsers;
+    let httpsHandlers = this._getHandlers("https://www.example.com", {
+      filterBrowsers: false,
+      filterHtml: false,
+    });
+    return {...httpHandlers, ...httpsHandlers};
   },
 
-  // Finds handlers that have registered for text/html pages or urls ending in html. Some apps, like
-  // the Samsung Video player will only appear for these urls, while some Browsers (like Link Bubble)
-  // won't register here because of the text/html mime type.
+  // Finds handlers that have registered for urls ending in html. Some apps, like
+  // the Samsung Video player, will only appear for these urls.
   get defaultHtmlHandlers() {
     delete this.defaultHtmlHandlers;
     return this.defaultHtmlHandlers = this._getHandlers("http://www.example.com/index.html", {
       filterBrowsers: false,
       filterHtml: false,
     });
   },
 
-  _getHandlers: function(url, options) {
+  _getHandlers(url, options) {
     let values = {};
 
     let handlers = this.getAppsForUri(Services.io.newURI(url), options);
-    handlers.forEach(function(app) {
+    handlers.forEach(app => {
       values[app.name] = app;
-    }, this);
+    });
 
     return values;
   },
 
   get protoSvc() {
     delete this.protoSvc;
     return this.protoSvc = Cc["@mozilla.org/uriloader/external-protocol-service;1"].getService(Ci.nsIExternalProtocolService);
   },
 
   get urlHandlerService() {
     delete this.urlHandlerService;
     return this.urlHandlerService = Cc["@mozilla.org/uriloader/external-url-handler-service;1"].getService(Ci.nsIExternalURLHandlerService);
   },
 
-  prompt: function showPicker(apps, promptOptions, callback) {
+  prompt(apps, promptOptions, callback) {
     let p = new Prompt(promptOptions).addIconGrid({ items: apps });
     p.show(callback);
   },
 
-  getAppsForProtocol: function getAppsForProtocol(scheme) {
+  getAppsForProtocol(scheme) {
     let protoHandlers = this.protoSvc.getProtocolHandlerInfoFromOS(scheme, {}).possibleApplicationHandlers;
 
     let results = {};
     for (let i = 0; i < protoHandlers.length; i++) {
       try {
         let protoApp = protoHandlers.queryElementAt(i, Ci.nsIHandlerApp);
         results[protoApp.name] = new App({
           name: protoApp.name,
           description: protoApp.detailedDescription,
         });
       } catch (e) {}
     }
 
     return results;
   },
 
-  getAppsForUri: function getAppsForUri(uri, flags = { }, callback) {
+  getAppsForUri(uri, flags = { }, callback) {
     // Return early for well-known internal schemes
     if (!uri || uri.schemeIs("about") || uri.schemeIs("chrome")) {
       if (callback) {
         callback([]);
       }
       return [];
     }
 
@@ -119,92 +132,104 @@ var HelperApps =  {
     let parseData = (apps) => {
       if (!apps) {
         return [];
       }
 
       apps = this._parseApps(apps);
 
       if (flags.filterBrowsers) {
-        apps = apps.filter((app) => {
-          return app.name && !this.defaultBrowsers[app.name];
-        });
+        apps = apps.filter(app =>
+          app.name && !this.defaultBrowsers[app.name]);
       }
 
       // Some apps will register for html files (the Samsung Video player) but should be shown
       // for non-HTML files (like videos). This filters them only if the page has an htm of html
       // file extension.
       if (flags.filterHtml) {
         // Matches from the first '.' to the end of the string, '?', or '#'
         let ext = /\.([^\?#]*)/.exec(uri.pathQueryRef);
         if (ext && (ext[1] === "html" || ext[1] === "htm")) {
-          apps = apps.filter(function(app) {
-            return app.name && !this.defaultHtmlHandlers[app.name];
-          }, this);
+          apps = apps.filter(app =>
+            app.name && !this.defaultHtmlHandlers[app.name]);
         }
       }
 
       return apps;
     };
 
     if (!callback) {
       let data = null;
       // Use dispatch to enable synchronous callback for Gecko thread event.
       EventDispatcher.instance.dispatch(msg.type, msg, {
-        onSuccess: (result) => { data = result; },
+        onSuccess: result => { data = result; },
         onError: () => { throw new Error("Intent:GetHandler callback failed"); },
       });
       if (data === null) {
         throw new Error("Intent:GetHandler did not return data");
       }
       return parseData(data);
     }
-      EventDispatcher.instance.sendRequestForResult(msg).then(function(data) {
+      EventDispatcher.instance.sendRequestForResult(msg).then(data => {
         callback(parseData(data));
       });
   },
 
-  launchUri: function launchUri(uri) {
+  launchUri(uri) {
     let msg = this._getMessage("Intent:Open", uri);
     EventDispatcher.instance.sendRequest(msg);
   },
 
-  _parseApps: function _parseApps(appInfo) {
+  _parseApps(appInfo) {
     // appInfo -> {apps: [app1Label, app1Default, app1PackageName, app1ActivityName, app2Label, app2Defaut, ...]}
     // see GeckoAppShell.java getHandlersForIntent function for details
     const numAttr = 4; // 4 elements per ResolveInfo: label, default, package name, activity name.
 
     let apps = [];
     for (let i = 0; i < appInfo.length; i += numAttr) {
       apps.push(new App({"name": appInfo[i],
                  "isDefault": appInfo[i + 1],
                  "packageName": appInfo[i + 2],
                  "activityName": appInfo[i + 3]}));
     }
 
     return apps;
   },
 
-  _getMessage: function(type, uri, options = {}) {
+  _getMessage(type, uri, options = {}) {
     let mimeType = options.mimeType;
     if (uri && mimeType == undefined) {
       mimeType = ContentAreaUtils.getMIMETypeForURI(uri) || "";
+      if (uri.scheme != "file" && NON_FILE_URI_IGNORED_MIME_TYPES.has(mimeType)) {
+        // We're guessing the MIME type based on the extension, which especially
+        // with non-local HTML documents will yield inconsistent results, as those
+        // commonly use URLs without any sort of extension, too.
+        // At the same time, apps offering to handle certain URLs in lieu of a
+        // browser often don't expect a MIME type to be used, and correspondingly
+        // register their intent filters without a MIME type.
+        // This means that when we *do* guess a non-empty MIME type because this
+        // time the URL *did* end on .(x)htm(l), Android won't offer any apps whose
+        // intent filter doesn't explicitly include that MIME type.
+        // Therefore, if the MIME type looks like something from that category,
+        // don't bother including it in the Intent for non-local files.
+        mimeType = "";
+      }
     }
 
     return {
       type: type,
       mime: mimeType,
       action: options.action || "", // empty action string defaults to android.intent.action.VIEW
       url: uri ? uri.displaySpec : "",
       packageName: options.packageName || "",
       className: options.className || "",
     };
   },
 
-  _launchApp: function launchApp(app, uri, callback) {
+  _launchApp(app, uri, callback) {
     if (callback) {
         let msg = this._getMessage("Intent:OpenForResult", uri, {
             packageName: app.packageName,
             className: app.activityName,
         });
 
         EventDispatcher.instance.sendRequestForResult(msg).then(callback);
     } else {
--- a/netwerk/cookie/nsCookieService.cpp
+++ b/netwerk/cookie/nsCookieService.cpp
@@ -3239,17 +3239,17 @@ bool nsCookieService::CanSetCookie(nsIUR
 
   // Collect telemetry on how often secure cookies are set from non-secure
   // origins, and vice-versa.
   //
   // 0 = nonsecure and "http:"
   // 1 = nonsecure and "https:"
   // 2 = secure and "http:"
   // 3 = secure and "https:"
-  bool isHTTPS;
+  bool isHTTPS = true;
   nsresult rv = aHostURI->SchemeIs("https", &isHTTPS);
   if (NS_SUCCEEDED(rv)) {
     Telemetry::Accumulate(Telemetry::COOKIE_SCHEME_SECURITY,
                           ((aCookieAttributes.isSecure) ? 0x02 : 0x00) |
                               ((isHTTPS) ? 0x01 : 0x00));
 
     // Collect telemetry on how often are first- and third-party cookies set
     // from HTTPS origins:
@@ -3340,25 +3340,20 @@ bool nsCookieService::CanSetCookie(nsIUR
 
   // if the new cookie is httponly, make sure we're not coming from script
   if (!aFromHttp && aCookieAttributes.isHttpOnly) {
     COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, savedCookieHeader,
                       "cookie is httponly; coming from script");
     return newCookie;
   }
 
-  bool isSecure = true;
-  if (aHostURI) {
-    aHostURI->SchemeIs("https", &isSecure);
-  }
-
   // If the new cookie is non-https and wants to set secure flag,
   // browser have to ignore this new cookie.
   // (draft-ietf-httpbis-cookie-alone section 3.1)
-  if (aCookieAttributes.isSecure && !isSecure) {
+  if (aCookieAttributes.isSecure && !isHTTPS) {
     COOKIE_LOGFAILURE(SET_COOKIE, aHostURI, aCookieHeader,
                       "non-https cookie can't set secure flag");
     return newCookie;
   }
 
   // If the new cookie is same-site but in a cross site context,
   // browser must ignore the cookie.
   if ((aCookieAttributes.sameSite != nsICookie2::SAMESITE_UNSET) &&
--- a/services/common/kinto-offline-client.js
+++ b/services/common/kinto-offline-client.js
@@ -28,17 +28,17 @@
 //
 // See https://bugzilla.mozilla.org/show_bug.cgi?id=1394556#c3 for
 // more details.
 const global = this;
 
 var EXPORTED_SYMBOLS = ["Kinto"];
 
 /*
- * Version 12.2.4 - 8fb687a
+ * Version 12.3.0 - f7a9e81
  */
 
 (function(f){if(typeof exports==="object"&&typeof module!=="undefined"){module.exports=f()}else if(typeof define==="function"&&define.amd){define([],f)}else{var g;if(typeof window!=="undefined"){g=window}else if(typeof global!=="undefined"){g=global}else if(typeof self!=="undefined"){g=self}else{g=this}g.Kinto = f()}})(function(){var define,module,exports;return (function(){function r(e,n,t){function o(i,f){if(!n[i]){if(!e[i]){var c="function"==typeof require&&require;if(!f&&c)return c(i,!0);if(u)return u(i,!0);var a=new Error("Cannot find module '"+i+"'");throw a.code="MODULE_NOT_FOUND",a}var p=n[i]={exports:{}};e[i][0].call(p.exports,function(r){var n=e[i][1][r];return o(n||r)},p,p.exports,r,e,n,t)}return n[i].exports}for(var u="function"==typeof require&&require,i=0;i<t.length;i++)o(t[i]);return o}return r})()({1:[function(require,module,exports){
 /*
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
  * You may obtain a copy of the License at
@@ -560,17 +560,17 @@ class IDB extends _base.default {
     super();
     this.cid = cid;
     this.dbName = options.dbName || "KintoDB";
     this._options = options;
     this._db = null;
   }
 
   _handleError(method, err) {
-    const error = new Error(method + "() " + err.message);
+    const error = new Error(`IndexedDB ${method}() ${err.message}`);
     error.stack = err.stack;
     throw error;
   }
   /**
    * Ensures a connection to the IndexedDB database has been opened.
    *
    * @override
    * @return {Promise}
@@ -609,17 +609,17 @@ class IDB extends _base.default {
       }
     });
 
     if (dataToMigrate) {
       const {
         records,
         timestamp
       } = dataToMigrate;
-      await this.loadDump(records);
+      await this.importBulk(records);
       await this.saveLastModified(timestamp);
       console.log(`${this.cid}: data was migrated successfully.`); // Delete the old database.
 
       await deleteDatabase(this.cid);
       console.warn(`${this.cid}: old database was deleted.`);
     }
 
     return this;
@@ -881,23 +881,36 @@ class IDB extends _base.default {
       return entry ? entry.value : null;
     } catch (e) {
       this._handleError("getLastModified", e);
     }
   }
   /**
    * Load a dump of records exported from a server.
    *
+   * @deprecated Use {@link importBulk} instead.
    * @abstract
    * @param  {Array} records The records to load.
    * @return {Promise}
    */
 
 
   async loadDump(records) {
+    return this.importBulk(records);
+  }
+  /**
+   * Load records in bulk that were exported from a server.
+   *
+   * @abstract
+   * @param  {Array} records The records to load.
+   * @return {Promise}
+   */
+
+
+  async importBulk(records) {
     try {
       await this.execute(transaction => {
         // Since the put operations are asynchronous, we chain
         // them together. The last one will be waited for the
         // `transaction.oncomplete` callback. (see #execute())
         let i = 0;
         putNext();
 
@@ -915,17 +928,17 @@ class IDB extends _base.default {
       const lastModified = Math.max(...records.map(record => record.last_modified));
 
       if (lastModified > previousLastModified) {
         await this.saveLastModified(lastModified);
       }
 
       return records;
     } catch (e) {
-      this._handleError("loadDump", e);
+      this._handleError("importBulk", e);
     }
   }
 
 }
 /**
  * IDB transaction proxy.
  *
  * @param  {IDB} adapter        The call IDB adapter
@@ -1112,18 +1125,31 @@ class BaseAdapter {
    * @return {Promise}
    */
 
 
   getLastModified() {
     throw new Error("Not Implemented.");
   }
   /**
+   * Load records in bulk that were exported from a server.
+   *
+   * @abstract
+   * @param  {Array} records The records to load.
+   * @return {Promise}
+   */
+
+
+  importBulk(records) {
+    throw new Error("Not Implemented.");
+  }
+  /**
    * Load a dump of records exported from a server.
    *
+   * @deprecated Use {@link importBulk} instead.
    * @abstract
    * @param  {Array} records The records to load.
    * @return {Promise}
    */
 
 
   loadDump(records) {
     throw new Error("Not Implemented.");
@@ -1135,17 +1161,17 @@ exports.default = BaseAdapter;
 
 },{}],6:[function(require,module,exports){
 "use strict";
 
 Object.defineProperty(exports, "__esModule", {
   value: true
 });
 exports.recordsEqual = recordsEqual;
-exports.CollectionTransaction = exports.default = exports.SyncResultObject = void 0;
+exports.CollectionTransaction = exports.default = exports.ServerWasFlushedError = exports.SyncResultObject = void 0;
 
 var _base = _interopRequireDefault(require("./adapters/base"));
 
 var _IDB = _interopRequireDefault(require("./adapters/IDB"));
 
 var _utils = require("./utils");
 
 var _uuid = require("uuid");
@@ -1258,16 +1284,32 @@ class SyncResultObject {
     this.ok = this.errors.length + this.conflicts.length === 0;
     return this;
   }
 
 }
 
 exports.SyncResultObject = SyncResultObject;
 
+class ServerWasFlushedError extends Error {
+  constructor(clientTimestamp, serverTimestamp, message) {
+    super(message);
+
+    if (Error.captureStackTrace) {
+      Error.captureStackTrace(this, ServerWasFlushedError);
+    }
+
+    this.clientTimestamp = clientTimestamp;
+    this.serverTimestamp = serverTimestamp;
+  }
+
+}
+
+exports.ServerWasFlushedError = ServerWasFlushedError;
+
 function createUUIDSchema() {
   return {
     generate() {
       return (0, _uuid.v4)();
     },
 
     validate(id) {
       return typeof id == "string" && _utils.RE_RECORD_ID.test(id);
@@ -2257,17 +2299,18 @@ class Collection {
     // This is relevant for the Kinto demo server
     // (and thus for many new comers).
 
     const localSynced = options.lastModified;
     const serverChanged = unquoted > options.lastModified;
     const emptyCollection = data.length === 0;
 
     if (!options.exclude && localSynced && serverChanged && emptyCollection) {
-      throw Error("Server has been flushed.");
+      const e = new ServerWasFlushedError(localSynced, unquoted, "Server has been flushed. Client Side Timestamp: " + localSynced + " Server Side Timestamp: " + unquoted);
+      throw e;
     }
 
     syncResultObject.lastModified = unquoted; // Decode incoming changes.
 
     const decodedChanges = await Promise.all(data.map(change => {
       return this._decodeRecord("remote", change);
     })); // Hook receives decoded records.
 
@@ -2573,22 +2616,37 @@ class Collection {
     return result;
   }
   /**
    * Load a list of records already synced with the remote server.
    *
    * The local records which are unsynced or whose timestamp is either missing
    * or superior to those being loaded will be ignored.
    *
+   * @deprecated Use {@link importBulk} instead.
    * @param  {Array} records The previously exported list of records to load.
    * @return {Promise} with the effectively imported records.
    */
 
 
   async loadDump(records) {
+    return this.importBulk(records);
+  }
+  /**
+   * Load a list of records already synced with the remote server.
+   *
+   * The local records which are unsynced or whose timestamp is either missing
+   * or superior to those being loaded will be ignored.
+   *
+   * @param  {Array} records The previously exported list of records to load.
+   * @return {Promise} with the effectively imported records.
+   */
+
+
+  async importBulk(records) {
     if (!Array.isArray(records)) {
       throw new Error("Records is not an array.");
     }
 
     for (const record of records) {
       if (!record.hasOwnProperty("id") || !this.idSchema.validate(record.id)) {
         throw new Error("Record has invalid ID: " + JSON.stringify(record));
       }
@@ -2614,17 +2672,17 @@ class Collection {
       const localRecord = existingById[record.id];
       const shouldKeep = // No local record with this id.
       localRecord === undefined || // Or local record is synced
       localRecord._status === "synced" && // And was synced from server
       localRecord.last_modified !== undefined && // And is older than imported one.
       record.last_modified > localRecord.last_modified;
       return shouldKeep;
     });
-    return await this.db.loadDump(newRecords.map(markSynced));
+    return await this.db.importBulk(newRecords.map(markSynced));
   }
 
 }
 /**
  * A Collection-oriented wrapper for an adapter's transaction.
  *
  * This defines the high-level functions available on a collection.
  * The collection itself offers functions of the same name. These will
--- a/services/common/kinto-storage-adapter.js
+++ b/services/common/kinto-storage-adapter.js
@@ -326,27 +326,31 @@ class FirefoxAdapter extends Kinto.adapt
       return records;
     }).then(results => {
       // The resulting list of records is filtered and sorted.
       // XXX: with some efforts, this could be implemented using SQL.
       return reduceRecords(params.filters, params.order, results);
     });
   }
 
+  async loadDump(records) {
+    return this.importBulk(records);
+  }
+
   /**
    * Load a list of records into the local database.
    *
    * Note: The adapter is not in charge of filtering the already imported
    * records. This is done in `Collection#loadDump()`, as a common behaviour
    * between every adapters.
    *
    * @param  {Array} records.
    * @return {Array} imported records.
    */
-  async loadDump(records) {
+  async importBulk(records) {
     const connection = this._connection;
     const collection_name = this.collection;
     await connection.executeTransaction(async function doImport() {
       for (let record of records) {
         const params = {
           collection_name,
           record_id: record.id,
           record: JSON.stringify(record),
--- a/services/common/tests/unit/test_kinto.js
+++ b/services/common/tests/unit/test_kinto.js
@@ -208,24 +208,24 @@ add_task(async function test_kinto_list(
     }
   } finally {
     await sqliteHandle.close();
   }
 });
 
 add_task(clear_collection);
 
-add_task(async function test_loadDump_ignores_already_imported_records() {
+add_task(async function test_importBulk_ignores_already_imported_records() {
   let sqliteHandle;
   try {
     sqliteHandle = await do_get_kinto_sqliteHandle();
     const collection = do_get_kinto_collection(sqliteHandle);
     const record = {id: "41b71c13-17e9-4ee3-9268-6a41abf9730f", title: "foo", last_modified: 1457896541};
-    await collection.loadDump([record]);
-    let impactedRecords = await collection.loadDump([record]);
+    await collection.importBulk([record]);
+    let impactedRecords = await collection.importBulk([record]);
     Assert.equal(impactedRecords.length, 0);
   } finally {
     await sqliteHandle.close();
   }
 });
 
 add_task(clear_collection);
 
--- a/services/settings/RemoteSettingsClient.jsm
+++ b/services/settings/RemoteSettingsClient.jsm
@@ -380,17 +380,17 @@ class RemoteSettingsClient extends Event
           await this.emit("sync", { data: filteredSyncResult });
         } catch (e) {
           reportStatus = UptakeTelemetry.STATUS.APPLY_ERROR;
           throw e;
         }
       }
     } catch (e) {
       // IndexedDB errors. See https://developer.mozilla.org/en-US/docs/Web/API/IDBRequest/error
-      if (/(AbortError|ConstraintError|QuotaExceededError|VersionError)/.test(e.message)) {
+      if (/(IndexedDB|AbortError|ConstraintError|QuotaExceededError|VersionError)/.test(e.message)) {
         reportStatus = UptakeTelemetry.STATUS.CUSTOM_1_ERROR;
       }
       // No specific error was tracked, mark it as unknown.
       if (reportStatus === null) {
         reportStatus = UptakeTelemetry.STATUS.UNKNOWN_ERROR;
       }
       throw e;
     } finally {
--- a/services/settings/test/unit/test_remote_settings.js
+++ b/services/settings/test/unit/test_remote_settings.js
@@ -380,16 +380,33 @@ add_task(async function test_telemetry_r
 
   client.openCollection = backup;
   const endHistogram = getUptakeTelemetrySnapshot(client.identifier);
   const expectedIncrements = {[UptakeTelemetry.STATUS.UNKNOWN_ERROR]: 1};
   checkUptakeTelemetry(startHistogram, endHistogram, expectedIncrements);
 });
 add_task(clear_state);
 
+add_task(async function test_telemetry_reports_indexeddb_as_custom_1() {
+  const backup = client.openCollection;
+  const msg = "IndexedDB getLastModified() The operation failed for reasons unrelated to the database itself";
+  client.openCollection = () => { throw new Error(msg); };
+  const startHistogram = getUptakeTelemetrySnapshot(client.identifier);
+
+  try {
+    await client.maybeSync(2000);
+  } catch (e) { }
+
+  client.openCollection = backup;
+  const endHistogram = getUptakeTelemetrySnapshot(client.identifier);
+  const expectedIncrements = {[UptakeTelemetry.STATUS.CUSTOM_1_ERROR]: 1};
+  checkUptakeTelemetry(startHistogram, endHistogram, expectedIncrements);
+});
+add_task(clear_state);
+
 add_task(async function test_bucketname_changes_when_bucket_pref_changes() {
   equal(client.bucketName, "main");
 
   Services.prefs.setCharPref("services.settings.default_bucket", "main-preview");
 
   equal(client.bucketName, "main-preview");
 });
 add_task(clear_state);
--- a/servo/components/style/cbindgen.toml
+++ b/servo/components/style/cbindgen.toml
@@ -8,16 +8,17 @@ autogen_warning = """/* DO NOT MODIFY TH
  *   2. Run `rustup run nightly cbindgen toolkit/library/rust/ --lockfile Cargo.lock --crate style -o layout/style/ServoStyleConsts.h`
  */
 #include "nsCoord.h"
 #include "Units.h"
 #include "mozilla/gfx/Types.h"
 class nsAtom;
 namespace mozilla {
   class WritingMode;
+  enum HalfCorner : uint8_t;
   enum LogicalSide : uint8_t;
   namespace css {
     struct URLValue;
   }
 
   // Work-around weird cbindgen renaming.
   typedef css::URLValue StyleURLValue;
   typedef nsAtom StylensAtom;
@@ -83,16 +84,18 @@ include = [
   "Rect",
   "IntersectionObserverRootMargin",
   "Size",
   "MaxSize",
   "FlexBasis",
   "Position",
   "BackgroundSize",
   "BorderImageSlice",
+  "BorderSpacing",
+  "BorderRadius",
   "NonNegativeLengthOrNumberRect",
   "Perspective",
   "ZIndex",
   "TransformOrigin",
 ]
 item_types = ["enums", "structs", "typedefs"]
 
 [export.body]
@@ -180,8 +183,12 @@ item_types = ["enums", "structs", "typed
   // Defined in WritingModes.h
   inline const T& Get(mozilla::Side) const;
   inline const T& Get(mozilla::WritingMode, mozilla::LogicalSide) const;
   inline const T& GetIStart(mozilla::WritingMode) const;
   inline const T& GetBStart(mozilla::WritingMode) const;
   inline const T& GetIEnd(mozilla::WritingMode) const;
   inline const T& GetBEnd(mozilla::WritingMode) const;
 """
+
+"GenericBorderRadius" = """
+  inline const StyleLengthPercentage& Get(mozilla::HalfCorner) const;
+"""
--- a/servo/components/style/gecko/conversions.rs
+++ b/servo/components/style/gecko/conversions.rs
@@ -570,38 +570,34 @@ impl nsStyleImage {
         })
     }
 }
 
 pub mod basic_shape {
     //! Conversions from and to CSS shape representations.
 
     use crate::gecko::values::GeckoStyleCoordConvertible;
-    use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCorners};
+    use crate::gecko_bindings::structs::nsStyleCoord;
     use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType};
     use crate::gecko_bindings::structs::{
         StyleGeometryBox, StyleShapeSource, StyleShapeSourceType,
     };
-    use crate::gecko_bindings::sugar::ns_style_coord::{CoordDataMut, CoordDataValue};
     use crate::gecko_bindings::sugar::refptr::RefPtr;
     use crate::values::computed::basic_shape::{
         BasicShape, ClippingShape, FloatAreaShape, ShapeRadius,
     };
-    use crate::values::computed::border::{BorderCornerRadius, BorderRadius};
     use crate::values::computed::length::LengthPercentage;
     use crate::values::computed::motion::OffsetPath;
     use crate::values::computed::url::ComputedUrl;
     use crate::values::generics::basic_shape::{
         BasicShape as GenericBasicShape, InsetRect, Polygon,
     };
     use crate::values::generics::basic_shape::{Circle, Ellipse, Path, PolygonCoord};
     use crate::values::generics::basic_shape::{GeometryBox, ShapeBox, ShapeSource};
-    use crate::values::generics::border::BorderRadius as GenericBorderRadius;
     use crate::values::generics::rect::Rect;
-    use crate::values::generics::NonNegative;
     use crate::values::specified::SVGPathData;
     use std::borrow::Borrow;
 
     impl StyleShapeSource {
         /// Convert StyleShapeSource to ShapeSource except URL and Image
         /// types.
         fn into_shape_source<ReferenceBox, ImageOrUrl>(
             &self,
@@ -701,17 +697,17 @@ pub mod basic_shape {
     impl<'a> From<&'a StyleBasicShape> for BasicShape {
         fn from(other: &'a StyleBasicShape) -> Self {
             match other.mType {
                 StyleBasicShapeType::Inset => {
                     let t = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[0]);
                     let r = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[1]);
                     let b = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[2]);
                     let l = LengthPercentage::from_gecko_style_coord(&other.mCoordinates[3]);
-                    let round: BorderRadius = (&other.mRadius).into();
+                    let round = other.mRadius;
                     let round = if round.all_zero() { None } else { Some(round) };
                     let rect = Rect::new(
                         t.expect("inset() offset should be a length, percentage, or calc value"),
                         r.expect("inset() offset should be a length, percentage, or calc value"),
                         b.expect("inset() offset should be a length, percentage, or calc value"),
                         l.expect("inset() offset should be a length, percentage, or calc value"),
                     );
                     GenericBasicShape::Inset(InsetRect { rect, round })
@@ -747,75 +743,16 @@ pub mod basic_shape {
                         fill: other.mFillRule,
                         coordinates: coords,
                     })
                 },
             }
         }
     }
 
-    impl<'a> From<&'a nsStyleCorners> for BorderRadius {
-        fn from(other: &'a nsStyleCorners) -> Self {
-            let get_corner = |index| {
-                BorderCornerRadius::new(
-                    NonNegative(
-                        LengthPercentage::from_gecko_style_coord(&other.data_at(index)).expect(
-                            "<border-radius> should be a length, percentage, or calc value",
-                        ),
-                    ),
-                    NonNegative(
-                        LengthPercentage::from_gecko_style_coord(&other.data_at(index + 1)).expect(
-                            "<border-radius> should be a length, percentage, or calc value",
-                        ),
-                    ),
-                )
-            };
-
-            GenericBorderRadius {
-                top_left: get_corner(0),
-                top_right: get_corner(2),
-                bottom_right: get_corner(4),
-                bottom_left: get_corner(6),
-            }
-        }
-    }
-
-    // Can't be a From impl since we need to set an existing
-    // nsStyleCorners, not create a new one
-    impl BorderRadius {
-        /// Set this `BorderRadius` into a given `nsStyleCoord`.
-        pub fn set_corners(&self, other: &mut nsStyleCorners) {
-            let mut set_corner = |field: &BorderCornerRadius, index| {
-                field
-                    .0
-                    .width()
-                    .to_gecko_style_coord(&mut other.data_at_mut(index));
-                field
-                    .0
-                    .height()
-                    .to_gecko_style_coord(&mut other.data_at_mut(index + 1));
-            };
-            set_corner(&self.top_left, 0);
-            set_corner(&self.top_right, 2);
-            set_corner(&self.bottom_right, 4);
-            set_corner(&self.bottom_left, 6);
-        }
-    }
-
-    /// We use None for a nonexistant radius, but Gecko uses (0 0 0 0 / 0 0 0 0)
-    pub fn set_corners_from_radius(radius: Option<BorderRadius>, other: &mut nsStyleCorners) {
-        if let Some(radius) = radius {
-            radius.set_corners(other);
-        } else {
-            for i in 0..8 {
-                other.data_at_mut(i).set_value(CoordDataValue::Coord(0));
-            }
-        }
-    }
-
     impl<'a> From<&'a nsStyleCoord> for ShapeRadius {
         fn from(other: &'a nsStyleCoord) -> Self {
             let other = other.borrow();
             ShapeRadius::from_gecko_style_coord(other)
                 .expect("<shape-radius> should be a length, percentage, calc, or keyword value")
         }
     }
 
--- a/servo/components/style/gecko_bindings/sugar/ns_style_coord.rs
+++ b/servo/components/style/gecko_bindings/sugar/ns_style_coord.rs
@@ -1,17 +1,17 @@
 /* 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 https://mozilla.org/MPL/2.0/. */
 
 //! Rust helpers for Gecko's `nsStyleCoord`.
 
 use crate::gecko_bindings::bindings;
 use crate::gecko_bindings::structs::{nsStyleCoord, nsStyleCoord_Calc, nsStyleCoord_CalcValue};
-use crate::gecko_bindings::structs::{nsStyleCorners, nsStyleSides};
+use crate::gecko_bindings::structs::nsStyleSides;
 use crate::gecko_bindings::structs::{nsStyleUnion, nsStyleUnit, nscoord};
 use std::mem;
 
 impl nsStyleCoord {
     #[inline]
     /// Get a `null` nsStyleCoord.
     pub fn null() -> Self {
         // Can't construct directly because it has private fields
@@ -118,74 +118,16 @@ unsafe impl<'a> CoordData for SidesDataM
 unsafe impl<'a> CoordDataMut for SidesDataMut<'a> {
     unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) {
         let unit = &mut self.sides.get_mUnits_mut()[self.index] as *mut _;
         let value = &mut self.sides.get_mValues_mut()[self.index] as *mut _;
         (&mut *unit, &mut *value)
     }
 }
 
-impl nsStyleCorners {
-    /// Get a `nsStyleCoord` like object representing the given index's value
-    /// and unit.
-    #[inline]
-    pub fn data_at(&self, index: usize) -> CornersData {
-        CornersData {
-            corners: self,
-            index: index,
-        }
-    }
-
-    /// Get a `nsStyleCoord` like object representing the mutable given index's
-    /// value and unit.
-    #[inline]
-    pub fn data_at_mut(&mut self, index: usize) -> CornersDataMut {
-        CornersDataMut {
-            corners: self,
-            index: index,
-        }
-    }
-}
-
-/// A `nsStyleCoord`-like struct on top of `nsStyleCorners`.
-pub struct CornersData<'a> {
-    corners: &'a nsStyleCorners,
-    index: usize,
-}
-
-/// A `nsStyleCoord`-like struct on top of a mutable `nsStyleCorners` reference.
-pub struct CornersDataMut<'a> {
-    corners: &'a mut nsStyleCorners,
-    index: usize,
-}
-
-unsafe impl<'a> CoordData for CornersData<'a> {
-    fn unit(&self) -> nsStyleUnit {
-        unsafe { self.corners.get_mUnits()[self.index] }
-    }
-    fn union(&self) -> nsStyleUnion {
-        unsafe { self.corners.get_mValues()[self.index] }
-    }
-}
-unsafe impl<'a> CoordData for CornersDataMut<'a> {
-    fn unit(&self) -> nsStyleUnit {
-        unsafe { self.corners.get_mUnits()[self.index] }
-    }
-    fn union(&self) -> nsStyleUnion {
-        unsafe { self.corners.get_mValues()[self.index] }
-    }
-}
-unsafe impl<'a> CoordDataMut for CornersDataMut<'a> {
-    unsafe fn values_mut(&mut self) -> (&mut nsStyleUnit, &mut nsStyleUnion) {
-        let unit = &mut self.corners.get_mUnits_mut()[self.index] as *mut _;
-        let value = &mut self.corners.get_mValues_mut()[self.index] as *mut _;
-        (&mut *unit, &mut *value)
-    }
-}
-
 /// Enum representing the tagged union that is CoordData.
 ///
 /// In release mode this should never actually exist in the code, and will be
 /// optimized out by threading matches and inlining.
 #[derive(Clone, Copy, Debug, PartialEq)]
 pub enum CoordDataValue {
     /// eStyleUnit_Null
     Null,
--- a/servo/components/style/properties/gecko.mako.rs
+++ b/servo/components/style/properties/gecko.mako.rs
@@ -47,17 +47,17 @@ use crate::gecko::values::round_border_t
 use crate::logical_geometry::WritingMode;
 use crate::media_queries::Device;
 use crate::properties::computed_value_flags::*;
 use crate::properties::longhands;
 use crate::rule_tree::StrongRuleNode;
 use crate::selector_parser::PseudoElement;
 use servo_arc::{Arc, RawOffsetArc};
 use std::marker::PhantomData;
-use std::mem::{forget, uninitialized, transmute, zeroed};
+use std::mem::{forget, uninitialized, zeroed};
 use std::{cmp, ops, ptr};
 use crate::values::{self, CustomIdent, Either, KeyframesName, None_};
 use crate::values::computed::{NonNegativeLength, Percentage, TransitionProperty};
 use crate::values::computed::BorderStyle;
 use crate::values::computed::font::FontSize;
 use crate::values::computed::effects::{BoxShadow, Filter, SimpleShadow};
 use crate::values::generics::column::ColumnCount;
 use crate::values::generics::transform::TransformStyle;
@@ -812,44 +812,33 @@ def set_gecko_property(ffi_name, expr):
     }
 
     #[allow(non_snake_case)]
     pub fn reset_${ident}(&mut self, other: &Self) {
         self.copy_${ident}_from(other)
     }
 </%def>
 
-<%def name="impl_corner_style_coord(ident, gecko_ffi_name, x_index, y_index)">
+<%def name="impl_corner_style_coord(ident, gecko_ffi_name, corner)">
     #[allow(non_snake_case)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
-        v.0.width().to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${x_index}));
-        v.0.height().to_gecko_style_coord(&mut self.gecko.${gecko_ffi_name}.data_at_mut(${y_index}));
+        self.gecko.${gecko_ffi_name}.${corner} = v;
     }
     #[allow(non_snake_case)]
     pub fn copy_${ident}_from(&mut self, other: &Self) {
-        self.gecko.${gecko_ffi_name}.data_at_mut(${x_index})
-                  .copy_from(&other.gecko.${gecko_ffi_name}.data_at(${x_index}));
-        self.gecko.${gecko_ffi_name}.data_at_mut(${y_index})
-                  .copy_from(&other.gecko.${gecko_ffi_name}.data_at(${y_index}));
+        self.gecko.${gecko_ffi_name}.${corner} =
+            other.gecko.${gecko_ffi_name}.${corner};
     }
     #[allow(non_snake_case)]
     pub fn reset_${ident}(&mut self, other: &Self) {
         self.copy_${ident}_from(other)
     }
-
     #[allow(non_snake_case)]
     pub fn clone_${ident}(&self) -> longhands::${ident}::computed_value::T {
-        use crate::values::computed::border::BorderCornerRadius;
-        let width = GeckoStyleCoordConvertible::from_gecko_style_coord(
-                        &self.gecko.${gecko_ffi_name}.data_at(${x_index}))
-                        .expect("Failed to clone ${ident}");
-        let height = GeckoStyleCoordConvertible::from_gecko_style_coord(
-                        &self.gecko.${gecko_ffi_name}.data_at(${y_index}))
-                        .expect("Failed to clone ${ident}");
-        BorderCornerRadius::new(width, height)
+        self.gecko.${gecko_ffi_name}.${corner}
     }
 </%def>
 
 <%def name="impl_css_url(ident, gecko_ffi_name)">
     #[allow(non_snake_case)]
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         match v {
             UrlOrNone::Url(ref url) => {
@@ -1382,55 +1371,40 @@ impl ${style_struct.gecko_struct_name} {
 
 <%!
 class Side(object):
     def __init__(self, name, index):
         self.name = name
         self.ident = name.lower()
         self.index = index
 
-class Corner(object):
-    def __init__(self, vert, horiz, index):
-        self.x_name = "HalfCorner::eCorner" + vert + horiz + "X"
-        self.y_name = "HalfCorner::eCorner" + vert + horiz + "Y"
-        self.ident = (vert + "_" + horiz).lower()
-        self.x_index = 2 * index
-        self.y_index = 2 * index + 1
-
 class GridLine(object):
     def __init__(self, name):
         self.ident = "grid-" + name.lower()
         self.name = self.ident.replace('-', '_')
         self.gecko = "m" + to_camel_case(self.ident)
 
 SIDES = [Side("Top", 0), Side("Right", 1), Side("Bottom", 2), Side("Left", 3)]
-CORNERS = [Corner("Top", "Left", 0), Corner("Top", "Right", 1),
-           Corner("Bottom", "Right", 2), Corner("Bottom", "Left", 3)]
+CORNERS = ["top_left", "top_right", "bottom_right", "bottom_left"]
 GRID_LINES = map(GridLine, ["row-start", "row-end", "column-start", "column-end"])
 %>
 
 #[allow(dead_code)]
 fn static_assert() {
-    unsafe {
-        % for corner in CORNERS:
-        transmute::<_, [u32; ${corner.x_index}]>([1; structs::${corner.x_name} as usize]);
-        transmute::<_, [u32; ${corner.y_index}]>([1; structs::${corner.y_name} as usize]);
-        % endfor
-    }
     // Note: using the above technique with an enum hits a rust bug when |structs| is in a different crate.
     % for side in SIDES:
     { const DETAIL: u32 = [0][(structs::Side::eSide${side.name} as usize != ${side.index}) as usize]; let _ = DETAIL; }
     % endfor
 }
 
 
 <% skip_border_longhands = " ".join(["border-{0}-{1}".format(x.ident, y)
                                      for x in SIDES
                                      for y in ["color", "style", "width"]] +
-                                    ["border-{0}-radius".format(x.ident.replace("_", "-"))
+                                    ["border-{0}-radius".format(x.replace("_", "-"))
                                      for x in CORNERS]) %>
 
 <%self:impl_trait style_struct_name="Border"
                   skip_longhands="${skip_border_longhands} border-image-source
                                   border-image-repeat border-image-width">
     % for side in SIDES:
     pub fn set_border_${side.ident}_style(&mut self, v: BorderStyle) {
         self.gecko.mBorderStyle[${side.index}] = v;
@@ -1489,20 +1463,19 @@ fn static_assert() {
                                 round_to_pixels=True) %>
 
     pub fn border_${side.ident}_has_nonzero_width(&self) -> bool {
         self.gecko.mComputedBorder.${side.ident} != 0
     }
     % endfor
 
     % for corner in CORNERS:
-    <% impl_corner_style_coord("border_%s_radius" % corner.ident,
+    <% impl_corner_style_coord("border_%s_radius" % corner,
                                "mBorderRadius",
-                               corner.x_index,
-                               corner.y_index) %>
+                               corner) %>
     % endfor
 
     pub fn set_border_image_source(&mut self, image: longhands::border_image_source::computed_value::T) {
         unsafe {
             // Prevent leaking of the last elements we did set
             Gecko_SetNullImageValue(&mut self.gecko.mBorderImageSource);
         }
 
@@ -2022,17 +1995,17 @@ fn static_assert() {
         };
 
         Either::First(TemplateAreasArc(Arc::new(TemplateAreas{ areas, strings, width })))
     }
 
 </%self:impl_trait>
 
 <% skip_outline_longhands = " ".join("outline-style outline-width".split() +
-                                     ["-moz-outline-radius-{0}".format(x.ident.replace("_", ""))
+                                     ["-moz-outline-radius-{0}".format(x.replace("_", ""))
                                       for x in CORNERS]) %>
 <%self:impl_trait style_struct_name="Outline"
                   skip_longhands="${skip_outline_longhands}">
 
     pub fn set_outline_style(&mut self, v: longhands::outline_style::computed_value::T) {
         self.gecko.mOutlineStyle = v;
         // NB: This is needed to correctly handling the initial value of
         // outline-width when outline-style changes, see the
@@ -2054,20 +2027,19 @@ fn static_assert() {
         self.gecko.mOutlineStyle.clone()
     }
 
     <% impl_non_negative_length("outline_width", "mActualOutlineWidth",
                                 inherit_from="mOutlineWidth",
                                 round_to_pixels=True) %>
 
     % for corner in CORNERS:
-    <% impl_corner_style_coord("_moz_outline_radius_%s" % corner.ident.replace("_", ""),
+    <% impl_corner_style_coord("_moz_outline_radius_%s" % corner.replace("_", ""),
                                "mOutlineRadius",
-                               corner.x_index,
-                               corner.y_index) %>
+                               corner) %>
     % endfor
 
     pub fn outline_has_nonzero_width(&self) -> bool {
         self.gecko.mActualOutlineWidth != 0
     }
 </%self:impl_trait>
 
 <%
@@ -4588,17 +4560,16 @@ fn set_style_svg_path(
     gecko_path.mFillRule = fill;
 }
 
 <%def name="impl_shape_source(ident, gecko_ffi_name)">
     pub fn set_${ident}(&mut self, v: longhands::${ident}::computed_value::T) {
         use crate::gecko_bindings::bindings::{Gecko_NewBasicShape, Gecko_DestroyShapeSource};
         use crate::gecko_bindings::structs::{StyleBasicShape, StyleBasicShapeType, StyleShapeSourceType};
         use crate::gecko_bindings::structs::{StyleGeometryBox, StyleShapeSource};
-        use crate::gecko::conversions::basic_shape::set_corners_from_radius;
         use crate::gecko::values::GeckoStyleCoordConvertible;
         use crate::values::generics::basic_shape::{BasicShape, ShapeSource};
 
         let ref mut ${ident} = self.gecko.${gecko_ffi_name};
 
         // clean up existing struct
         unsafe { Gecko_DestroyShapeSource(${ident}) };
         ${ident}.mType = StyleShapeSourceType::None;
@@ -4653,18 +4624,20 @@ fn set_style_svg_path(
                         shape.mCoordinates[0].leaky_set_null();
                         inset.rect.0.to_gecko_style_coord(&mut shape.mCoordinates[0]);
                         shape.mCoordinates[1].leaky_set_null();
                         inset.rect.1.to_gecko_style_coord(&mut shape.mCoordinates[1]);
                         shape.mCoordinates[2].leaky_set_null();
                         inset.rect.2.to_gecko_style_coord(&mut shape.mCoordinates[2]);
                         shape.mCoordinates[3].leaky_set_null();
                         inset.rect.3.to_gecko_style_coord(&mut shape.mCoordinates[3]);
-
-                        set_corners_from_radius(inset.round, &mut shape.mRadius);
+                        shape.mRadius = match inset.round {
+                            Some(radius) => radius,
+                            None => crate::values::computed::BorderRadius::zero(),
+                        };
                     }
                     BasicShape::Circle(circ) => {
                         let shape = init_shape(${ident}, StyleBasicShapeType::Circle);
                         unsafe { shape.mCoordinates.set_len(1) };
                         shape.mCoordinates[0].leaky_set_null();
                         circ.radius.to_gecko_style_coord(&mut shape.mCoordinates[0]);
 
                         shape.mPosition = circ.position.into();
--- a/servo/components/style/values/computed/border.rs
+++ b/servo/components/style/values/computed/border.rs
@@ -82,16 +82,26 @@ impl BorderCornerRadius {
         GenericBorderCornerRadius(Size2D::new(
             NonNegativeLengthPercentage::zero(),
             NonNegativeLengthPercentage::zero(),
         ))
     }
 }
 
 impl BorderRadius {
+    /// Returns a `0` border radius.
+    pub fn zero() -> Self {
+        Self {
+            top_left: BorderCornerRadius::zero(),
+            top_right: BorderCornerRadius::zero(),
+            bottom_right: BorderCornerRadius::zero(),
+            bottom_left: BorderCornerRadius::zero(),
+        }
+    }
+
     /// Returns whether all the values are `0px`.
     pub fn all_zero(&self) -> bool {
         fn all(corner: &BorderCornerRadius) -> bool {
             fn is_zero(l: &NonNegativeLengthPercentage) -> bool {
                 *l == NonNegativeLengthPercentage::zero()
             }
             is_zero(corner.0.width()) && is_zero(corner.0.height())
         }
--- a/servo/components/style/values/generics/border.rs
+++ b/servo/components/style/values/generics/border.rs
@@ -48,17 +48,20 @@ pub use self::GenericBorderImageSlice as
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
 )]
-pub struct BorderCornerRadius<L>(#[css(field_bound)] pub Size2D<L>);
+#[repr(C)]
+pub struct GenericBorderCornerRadius<L>(#[css(field_bound)] pub Size2D<L>);
+
+pub use self::GenericBorderCornerRadius as BorderCornerRadius;
 
 impl<L> BorderCornerRadius<L> {
     /// Trivially create a `BorderCornerRadius`.
     pub fn new(w: L, h: L) -> Self {
         BorderCornerRadius(Size2D::new(w, h))
     }
 }
 
@@ -72,16 +75,17 @@ impl<L> BorderCornerRadius<L> {
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToAnimatedZero,
     ToComputedValue,
     ToCss,
 )]
+#[repr(transparent)]
 pub struct BorderSpacing<L>(#[css(field_bound)] pub Size2D<L>);
 
 impl<L> BorderSpacing<L> {
     /// Trivially create a `BorderCornerRadius`.
     pub fn new(w: L, h: L) -> Self {
         BorderSpacing(Size2D::new(w, h))
     }
 }
@@ -96,27 +100,30 @@ impl<L> BorderSpacing<L> {
     Copy,
     Debug,
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedValue,
     ToComputedValue,
 )]
-pub struct BorderRadius<LengthPercentage> {
+#[repr(C)]
+pub struct GenericBorderRadius<LengthPercentage> {
     /// The top left radius.
-    pub top_left: BorderCornerRadius<LengthPercentage>,
+    pub top_left: GenericBorderCornerRadius<LengthPercentage>,
     /// The top right radius.
-    pub top_right: BorderCornerRadius<LengthPercentage>,
+    pub top_right: GenericBorderCornerRadius<LengthPercentage>,
     /// The bottom right radius.
-    pub bottom_right: BorderCornerRadius<LengthPercentage>,
+    pub bottom_right: GenericBorderCornerRadius<LengthPercentage>,
     /// The bottom left radius.
-    pub bottom_left: BorderCornerRadius<LengthPercentage>,
+    pub bottom_left: GenericBorderCornerRadius<LengthPercentage>,
 }
 
+pub use self::GenericBorderRadius as BorderRadius;
+
 impl<L> BorderRadius<L> {
     /// Returns a new `BorderRadius<L>`.
     #[inline]
     pub fn new(
         tl: BorderCornerRadius<L>,
         tr: BorderCornerRadius<L>,
         br: BorderCornerRadius<L>,
         bl: BorderCornerRadius<L>,
--- a/servo/components/style/values/generics/size.rs
+++ b/servo/components/style/values/generics/size.rs
@@ -20,16 +20,17 @@ use style_traits::{CssWriter, ParseError
     MallocSizeOf,
     PartialEq,
     SpecifiedValueInfo,
     ToAnimatedZero,
     ToAnimatedValue,
     ToComputedValue,
 )]
 #[allow(missing_docs)]
+#[repr(C)]
 pub struct Size2D<L> {
     pub width: L,
     pub height: L,
 }
 
 impl<L> Size2D<L> {
     #[inline]
     /// Create a new `Size2D` for an area of given width and height.
--- a/servo/ports/geckolib/glue.rs
+++ b/servo/ports/geckolib/glue.rs
@@ -3698,16 +3698,25 @@ pub unsafe extern "C" fn Servo_Serialize
     output: *mut nsAString,
 ) {
     easing
         .mTiming
         .to_css(&mut CssWriter::new(&mut *output))
         .unwrap();
 }
 
+
+#[no_mangle]
+pub unsafe extern "C" fn Servo_SerializeBorderRadius(
+    radius: *const computed::BorderRadius,
+    output: *mut nsAString,
+) {
+    (*radius).to_css(&mut CssWriter::new(&mut *output)).unwrap();
+}
+
 #[no_mangle]
 pub extern "C" fn Servo_GetProperties_Overriding_Animation(
     element: RawGeckoElementBorrowed,
     list: RawGeckoCSSPropertyIDListBorrowed,
     set: nsCSSPropertyIDSetBorrowedMut,
 ) {
     let element = GeckoElement(element);
     let element_data = match element.borrow_data() {
--- a/taskcluster/ci/test/raptor.yml
+++ b/taskcluster/ci/test/raptor.yml
@@ -448,17 +448,17 @@ raptor-speedometer-geckoview-power:
 raptor-speedometer-fennec:
     description: "Raptor Speedometer on Fennec"
     try-name: raptor-speedometer-fennec
     treeherder-symbol: Rap(sp)
     target: target.apk
     run-on-projects:
         by-test-platform:
             android-hw.*: ['try', 'trunk', 'mozilla-beta']
-    tier: 3
+    tier: 2
     max-run-time: 900
     mozharness:
         extra-options:
             - --test=raptor-speedometer-fennec
             - --app=fennec
             - --binary=org.mozilla.fennec_aurora
 
 raptor-speedometer-chrome:
--- a/testing/mozbase/mozlog/mozlog/formatters/html/html.py
+++ b/testing/mozbase/mozlog/mozlog/formatters/html/html.py
@@ -71,18 +71,18 @@ class HTMLFormatter(base.BaseFormatter):
             self.env["Gecko version"] = version_info.get("application_version")
             self.env["Gecko build"] = version_info.get("application_buildid")
 
             if version_info.get("application_changeset"):
                 self.env["Gecko revision"] = version_info.get("application_changeset")
                 if version_info.get("application_repository"):
                     self.env["Gecko revision"] = html.a(
                         version_info.get("application_changeset"),
-                        href="/".join([version_info.get("application_repository"),
-                                       version_info.get("application_changeset")]),
+                        href="/rev/".join([version_info.get("application_repository"),
+                                           version_info.get("application_changeset")]),
                         target="_blank")
 
             if version_info.get("gaia_changeset"):
                 self.env["Gaia revision"] = html.a(
                     version_info.get("gaia_changeset")[:12],
                     href="https://github.com/mozilla-b2g/gaia/commit/%s" % version_info.get(
                         "gaia_changeset"),
                     target="_blank")
--- a/testing/raptor/test/test_manifest.py
+++ b/testing/raptor/test/test_manifest.py
@@ -121,27 +121,24 @@ def test_get_raptor_test_list_chrome(cre
     args = create_args(app="chrome",
                        test="raptor-speedometer")
 
     test_list = get_raptor_test_list(args, mozinfo.os)
     assert len(test_list) == 1
     assert test_list[0]['name'] == 'raptor-speedometer-chrome'
 
 
-# Commented test_get_raptor_test_list_geckoview
-# in order to disable raptor-unity-webgl-geckoview - Bug 1524495
-"""
- def test_get_raptor_test_list_geckoview(create_args):
-    args = create_args(app="geckoview",
-                         test="raptor-unity-webgl")
-
-    test_list = get_raptor_test_list(args, mozinfo.os)
-    assert len(test_list) == 1
-    assert test_list[0]['name'] == 'raptor-unity-webgl-geckoview'
-"""
+def test_get_raptor_test_list_geckoview(create_args):
+    return
+#   args = create_args(app="geckoview",
+#                      test="raptor-unity-webgl")
+#
+#   test_list = get_raptor_test_list(args, mozinfo.os)
+#   assert len(test_list) == 1
+#   assert test_list[0]['name'] == 'raptor-unity-webgl-geckoview'
 
 
 def test_get_raptor_test_list_gecko_profiling(create_args):
     args = create_args(test="raptor-tp6-google-firefox",
                        gecko_profile=True)
 
     test_list = get_raptor_test_list(args, mozinfo.os)
     assert len(test_list) == 1
deleted file mode 100644
--- a/testing/web-platform/meta/css/css-shapes/shape-outside/values/shape-outside-inset-006.html.ini
+++ /dev/null
@@ -1,22 +0,0 @@
-[shape-outside-inset-006.html]
-  [inset(10px round 10.1200px 20.34px 30.56px 40.780px) - computed]
-    expected: FAIL
-
-  [inset(10px round 10.123px 20.00px 30.10px 40.5678px) - computed]
-    expected: FAIL
-
-  [inset(10px round +10.1200px +20.340px +30.56px +40.780px) - computed]
-    expected: FAIL
-
-  [inset(10px round 10.1200px 20.34px 30.56px 40.780px / 10.1200px 20.34px 30.56px 40.780px) - computed]
-    expected: FAIL
-
-  [inset(10px round 10.123px 20.00px 30.10px 40.5678px / 10.123px 20.00px 30.10px 40.5678px) - computed]
-    expected: FAIL
-
-  [inset(10px round +10.1200px +20.340px +30.56px +40.780px / +10.1200px +20.340px +30.56px +40.780px) - computed]
-    expected: FAIL
-
-  [inset(10px round +10.123px +20.00px +30.10px +40.5678px / 10.123px +20.00px +30.10px +40.5678px) - computed]
-    expected: FAIL
-
--- a/testing/webdriver/src/command.rs
+++ b/testing/webdriver/src/command.rs
@@ -444,16 +444,19 @@ pub enum NewSessionParameters {
 
 impl<'de> Deserialize<'de> for NewSessionParameters {
     fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
     where
         D: Deserializer<'de>,
     {
         let value = serde_json::Value::deserialize(deserializer)?;
         if let Some(caps) = value.get("capabilities") {
+            if !caps.is_object() {
+                return Err(de::Error::custom("capabilities must be objects"));
+            }
             let caps = SpecNewSessionParameters::deserialize(caps).map_err(de::Error::custom)?;
             return Ok(NewSessionParameters::Spec(caps));
         }
 
         warn!("You are using deprecated legacy session negotiation patterns (desiredCapabilities/requiredCapabilities), see https://developer.mozilla.org/en-US/docs/Web/WebDriver/Capabilities#Legacy");
         let legacy = LegacyNewSessionParameters::deserialize(value).map_err(de::Error::custom)?;
         Ok(NewSessionParameters::Legacy(legacy))
     }
--- a/toolkit/components/extensions/ExtensionStorageSync.jsm
+++ b/toolkit/components/extensions/ExtensionStorageSync.jsm
@@ -1052,17 +1052,17 @@ class ExtensionStorageSync {
       }
       // No conflicts, or conflict was just someone else adding keys.
       return result;
     } catch (e) {
       if (KeyRingEncryptionRemoteTransformer.isOutdatedKB(e) ||
           e instanceof ServerKeyringDeleted ||
           // This is another way that ServerKeyringDeleted can
           // manifest; see bug 1350088 for more details.
-          e.message == "Server has been flushed.") {
+          e.message.includes("Server has been flushed.")) {
         // Check if our token is still valid, or if we got locked out
         // between starting the sync and talking to Kinto.
         const isSessionValid = await this._fxaService.sessionStatus();
         if (isSessionValid) {
           log.error("Couldn't decipher old keyring; deleting the default bucket and resetting sync status");
           await this._deleteBucket();
           await this.cryptoCollection.resetSyncStatus();
 
--- a/toolkit/components/telemetry/Scalars.yaml
+++ b/toolkit/components/telemetry/Scalars.yaml
@@ -501,16 +501,29 @@ contentblocking:
     expires: never
     kind: boolean
     notification_emails:
       - aedelstein@mozilla.com
       - seceng-telemetry@mozilla.com
     release_channel_collection: opt-out
     record_in_processes:
       - main
+  category:
+    bug_numbers:
+      - 1529425
+    description: >
+      This scalar reports the value of the content blocking category pref (0 = "standard", 1 = "strict", 2 = "custom", 3 = some other value, this is not supported).
+    expires: never
+    kind: uint
+    notification_emails:
+      - aedelstein@mozilla.com
+      - seceng-telemetry@mozilla.com
+    release_channel_collection: opt-out
+    record_in_processes:
+      - main
 
 sandbox:
   no_job:
     bug_numbers:
       - 1392570
     description: >
       Indicates that we can't use a job object for sandboxed child processes.
       Keyed by whether we are in a remote session or not from ::GetSystemMetrics(SM_REMOTESESSION).
--- a/toolkit/components/utils/JsonSchemaValidator.jsm
+++ b/toolkit/components/utils/JsonSchemaValidator.jsm
@@ -151,16 +151,32 @@ function validateAndParseParamRecursive(
           if (!valid) {
             return [false, null];
           }
           parsedObj[item] = parsedValue;
         }
       }
       return [true, parsedObj];
     }
+
+    case "JSON":
+      if (typeof(param) == "object") {
+        return [true, param];
+      }
+      try {
+        let json = JSON.parse(param);
+        if (typeof(json) != "object") {
+          log.error("JSON was not an object");
+          return [false, null];
+        }
+        return [true, json];
+      } catch (e) {
+        log.error("JSON string couldn't be parsed");
+        return [false, null];
+      }
   }
 
   return [false, null];
 }
 
 function validateAndParseSimpleParam(param, type) {
   let valid = false;
   let parsedParam = param;
--- a/toolkit/components/utils/test/browser/browser_JsonSchemaValidator.js
+++ b/toolkit/components/utils/test/browser/browser_JsonSchemaValidator.js
@@ -442,8 +442,49 @@ add_task(async function test_patternProp
       "[": {" type": "string" },
     },
   };
 
   Assert.throws(() => {
     [valid, parsed] = JsonSchemaValidator.validateAndParseParameters({}, schema);
   }, /Invalid property pattern/, "Checking that invalid property patterns throw");
 });
+
+add_task(async function test_JSON_type() {
+  let schema = {
+    type: "JSON",
+  };
+
+  let valid, parsed;
+  [valid, parsed] = JsonSchemaValidator.validateAndParseParameters({
+    "a": "b",
+  }, schema);
+
+  ok(valid, "Object is valid");
+  ok(typeof(parsed) == "object", "parsed in an object");
+  is(parsed.a, "b", "parsedProperty is correct");
+
+  [valid, parsed] = JsonSchemaValidator.validateAndParseParameters(
+    "{\"a\": \"b\"}"
+  , schema);
+
+  ok(valid, "Object is valid");
+  ok(typeof(parsed) == "object", "parsed in an object");
+  is(parsed.a, "b", "parsedProperty is correct");
+
+  [valid, parsed] = JsonSchemaValidator.validateAndParseParameters(
+    "{This{is{not{JSON}}}}"
+  , schema);
+
+  ok(!valid, "Object is not valid since JSON was incorrect");
+
+  [valid, parsed] = JsonSchemaValidator.validateAndParseParameters(
+    "0"
+  , schema);
+
+  ok(!valid, "Object is not valid since input wasn't an object");
+
+  [valid, parsed] = JsonSchemaValidator.validateAndParseParameters(
+    "true"
+  , schema);
+
+  ok(!valid, "Object is not valid since input wasn't an object");
+});
--- a/toolkit/content/tests/chrome/test_labelcontrol.xul
+++ b/toolkit/content/tests/chrome/test_labelcontrol.xul
@@ -5,39 +5,48 @@
   XUL Widget Test for label control="value"
   -->
 <window title="tabindex" width="500" height="600"
         onload="runTests()"
         xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>  
   <script type="application/javascript" src="chrome://mochikit/content/tests/SimpleTest/EventUtils.js"></script>  
 
-<label id="lab" control="ctl"/>
-<textbox id="ctl" value="Test"/>
-<checkbox id="chk" value="Checkbox"/>
+<label id="textbox-label" control="textbox" />
+<textbox id="textbox" value="Test"/>
+<label id="checkbox-label" control="checkbox" />
+<checkbox id="checkbox" value="Checkbox"/>
 
 <body xmlns="http://www.w3.org/1999/xhtml">
 <p id="display"></p>
 <div id="content" style="display: none">
 </div>
 <pre id="test">
 </pre>
 </body>
 
 <script>
 <![CDATA[
 
 SimpleTest.waitForExplicitFinish();
  
 function runTests()
 {
-  is($("lab").control, "ctl", "control");
-  is($("lab").labeledControlElement, $("ctl"), "labeledControlElement");
-  is($("ctl").labelElement, $("lab"), "labelElement");
-  is($("chk").labelElement.className, "checkbox-label", "labelElement");
+  let textbox = $("textbox");
+  let textboxLabel = $("textbox-label");
+  is(textboxLabel.control, "textbox", "textbox control");
+  is(textboxLabel.labeledControlElement, textbox, "textbox labeledControlElement");
+
+  let checkbox = $("checkbox");
+  let checkboxLabel = $("checkbox-label");
+  is(checkboxLabel.control, "checkbox", "checkbox control");
+  is(checkboxLabel.labeledControlElement, checkbox, "checkbox labeledControlElement");
+  is(checkbox.accessKey, "", "checkbox accessKey not set");
+  checkboxLabel.accessKey = "C";
+  is(checkbox.accessKey, "C", "checkbox accessKey set");
 
   SimpleTest.finish();
 }
 
 ]]>
 
 </script>
 
--- a/toolkit/content/widgets/general.xml
+++ b/toolkit/content/widgets/general.xml
@@ -31,30 +31,29 @@
                                   onget="return this.getAttribute('crop');"/>
       <property name="image"      onset="this.setAttribute('image',val); return val;"
                                   onget="return this.getAttribute('image');"/>
       <property name="command"    onset="this.setAttribute('command',val); return val;"
                                   onget="return this.getAttribute('command');"/>
       <property name="accessKey">
         <getter>
           <![CDATA[
-            return this.labelElement ? this.labelElement.accessKey : this.getAttribute("accesskey");
+            return this.getAttribute("accesskey");
           ]]>
         </getter>
         <setter>
           <![CDATA[
             // Always store on the control
             this.setAttribute("accesskey", val);
             // If there is a label, change the accesskey on the labelElement
             // if it's also set there
-            if (this.labelElement) {
-              this.labelElement.accessKey = val;
+            let labelElement = document.getElementsByAttribute("control", this.id)[0];
+            if (labelElement) {
+              labelElement.setAttribute("accesskey", val);
             }
             return val;
           ]]>
         </setter>
       </property>
-
-      <field name="labelElement"/>
     </implementation>
   </binding>
 
 </bindings>
--- a/toolkit/content/widgets/text.xml
+++ b/toolkit/content/widgets/text.xml
@@ -19,31 +19,16 @@
           this.formatAccessKey(true);
         ]]>
       </constructor>
 
       <method name="formatAccessKey">
         <parameter name="firstTime"/>
         <body>
           <![CDATA[
-            var control = this.labeledControlElement;
-            if (!control) {
-              var bindingParent = document.getBindingParent(this);
-              if ("accessKey" in bindingParent) {
-                control = bindingParent; // For controls that make the <label> an anon child
-              }
-            }
-            if (control) {
-              control.labelElement = this;
-              var controlAccessKey = control.getAttribute("accesskey");
-              if (controlAccessKey) {
-                this.setAttribute("accesskey", controlAccessKey);
-              }
-            }
-
             var accessKey = this.accessKey;
             // No need to remove existing formatting the first time.
             if (firstTime && !accessKey)
               return;
 
             if (this.mInsertSeparator === undefined) {
               try {
                 var prefs = Cc["@mozilla.org/preferences-service;1"].
@@ -83,17 +68,17 @@
 
             var oldHiddenSpan =
               this.getElementsByAttribute("class", "hiddenColon").item(0);
             if (oldHiddenSpan) {
               this.mergeElement(oldHiddenSpan);
             }
 
             var labelText = this.textContent;
-            if (!accessKey || !labelText || !control) {
+            if (!accessKey || !labelText) {
               return;
             }
             var accessKeyIndex = -1;
             if (!this.mAlwaysAppendAccessKey) {
               accessKeyIndex = labelText.indexOf(accessKey);
               if (accessKeyIndex < 0) { // Try again in upper case
                 accessKeyIndex =
                   labelText.toUpperCase().indexOf(accessKey.toUpperCase());
@@ -190,48 +175,39 @@
         !/Mac/.test(navigator.platform)
       </field>
       <field name="mInsertSeparator"/>
       <field name="mAlwaysAppendAccessKey">false</field>
 
       <property name="accessKey">
         <getter>
           <![CDATA[
-            var accessKey = this.getAttribute("accesskey");
-            return accessKey ? accessKey[0] : null;
+            return this.getAttribute("accesskey");
           ]]>
         </getter>
         <setter>
           <![CDATA[
-            // If this label already has an accesskey attribute store it here as well
-            if (this.hasAttribute("accesskey")) {
-              this.setAttribute("accesskey", val);
-            }
+            this.setAttribute("accesskey", val);
             var control = this.labeledControlElement;
             if (control) {
               control.setAttribute("accesskey", val);
             }
             this.formatAccessKey(false);
             return val;
           ]]>
         </setter>
       </property>
 
       <property name="labeledControlElement" readonly="true"
                 onget="var control = this.control; return control ? document.getElementById(control) : null;" />
 
       <property name="control" onget="return this.getAttribute('control');">
         <setter>
           <![CDATA[
-            var control = this.labeledControlElement;
-            if (control) {
-              control.labelElement = null; // No longer pointed to be this label
-            }
             this.setAttribute("control", val);
-            this.formatAccessKey(false);
             return val;
           ]]>
         </setter>
       </property>
     </implementation>
 
     <handlers>
       <handler event="click"><![CDATA[
--- a/toolkit/content/widgets/textbox.xml
+++ b/toolkit/content/widgets/textbox.xml
@@ -47,19 +47,17 @@
         ]]></getter>
       </property>
 
       <property name="value"      onset="this.inputField.value = val; return val;"
                                   onget="return this.inputField.value;"/>
       <property name="defaultValue" onset="this.inputField.defaultValue = val; return val;"
                                   onget="return this.inputField.defaultValue;"/>
       <property name="label"      onset="this.setAttribute('label', val); return val;"
-                                  onget="return this.getAttribute('label') ||
-                                                (this.labelElement ? this.labelElement.value :
-                                                 this.placeholder);"/>
+                                  onget="return this.getAttribute('label') || this.placeholder;" />
       <property name="placeholder" onset="this.inputField.placeholder = val; return val;"
                                   onget="return this.inputField.placeholder;"/>
       <property name="emptyText"  onset="this.placeholder = val; return val;"
                                   onget="return this.placeholder;"/>
       <property name="type"       onset="if (val) this.setAttribute('type', val);
                                          else this.removeAttribute('type'); return val;"
                                   onget="return this.getAttribute('type');"/>
       <property name="maxLength"  onset="this.inputField.maxLength = val; return val;"
--- a/toolkit/content/widgets/toolbarbutton.xml
+++ b/toolkit/content/widgets/toolbarbutton.xml
@@ -6,16 +6,20 @@
 
 <bindings id="toolbarbuttonBindings"
    xmlns="http://www.mozilla.org/xbl"
    xmlns:xul="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul"
    xmlns:xbl="http://www.mozilla.org/xbl">
 
   <binding id="toolbarbutton" display="xul:button"
            extends="chrome://global/content/bindings/button.xml#button-base">
+    <implementation>
+      <property name="multilineLabel"
+        onget="return document.getAnonymousElementByAttribute(this, 'class', 'toolbarbutton-multiline-text');" />
+    </implementation>
     <content>
       <children includes="observes|template|menupopup|panel|tooltip"/>
       <xul:image class="toolbarbutton-icon" xbl:inherits="validate,src=image,label,type,consumeanchor,triggeringprincipal=iconloadingprincipal"/>
       <xul:label class="toolbarbutton-text" crop="right" flex="1"
                  xbl:inherits="value=label,accesskey,crop,dragover-top,wrap"/>
       <xul:label class="toolbarbutton-multiline-text" flex="1"
                  xbl:inherits="xbl:text=label,accesskey,wrap"/>
       <children includes="box"/>
--- a/toolkit/mozapps/extensions/internal/XPIInstall.jsm
+++ b/toolkit/mozapps/extensions/internal/XPIInstall.jsm
@@ -390,17 +390,21 @@ async function loadManifestFromWebManife
   let manifest = await extension.loadManifest();
 
   // Read the list of available locales, and pre-load messages for
   // all locales.
   let locales = (extension.errors.length == 0) ?
                 await extension.initAllLocales() : null;
 
   if (extension.errors.length > 0) {
-    throw new Error("Extension is invalid");
+    let error = new Error("Extension is invalid");
+    // Add detailed errors on the error object so that the front end can display them
+    // if needed (eg in about:debugging).
+    error.additionalErrors = extension.errors;
+    throw error;
   }
 
   let bss = (manifest.browser_specific_settings && manifest.browser_specific_settings.gecko)
       || (manifest.applications && manifest.applications.gecko) || {};
   if (manifest.browser_specific_settings && manifest.applications) {
     logger.warn("Ignoring applications property in manifest");
   }
 
--- a/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js
+++ b/toolkit/mozapps/extensions/test/xpcshell/test_webextension_install.js
@@ -46,16 +46,53 @@ add_task(async function test_implicit_id
   // file url of the installed xpi file.
   equal(addon.sourceURI && addon.sourceURI.spec,
         Services.io.newFileURI(xpifile).spec,
         "SourceURI of the add-on has the expected value");
 
   await addon.uninstall();
 });
 
+// Test that extension install error attach the detailed error messages to the
+// Error object.
+add_task(async function test_invalid_extension_install_errors() {
+  const manifest = {
+    name: "invalid",
+    applications: {
+      gecko: {
+        id: "invalid@tests.mozilla.org",
+      },
+    },
+    description: "extension with an invalid 'matches' value",
+    manifest_version: 2,
+    content_scripts: [{
+      "matches": "*://*.foo.com/*",
+      "js": ["content.js"],
+    }],
+    version: "1.0",
+  };
+
+  const addonDir = await promiseWriteWebManifestForExtension(manifest, gTmpD,
+                                                "the-addon-sub-dir");
+
+  await Assert.rejects(
+    AddonManager.installTemporaryAddon(addonDir),
+    err => {
+      return err.additionalErrors.length == 1 &&
+             err.additionalErrors[0] ==
+              `Reading manifest: Error processing content_scripts.0.matches: ` +
+              `Expected array instead of "*://*.foo.com/*"`;
+    },
+    "Exception has the proper additionalErrors details"
+  );
+
+  Services.obs.notifyObservers(addonDir, "flush-cache-entry");
+  addonDir.remove(true);
+});
+
 // We should be able to temporarily install an unsigned web extension
 // that does not have an ID in its manifest.
 add_task(async function test_unsigned_no_id_temp_install() {
   AddonTestUtils.useRealCertChecks = true;
   const manifest = {
     name: "no ID",
     description: "extension without an ID",
     manifest_version: 2,
--- a/toolkit/mozapps/update/common/updatedefines.h
+++ b/toolkit/mozapps/update/common/updatedefines.h
@@ -2,30 +2,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/. */
 
 #ifndef UPDATEDEFINES_H
 #define UPDATEDEFINES_H
 
 #include "readstrings.h"
 
-#ifndef MAXPATHLEN
-#  ifdef PATH_MAX
-#    define MAXPATHLEN PATH_MAX
-#  elif defined(MAX_PATH)
-#    define MAXPATHLEN MAX_PATH
-#  elif defined(_MAX_PATH)
-#    define MAXPATHLEN _MAX_PATH
-#  elif defined(CCHMAXPATH)
-#    define MAXPATHLEN CCHMAXPATH
-#  else
-#    define MAXPATHLEN 1024
-#  endif
-#endif
-
 #if defined(XP_WIN)
 #  include <windows.h>
 #  include <shlwapi.h>
 #  include <direct.h>
 #  include <io.h>
 #  include <stdio.h>
 #  include <stdarg.h>
 
@@ -140,9 +126,23 @@ static inline int mywcsprintf(WCHAR* des
 #  define NS_tdirent dirent
 #  define NS_topendir opendir
 #  define NS_tclosedir closedir
 #  define NS_treaddir readdir
 #endif
 
 #define BACKUP_EXT NS_T(".moz-backup")
 
+#ifndef MAXPATHLEN
+#  ifdef PATH_MAX
+#    define MAXPATHLEN PATH_MAX
+#  elif defined(MAX_PATH)
+#    define MAXPATHLEN MAX_PATH
+#  elif defined(_MAX_PATH)
+#    define MAXPATHLEN _MAX_PATH
+#  elif defined(CCHMAXPATH)
+#    define MAXPATHLEN CCHMAXPATH
+#  else
+#    define MAXPATHLEN 1024
+#  endif
 #endif
+
+#endif