Merge mozilla-central to inbound. a=merge CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Mon, 15 Oct 2018 01:21:36 +0300
changeset 489516 408c0e44c2d93fae7df447e07b615ab833fdd28d
parent 489495 00351b000d8835beb11192c939f3953699799940 (current diff)
parent 489515 3aca49b2df240e86d5b164feb18575681c818c63 (diff)
child 489517 b8601c0c061473d7c81844816d6efdbfbc1eb53b
push id247
push userfmarier@mozilla.com
push dateSat, 27 Oct 2018 01:06:44 +0000
reviewersmerge
milestone64.0a1
Merge mozilla-central to inbound. a=merge CLOSED TREE
--- a/browser/app/moz.build
+++ b/browser/app/moz.build
@@ -79,21 +79,16 @@ if CONFIG['OS_ARCH'] == 'WINNT':
     LOCAL_INCLUDES += [
         '/browser/app/winlauncher',
     ]
     DELAYLOAD_DLLS += [
         'oleaut32.dll',
         'ole32.dll',
     ]
 
-if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'Darwin':
-    USE_LIBS += [
-        'mozsandbox',
-    ]
-
 if CONFIG['MOZ_SANDBOX'] and CONFIG['OS_ARCH'] == 'WINNT':
     # For sandbox includes and the include dependencies those have
     LOCAL_INCLUDES += [
         '/security/sandbox/chromium',
         '/security/sandbox/chromium-shim',
     ]
 
     USE_LIBS += [
--- a/browser/app/nsBrowserApp.cpp
+++ b/browser/app/nsBrowserApp.cpp
@@ -38,20 +38,16 @@
 #include "mozilla/Sprintf.h"
 #include "mozilla/StartupTimeline.h"
 #include "mozilla/WindowsDllBlocklist.h"
 
 #ifdef LIBFUZZER
 #include "FuzzerDefs.h"
 #endif
 
-#ifdef XP_MACOSX
-#include "mozilla/Sandbox.h"
-#endif
-
 #ifdef MOZ_LINUX_32_SSE2_STARTUP_ERROR
 #include <cpuid.h>
 #include "mozilla/Unused.h"
 
 static bool
 IsSSE2Available()
 {
   // The rest of the app has been compiled to assume that SSE2 is present
@@ -262,26 +258,16 @@ InitXPCOMGlue()
 // NB: This must be extern, as this value is checked elsewhere
 uint32_t gBlocklistInitFlags = eDllBlocklistInitFlagDefault;
 #endif
 
 int main(int argc, char* argv[], char* envp[])
 {
   mozilla::TimeStamp start = mozilla::TimeStamp::Now();
 
-#ifdef XP_MACOSX
-  if (argc > 1 && IsArg(argv[1], "contentproc")) {
-    std::string err;
-    if (!mozilla::EarlyStartMacSandboxIfEnabled(argc, argv, err)) {
-      Output("Sandbox error: %s\n", err.c_str());
-      MOZ_CRASH("Sandbox initialization failed");
-    }
-  }
-#endif
-
 #ifdef MOZ_BROWSER_CAN_BE_CONTENTPROC
   // We are launching as a content process, delegate to the appropriate
   // main
   if (argc > 1 && IsArg(argv[1], "contentproc")) {
 #ifdef HAS_DLL_BLOCKLIST
     DllBlocklist_Initialize(eDllBlocklistInitFlagIsChildProcess);
 #endif
 #if defined(XP_WIN) && defined(MOZ_SANDBOX)
--- a/browser/app/profile/firefox.js
+++ b/browser/app/profile/firefox.js
@@ -1021,22 +1021,16 @@ pref("security.sandbox.gpu.level", 0);
 
 // Controls whether we disable win32k for the GMP processes.
 // true means that win32k system calls are not permitted.
 // Note: win32k is currently _not_ disabled due to intermittent test failures,
 // where the GMP process fails very early. See bug 1449348.
 pref("security.sandbox.gmp.win32k-disable", false);
 #endif
 
-#if defined(NIGHTLY_BUILD) && defined(XP_MACOSX) && defined(MOZ_SANDBOX)
-// Start the Mac sandbox immediately during child process startup instead
-// of when messaged by the parent after the message loop is running.
-pref("security.sandbox.content.mac.earlyinit", true);
-#endif
-
 #if defined(XP_MACOSX) && defined(MOZ_SANDBOX) && defined(MOZ_CONTENT_SANDBOX)
 // This pref is discussed in bug 1083344, the naming is inspired from its
 // Windows counterpart, but on Mac it's an integer which means:
 // 0 -> "no sandbox" (nightly only)
 // 1 -> "preliminary content sandboxing enabled: write access to
 //       home directory is prevented"
 // 2 -> "preliminary content sandboxing enabled with profile protection:
 //       write access to home directory is prevented, read and write access
--- a/browser/base/content/test/general/browser_homeDrop.js
+++ b/browser/base/content/test/general/browser_homeDrop.js
@@ -14,18 +14,16 @@ add_task(async function() {
   ok(dragSrcElement, "Downloads button exists");
   let homeButton = document.getElementById("home-button");
   ok(homeButton, "home button present");
 
   async function drop(dragData, homepage) {
     let setHomepageDialogPromise = BrowserTestUtils.domWindowOpened();
 
     EventUtils.synthesizeDrop(dragSrcElement, homeButton, dragData, "copy", window);
-    // Ensure dnd suppression is cleared.
-    EventUtils.synthesizeMouseAtCenter(homeButton, { type: "mouseup" }, window);
 
     let setHomepageDialog = await setHomepageDialogPromise;
     ok(true, "dialog appeared in response to home button drop");
     await BrowserTestUtils.waitForEvent(setHomepageDialog, "load", false);
 
     let setHomepagePromise = new Promise(function(resolve) {
       let observer = {
         QueryInterface: ChromeUtils.generateQI([Ci.nsIObserver]),
@@ -65,18 +63,16 @@ add_task(async function() {
       });
 
       executeSoon(function() {
         info("Attempting second drop, of a javascript: URI");
         // The drop handler throws an exception when dragging URIs that inherit
         // principal, e.g. javascript:
         expectUncaughtException();
         EventUtils.synthesizeDrop(dragSrcElement, homeButton, [[{type: "text/plain", data: "javascript:8888"}]], "copy", window);
-        // Ensure dnd suppression is cleared.
-        EventUtils.synthesizeMouseAtCenter(homeButton, { type: "mouseup" }, window);
       });
     });
   }
 
   await drop([[{type: "text/plain",
                  data: "http://mochi.test:8888/"}]],
               "http://mochi.test:8888/");
   await drop([[{type: "text/plain",
--- a/browser/components/customizableui/test/head.js
+++ b/browser/components/customizableui/test/head.js
@@ -18,17 +18,17 @@ Services.scriptloader.loadSubScript("chr
 /**
  * Instance of CustomizableUITestUtils for the current browser window.
  */
 var gCUITestUtils = new CustomizableUITestUtils(window);
 
 Services.prefs.setBoolPref("browser.uiCustomization.skipSourceNodeCheck", true);
 registerCleanupFunction(() => Services.prefs.clearUserPref("browser.uiCustomization.skipSourceNodeCheck"));
 
-var {synthesizeDragStart, synthesizeDrop, synthesizeMouseAtCenter} = EventUtils;
+var {synthesizeDragStart, synthesizeDrop} = EventUtils;
 
 const kNSXUL = "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul";
 
 const kForceOverflowWidthPx = 300;
 
 function createDummyXULButton(id, label, win = window) {
   let btn = document.createElementNS(kNSXUL, "toolbarbutton");
   btn.id = id;
@@ -184,18 +184,16 @@ function simulateItemDrag(aToDrag, aTarg
       ev = {clientX: bounds.right - 2, clientY: bounds.bottom - 2};
     } else {
       ev = {clientX: bounds.left + 2, clientY: bounds.top + 2};
     }
   }
   ev._domDispatchOnly = true;
   synthesizeDrop(aToDrag.parentNode, aTarget, null, null,
                  aToDrag.ownerGlobal, aTarget.ownerGlobal, ev);
-  // Ensure dnd suppression is cleared.
-  synthesizeMouseAtCenter(aTarget, { type: "mouseup" }, aTarget.ownerGlobal);
 }
 
 function endCustomizing(aWindow = window) {
   if (aWindow.document.documentElement.getAttribute("customizing") != "true") {
     return true;
   }
   return new Promise(resolve => {
     function onCustomizationEnds() {
--- a/devtools/client/jar.mn
+++ b/devtools/client/jar.mn
@@ -102,17 +102,16 @@ devtools.jar:
     skin/dark-theme.css (themes/dark-theme.css)
     skin/light-theme.css (themes/light-theme.css)
     skin/toolbars.css (themes/toolbars.css)
     skin/toolbox.css (themes/toolbox.css)
     skin/tooltips.css (themes/tooltips.css)
     skin/images/accessibility.svg (themes/images/accessibility.svg)
     skin/images/add.svg (themes/images/add.svg)
     skin/images/arrowhead-left.svg (themes/images/arrowhead-left.svg)
-    skin/images/arrowhead-right.svg (themes/images/arrowhead-right.svg)
     skin/images/arrowhead-down.svg (themes/images/arrowhead-down.svg)
     skin/images/arrowhead-up.svg (themes/images/arrowhead-up.svg)
     skin/images/breadcrumbs-divider.svg (themes/images/breadcrumbs-divider.svg)
     skin/images/filters.svg (themes/images/filters.svg)
     skin/images/filter-swatch.svg (themes/images/filter-swatch.svg)
     skin/images/aboutdebugging-collapse-icon.svg (themes/images/aboutdebugging-collapse-icon.svg)
     skin/images/aboutdebugging-connect-icon.svg (themes/images/aboutdebugging-connect-icon.svg)
     skin/images/aboutdebugging-firefox-aurora.svg (themes/images/aboutdebugging-firefox-aurora.svg)
--- a/devtools/client/themes/layout.css
+++ b/devtools/client/themes/layout.css
@@ -212,67 +212,96 @@
 
 .flex-outline-final,
 .flex-outline-basis,
 .flex-outline-delta {
   grid-row: 1;
 }
 
 .flex-outline-final {
-  border: 1px solid currentColor;
+  border: 2px solid currentColor;
   position: relative;
   grid-column: final-start / final-end;
 }
 
 .flex-outline-final.clamped::after {
   content: "";
-  background-color: var(--theme-body-background);
   background-image: url(chrome://devtools/skin/images/lock.svg);
   background-size: 16px;
   background-repeat: no-repeat;
   background-position: center 1px;
   fill: currentColor;
   -moz-context-properties: fill;
   width: 20px;
   height: 20px;
   position: absolute;
   right: -10px;
   top: 6px;
-  border-radius: 50%;
+  /* Making sure the icon is visible against any background by creating a plain background
+     around its shape, using a drop-shadow filter. */
+  filter:
+    drop-shadow(1px 0px 0px var(--theme-body-background))
+    drop-shadow(0px 1px 0px var(--theme-body-background))
+    drop-shadow(-1px 0px 0px var(--theme-body-background))
+    drop-shadow(0px -1px 0px var(--theme-body-background));
 }
 
 .flex-outline.column .flex-outline-final.clamped::after {
   transform: rotate(-.25turn);
 }
 
 .flex-outline-basis {
   border-style: dotted;
   border-width: 3px;
-  margin: 1px 0;
+  margin: 1px;
   grid-column: basis-start / basis-end;
 }
 
 .flex-outline-basis.zero-basis {
   border-width: 0 0 0 3px;
 }
 
 .flex-outline-delta {
-  background-repeat: round;
-  fill: currentColor;
-  -moz-context-properties: fill;
   grid-column: delta-start / delta-end;
-  margin: 4px;
+  margin: 3px 0;
+  opacity: .5;
+  position: relative;
+}
+
+.flex-outline-delta::before {
+  content: "";
+  position: absolute;
+  left: 2px;
+  right: 2px;
+  top: calc(50% - .5px);
+  height: 1px;
+  background: currentColor;
 }
 
-.flex-outline.growing .flex-outline-delta {
-  background-image: url(chrome://devtools/skin/images/arrowhead-right.svg);
+.flex-outline-delta::after {
+  content: "";
+  position: absolute;
+  width: 5px;
+  height: 5px;
+  top: 50%;
+  border: 1px solid currentColor;
 }
 
-.flex-outline.shrinking .flex-outline-delta {
-  background-image: url(chrome://devtools/skin/images/arrowhead-left.svg);
+.flex-outline.growing .flex-outline-delta:after {
+  right: 2px;
+  border-width: 1px 1px 0 0;
+  transform-origin: top right;
+  transform: rotate(.125turn);
+}
+
+.flex-outline.shrinking .flex-outline-delta:after {
+  left: 2px;
+  border-width: 1px 0 0 1px;
+  transform-origin: top left;
+  transform: rotate(-.125turn);
 }
 
 .flex-outline-point {
   position: relative;
   -moz-user-select: none;
 }
 
 .flex-outline-point {
--- a/dom/ipc/ContentChild.cpp
+++ b/dom/ipc/ContentChild.cpp
@@ -189,17 +189,16 @@
 #ifdef XP_WIN
 #include <process.h>
 #define getpid _getpid
 #include "mozilla/widget/AudioSession.h"
 #include "mozilla/audio/AudioNotificationReceiver.h"
 #endif
 
 #if defined(XP_MACOSX)
-#include "nsMacUtilsImpl.h"
 #include <CoreServices/CoreServices.h>
 // Info.plist key associated with the developer repo path
 #define MAC_DEV_REPO_KEY "MozillaDeveloperRepoPath"
 // Info.plist key associated with the developer repo object directory
 #define MAC_DEV_OBJ_KEY "MozillaDeveloperObjPath"
 #endif /* XP_MACOSX */
 
 #ifdef MOZ_X11
@@ -1519,16 +1518,120 @@ ContentChild::RecvReinitRenderingForDevi
     if (tabChild->GetLayersId().IsValid()) {
       tabChild->ReinitRenderingForDeviceReset();
     }
   }
   return IPC_OK();
 }
 
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
+
+#include <stdlib.h>
+
+static bool
+GetAppPaths(nsCString &aAppPath, nsCString &aAppBinaryPath, nsCString &aAppDir)
+{
+  nsAutoCString appPath;
+  nsAutoCString appBinaryPath(
+    (CommandLine::ForCurrentProcess()->argv()[0]).c_str());
+
+  nsAutoCString::const_iterator start, end;
+  appBinaryPath.BeginReading(start);
+  appBinaryPath.EndReading(end);
+  if (RFindInReadable(NS_LITERAL_CSTRING(".app/Contents/MacOS/"), start, end)) {
+    end = start;
+    ++end; ++end; ++end; ++end;
+    appBinaryPath.BeginReading(start);
+    appPath.Assign(Substring(start, end));
+  } else {
+    return false;
+  }
+
+  nsCOMPtr<nsIFile> app, appBinary;
+  nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appPath),
+                                true, getter_AddRefs(app));
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+  rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appBinaryPath),
+                       true, getter_AddRefs(appBinary));
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  nsCOMPtr<nsIFile> appDir;
+  nsCOMPtr<nsIProperties> dirSvc =
+    do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID);
+  if (!dirSvc) {
+    return false;
+  }
+  rv = dirSvc->Get(NS_GRE_DIR,
+                   NS_GET_IID(nsIFile), getter_AddRefs(appDir));
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+  bool exists;
+  rv = appDir->Exists(&exists);
+  if (NS_FAILED(rv) || !exists) {
+    return false;
+  }
+
+  // appDir points to .app/Contents/Resources, for our purposes we want
+  // .app/Contents.
+  nsCOMPtr<nsIFile> appDirParent;
+  rv = appDir->GetParent(getter_AddRefs(appDirParent));
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+
+  rv = app->Normalize();
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+  app->GetNativePath(aAppPath);
+
+  rv = appBinary->Normalize();
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+  appBinary->GetNativePath(aAppBinaryPath);
+
+  rv = appDirParent->Normalize();
+  if (NS_FAILED(rv)) {
+    return false;
+  }
+  appDirParent->GetNativePath(aAppDir);
+
+  return true;
+}
+
+// This function is only used in an |#ifdef DEBUG| path.
+#ifdef DEBUG
+// Given a path to a file, return the directory which contains it.
+static nsAutoCString
+GetDirectoryPath(const char *aPath) {
+  nsCOMPtr<nsIFile> file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
+  if (!file ||
+      NS_FAILED(file->InitWithNativePath(nsDependentCString(aPath)))) {
+    MOZ_CRASH("Failed to create or init an nsIFile");
+  }
+  nsCOMPtr<nsIFile> directoryFile;
+  if (NS_FAILED(file->GetParent(getter_AddRefs(directoryFile))) ||
+      !directoryFile) {
+    MOZ_CRASH("Failed to get parent for an nsIFile");
+  }
+  directoryFile->Normalize();
+  nsAutoCString directoryPath;
+  if (NS_FAILED(directoryFile->GetNativePath(directoryPath))) {
+    MOZ_CRASH("Failed to get path for an nsIFile");
+  }
+  return directoryPath;
+}
+#endif // DEBUG
+
 extern "C" {
 CGError
 CGSSetDenyWindowServerConnections(bool);
 void CGSShutdownServerConnections();
 };
 
 static bool
 StartMacOSContentSandbox()
@@ -1550,19 +1653,19 @@ StartMacOSContentSandbox()
         "security.sandbox.content.mac.disconnect-windowserver")) {
     CGError result = CGSSetDenyWindowServerConnections(true);
     MOZ_DIAGNOSTIC_ASSERT(result == kCGErrorSuccess);
 #if !MOZ_DIAGNOSTIC_ASSERT_ENABLED
     Unused << result;
 #endif
   }
 
-  nsAutoCString appPath;
-  if (!nsMacUtilsImpl::GetAppPath(appPath)) {
-    MOZ_CRASH("Error resolving child process app path");
+  nsAutoCString appPath, appBinaryPath, appDir;
+  if (!GetAppPaths(appPath, appBinaryPath, appDir)) {
+    MOZ_CRASH("Error resolving child process path");
   }
 
   ContentChild* cc = ContentChild::GetSingleton();
 
   nsresult rv;
   nsCOMPtr<nsIFile> profileDir;
   cc->GetProfileDir(getter_AddRefs(profileDir));
   nsCString profileDirPath;
@@ -1578,19 +1681,19 @@ StartMacOSContentSandbox()
 
   MacSandboxInfo info;
   info.type = MacSandboxType_Content;
   info.level = sandboxLevel;
   info.hasFilePrivileges = isFileProcess;
   info.shouldLog = Preferences::GetBool("security.sandbox.logging.enabled") ||
                    PR_GetEnv("MOZ_SANDBOX_LOGGING");
   info.appPath.assign(appPath.get());
+  info.appBinaryPath.assign(appBinaryPath.get());
+  info.appDir.assign(appDir.get());
   info.hasAudio = !Preferences::GetBool("media.cubeb.sandbox");
-  info.hasWindowServer = !Preferences::GetBool(
-      "security.sandbox.content.mac.disconnect-windowserver");
 
   // These paths are used to whitelist certain directories used by the testing
   // system. They should not be considered a public API, and are only intended
   // for use in automation.
   nsAutoCString testingReadPath1;
   Preferences::GetCString("security.sandbox.content.mac.testing_read_path1",
                           testingReadPath1);
   if (!testingReadPath1.IsEmpty()) {
@@ -1634,18 +1737,17 @@ StartMacOSContentSandbox()
 #ifdef DEBUG
   // When a content process dies intentionally (|NoteIntentionalCrash|), for
   // tests it wants to log that it did this. Allow writing to this location
   // that the testrunner wants.
   char *bloatLog = PR_GetEnv("XPCOM_MEM_BLOAT_LOG");
   if (bloatLog != nullptr) {
     // |bloatLog| points to a specific file, but we actually write to a sibling
     // of that path.
-    nsAutoCString bloatDirectoryPath =
-      nsMacUtilsImpl::GetDirectoryPath(bloatLog);
+    nsAutoCString bloatDirectoryPath = GetDirectoryPath(bloatLog);
     info.debugWriteDir.assign(bloatDirectoryPath.get());
   }
 #endif // DEBUG
 
   std::string err;
   if (!mozilla::StartMacSandbox(info, err)) {
     NS_WARNING(err.c_str());
     MOZ_CRASH("sandbox_init() failed");
--- a/dom/ipc/ContentParent.cpp
+++ b/dom/ipc/ContentParent.cpp
@@ -105,27 +105,25 @@
 #include "mozilla/StaticPrefs.h"
 #include "mozilla/Telemetry.h"
 #include "mozilla/TelemetryIPC.h"
 #include "mozilla/WebBrowserPersistDocumentParent.h"
 #include "mozilla/widget/ScreenManager.h"
 #include "mozilla/Unused.h"
 #include "mozilla/HangDetails.h"
 #include "nsAnonymousTemporaryFile.h"
-#include "nsAppDirectoryServiceDefs.h"
 #include "nsAppRunner.h"
 #include "nsCDefaultURIFixup.h"
 #include "nsCExternalHandlerService.h"
 #include "nsCOMPtr.h"
 #include "nsChromeRegistryChrome.h"
 #include "nsConsoleMessage.h"
 #include "nsConsoleService.h"
 #include "nsContentUtils.h"
 #include "nsDebugImpl.h"
-#include "nsDirectoryService.h"
 #include "nsDirectoryServiceDefs.h"
 #include "nsEmbedCID.h"
 #include "nsFrameLoader.h"
 #include "nsFrameMessageManager.h"
 #include "nsHashPropertyBag.h"
 #include "nsIAlertsService.h"
 #include "nsIClipboard.h"
 #include "nsICookie.h"
@@ -211,20 +209,16 @@
 #include "nsLayoutStylesheetCache.h"
 
 #include "mozilla/Sprintf.h"
 
 #ifdef MOZ_WEBRTC
 #include "signaling/src/peerconnection/WebrtcGlobalParent.h"
 #endif
 
-#if defined(XP_MACOSX)
-#include "nsMacUtilsImpl.h"
-#endif
-
 #if defined(ANDROID) || defined(LINUX)
 #include "nsSystemInfo.h"
 #endif
 
 #if defined(XP_LINUX)
 #include "mozilla/Hal.h"
 #endif
 
@@ -610,20 +604,16 @@ static const char* sObserverTopics[] = {
   "cacheservice:empty-cache",
   "intl:app-locales-changed",
   "intl:requested-locales-changed",
   "cookie-changed",
   "private-cookie-changed",
   "clear-site-data-reload-needed",
 };
 
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
-bool ContentParent::sEarlySandboxInit = false;
-#endif
-
 // PreallocateProcess is called by the PreallocatedProcessManager.
 // ContentParent then takes this process back within GetNewOrUsedBrowserProcess.
 /*static*/ already_AddRefed<ContentParent>
 ContentParent::PreallocateProcess()
 {
   RefPtr<ContentParent> process =
     new ContentParent(/* aOpener = */ nullptr,
                       NS_LITERAL_STRING(DEFAULT_REMOTE_TYPE),
@@ -2135,130 +2125,16 @@ ContentParent::DestroyTestShell(TestShel
 
 TestShellParent*
 ContentParent::GetTestShellSingleton()
 {
   PTestShellParent* p = LoneManagedOrNullAsserts(ManagedPTestShellParent());
   return static_cast<TestShellParent*>(p);
 }
 
-#ifdef XP_MACOSX
-void
-ContentParent::AppendSandboxParams(std::vector<std::string> &aArgs)
-{
-  nsCOMPtr<nsIProperties>
-    directoryService(do_GetService(NS_DIRECTORY_SERVICE_CONTRACTID));
-  if (!directoryService) {
-    MOZ_CRASH("Failed to get the directory service");
-  }
-
-  // Indicates the child should startup the sandbox
-  aArgs.push_back("-sbStartup");
-
-  // The content sandbox level
-  int contentSandboxLevel =
-    Preferences::GetInt("security.sandbox.content.level");
-  std::ostringstream os;
-  os << contentSandboxLevel;
-  std::string contentSandboxLevelString = os.str();
-  aArgs.push_back("-sbLevel");
-  aArgs.push_back(contentSandboxLevelString);
-
-  // Sandbox logging
-  if (Preferences::GetBool("security.sandbox.logging.enabled") ||
-      PR_GetEnv("MOZ_SANDBOX_LOGGING")) {
-    aArgs.push_back("-sbLogging");
-  }
-
-  // For file content processes
-  if (GetRemoteType().EqualsLiteral(FILE_REMOTE_TYPE)) {
-    aArgs.push_back("-sbAllowFileAccess");
-  }
-
-  // Audio access
-  if (!Preferences::GetBool("media.cubeb.sandbox")) {
-    aArgs.push_back("-sbAllowAudio");
-  }
-
-  // Windowserver access
-  if (!Preferences::GetBool("security.sandbox.content.mac.disconnect-windowserver")) {
-    aArgs.push_back("-sbAllowWindowServer");
-  }
-
-  // .app path (normalized)
-  nsAutoCString appPath;
-  if (!nsMacUtilsImpl::GetAppPath(appPath)) {
-    MOZ_CRASH("Failed to get app dir paths");
-  }
-  aArgs.push_back("-sbAppPath");
-  aArgs.push_back(appPath.get());
-
-  // TESTING_READ_PATH1
-  nsAutoCString testingReadPath1;
-  Preferences::GetCString("security.sandbox.content.mac.testing_read_path1",
-                          testingReadPath1);
-  if (!testingReadPath1.IsEmpty()) {
-    aArgs.push_back("-sbTestingReadPath");
-    aArgs.push_back(testingReadPath1.get());
-  }
-
-  // TESTING_READ_PATH2
-  nsAutoCString testingReadPath2;
-  Preferences::GetCString("security.sandbox.content.mac.testing_read_path2",
-                          testingReadPath2);
-  if (!testingReadPath2.IsEmpty()) {
-    aArgs.push_back("-sbTestingReadPath");
-    aArgs.push_back(testingReadPath2.get());
-  }
-
-  // TESTING_READ_PATH3, TESTING_READ_PATH4. In development builds,
-  // these are used to whitelist the repo dir and object dir respectively.
-  nsresult rv;
-  if (mozilla::IsDevelopmentBuild()) {
-    // Repo dir
-    nsCOMPtr<nsIFile> repoDir;
-    rv = mozilla::GetRepoDir(getter_AddRefs(repoDir));
-    if (NS_FAILED(rv)) {
-      MOZ_CRASH("Failed to get path to repo dir");
-    }
-    nsCString repoDirPath;
-    Unused << repoDir->GetNativePath(repoDirPath);
-    aArgs.push_back("-sbTestingReadPath");
-    aArgs.push_back(repoDirPath.get());
-
-    // Object dir
-    nsCOMPtr<nsIFile> objDir;
-    rv = mozilla::GetObjDir(getter_AddRefs(objDir));
-    if (NS_FAILED(rv)) {
-      MOZ_CRASH("Failed to get path to build object dir");
-    }
-    nsCString objDirPath;
-    Unused << objDir->GetNativePath(objDirPath);
-    aArgs.push_back("-sbTestingReadPath");
-    aArgs.push_back(objDirPath.get());
-  }
-
-  // DEBUG_WRITE_DIR
-#ifdef DEBUG
-  // When a content process dies intentionally (|NoteIntentionalCrash|), for
-  // tests it wants to log that it did this. Allow writing to this location
-  // that the testrunner wants.
-  char *bloatLog = PR_GetEnv("XPCOM_MEM_BLOAT_LOG");
-  if (bloatLog != nullptr) {
-    // |bloatLog| points to a specific file, but we actually write to a sibling
-    // of that path.
-    nsAutoCString bloatDirectoryPath =
-      nsMacUtilsImpl::GetDirectoryPath(bloatLog);
-    aArgs.push_back("-sbDebugWriteDir");
-    aArgs.push_back(bloatDirectoryPath.get());
-  }
-#endif // DEBUG
-}
-#endif // XP_MACOSX
-
 bool
 ContentParent::LaunchSubprocess(ProcessPriority aInitialPriority /* = PROCESS_PRIORITY_FOREGROUND */)
 {
   AUTO_PROFILER_LABEL("ContentParent::LaunchSubprocess", OTHER);
 
   if (!ContentProcessManager::GetSingleton()) {
     // Shutdown has begun, we shouldn't spawn any more child processes.
     return false;
@@ -2337,25 +2213,16 @@ ContentParent::LaunchSubprocess(ProcessP
   nsPrintfCString schedulerPrefs = Scheduler::GetPrefs();
   extraArgs.push_back("-schedulerPrefs");
   extraArgs.push_back(schedulerPrefs.get());
 
   if (gSafeMode) {
     extraArgs.push_back("-safeMode");
   }
 
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
-  // If we're launching a middleman process for a
-  // recording or replay, start the sandbox later.
-  if (sEarlySandboxInit && IsContentSandboxEnabled() &&
-      !IsRecordingOrReplaying()) {
-    AppendSandboxParams(extraArgs);
-  }
-#endif
-
   nsCString parentBuildID(mozilla::PlatformBuildID());
   extraArgs.push_back("-parentBuildID");
   extraArgs.push_back(parentBuildID.get());
 
   // Specify whether the process is recording or replaying an execution.
   if (mRecordReplayState != eNotRecordingOrReplaying) {
     nsPrintfCString buf("%d", mRecordReplayState == eRecording
                               ? (int) recordreplay::ProcessKind::MiddlemanRecording
@@ -2465,27 +2332,16 @@ ContentParent::ContentParent(ContentPare
   // channel. Generally only applies to the situation where we get caught in
   // a deadlock with the plugin process when sending CPOWs.
   GetIPCChannel()->SetChannelFlags(MessageChannel::REQUIRE_DEFERRED_MESSAGE_PROTECTION);
 #endif
 
   NS_ASSERTION(NS_IsMainThread(), "Wrong thread!");
   bool isFile = mRemoteType.EqualsLiteral(FILE_REMOTE_TYPE);
   mSubprocess = new ContentProcessHost(this, isFile);
-
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
-  // sEarlySandboxInit is statically initialized to false.
-  // Once we've set it to true due to the pref, avoid checking the
-  // pref on subsequent calls. As a result, changing the earlyinit
-  // pref requires restarting the browser to take effect.
-  if (!ContentParent::sEarlySandboxInit) {
-    ContentParent::sEarlySandboxInit =
-      Preferences::GetBool("security.sandbox.content.mac.earlyinit");
-  }
-#endif
 }
 
 ContentParent::~ContentParent()
 {
   if (mForceKillTimer) {
     mForceKillTimer->Cancel();
   }
 
@@ -2746,25 +2602,16 @@ ContentParent::InitInternal(ProcessPrior
   MaybeFileDesc brokerFd = void_t();
   // XXX: Checking the pref here makes it possible to enable/disable sandboxing
   // during an active session. Currently the pref is only used for testing
   // purpose. If the decision is made to permanently rely on the pref, this
   // should be changed so that it is required to restart firefox for the change
   // of value to take effect.
   shouldSandbox = IsContentSandboxEnabled();
 
-#ifdef XP_MACOSX
-  // If the sandbox was initialized during content process
-  // startup, we must not send the SetProcessSandbox message.
-  // If early startup was pref'd off or the process is a
-  // middleman process, send SetProcessSandbox now.
-  shouldSandbox = shouldSandbox &&
-    (!sEarlySandboxInit || IsRecordingOrReplaying());
-#endif
-
 #ifdef XP_LINUX
   if (shouldSandbox) {
     MOZ_ASSERT(!mSandboxBroker);
     bool isFileProcess = mRemoteType.EqualsLiteral(FILE_REMOTE_TYPE);
     UniquePtr<SandboxBroker::Policy> policy =
       sSandboxBrokerPolicyFactory->GetContentPolicy(Pid(), isFileProcess);
     if (policy) {
       brokerFd = FileDescriptor();
--- a/dom/ipc/ContentParent.h
+++ b/dom/ipc/ContentParent.h
@@ -1257,18 +1257,16 @@ public:
 
   virtual mozilla::ipc::IPCResult
   RecvStoreUserInteractionAsPermission(const Principal& aPrincipal) override;
 
   // Notify the ContentChild to enable the input event prioritization when
   // initializing.
   void MaybeEnableRemoteInputEventQueue();
 
-  void AppendSandboxParams(std::vector<std::string>& aArgs);
-
 public:
   void SendGetFilesResponseAndForget(const nsID& aID,
                                      const GetFilesResponseResult& aResult);
 
   bool SendRequestMemoryReport(const uint32_t& aGeneration,
                                const bool& aAnonymize,
                                const bool& aMinimizeMemoryUsage,
                                const MaybeFileDesc& aDMDFile) override;
@@ -1384,23 +1382,16 @@ private:
   nsTHashtable<nsCStringHashKey> mActivePermissionKeys;
 
   nsTArray<nsCString> mBlobURLs;
 
   UniquePtr<mozilla::ipc::CrashReporterHost> mCrashReporter;
 
   static uint64_t sNextTabParentId;
   static nsDataHashtable<nsUint64HashKey, TabParent*> sNextTabParents;
-
-#if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
-  // When set to true, indicates that content processes should
-  // initialize their sandbox during startup instead of waiting
-  // for the SetProcessSandbox IPDL message.
-  static bool sEarlySandboxInit;
-#endif
 };
 
 } // namespace dom
 } // namespace mozilla
 
 class ParentIdleListener : public nsIObserver
 {
   friend class mozilla::dom::ContentParent;
--- a/dom/ipc/ContentProcess.cpp
+++ b/dom/ipc/ContentProcess.cpp
@@ -9,17 +9,16 @@
 #include "ContentProcess.h"
 #include "base/shared_memory.h"
 #include "mozilla/Preferences.h"
 #include "mozilla/Scheduler.h"
 #include "mozilla/recordreplay/ParentIPC.h"
 
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
 #include <stdlib.h>
-#include "mozilla/Sandbox.h"
 #endif
 
 #if (defined(XP_WIN) || defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
 #include "mozilla/SandboxSettings.h"
 #include "nsAppDirectoryServiceDefs.h"
 #include "nsDirectoryService.h"
 #include "nsDirectoryServiceDefs.h"
 #endif
@@ -292,26 +291,17 @@ ContentProcess::Init(int aArgc, char* aA
                 *parentBuildID,
                 IOThreadChild::channel(),
                 *childID,
                 *isForBrowser);
 
   mXREEmbed.Start();
 #if (defined(XP_MACOSX)) && defined(MOZ_CONTENT_SANDBOX)
   mContent.SetProfileDir(profileDir);
-#if defined(DEBUG)
-  // For WebReplay middleman processes, the sandbox is
-  // started after receiving the SetProcessSandbox message.
-  if (IsContentSandboxEnabled() &&
-      Preferences::GetBool("security.sandbox.content.mac.earlyinit") &&
-      !recordreplay::IsMiddleman()) {
-    AssertMacSandboxEnabled();
-  }
-#endif /* DEBUG */
-#endif /* XP_MACOSX && MOZ_CONTENT_SANDBOX */
+#endif
 
 #if defined(XP_WIN) && defined(MOZ_CONTENT_SANDBOX)
   SetUpSandboxEnvironment();
 #endif
 
   return true;
 }
 
--- a/dom/media/tests/mochitest/identity/test_fingerprints.html
+++ b/dom/media/tests/mochitest/identity/test_fingerprints.html
@@ -1,122 +1,91 @@
 <html>
 <head>
 <meta charset="utf-8" />
-<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
-<script type="application/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
+<script type="application/javascript">var scriptRelativePath = "../";</script>
+<script type="application/javascript" src="../pc.js"></script>
 </head>
 <body>
-  <script class="testbody" type="application/javascript">
-'use strict';
+<script class="testbody" type="application/javascript">
+createHTML({ title: "Test multiple identity fingerprints",  bug: "1005152" });
 
 // here we call the identity provider directly
-function getIdentityAssertion(fpArray) {
-  var Cu = SpecialPowers.Cu;
-  var rtcid = Cu.import('resource://gre/modules/media/IdpSandbox.jsm');
-  var sandbox = new rtcid.IdpSandbox('example.com', 'idp.js', window);
-  return sandbox.start()
-    .then(idp => SpecialPowers.wrap(idp)
-                   .generateAssertion(JSON.stringify({ fingerprint: fpArray }),
-                                      'https://example.com',
-                                      {}))
-    .then(assertion => {
-      assertion = SpecialPowers.wrap(assertion);
-      var assertionString = btoa(JSON.stringify(assertion));
-      sandbox.stop();
-      return assertionString;
-    });
+async function getIdentityAssertion(fingerprint) {
+  const {Cu} = SpecialPowers;
+  const rtcid = Cu.import('resource://gre/modules/media/IdpSandbox.jsm');
+  const sandbox = new rtcid.IdpSandbox('example.com', 'idp.js', window);
+  const idp = SpecialPowers.wrap(await sandbox.start());
+  const assertion = SpecialPowers.wrap(await
+      idp.generateAssertion(JSON.stringify({ fingerprint }),
+                            'https://example.com',
+                            {}));
+  const assertionString = btoa(JSON.stringify(assertion));
+  sandbox.stop();
+  return assertionString;
 }
 
 // This takes a real fingerprint and makes some extra bad ones.
-function makeFingerprints(algo, digest) {
-  var fingerprints = [];
-  fingerprints.push({ algorithm: algo, digest: digest });
+function makeFingerprints(algorithm, digest) {
+  const fingerprints = [];
+  fingerprints.push({ algorithm, digest });
   for (var i = 0; i < 3; ++i) {
     fingerprints.push({
-      algorithm: algo,
+      algorithm,
       digest: digest.replace(/:./g, ':' + i.toString(16))
     });
   }
   return fingerprints;
 }
 
-var fingerprintRegex = /^a=fingerprint:(\S+) (\S+)/m;
-var identityRegex = /^a=identity:(\S+)/m;
+const fingerprintRegex = /^a=fingerprint:(\S+) (\S+)/m;
+const identityRegex = /^a=identity:(\S+)/m;
 
 function fingerprintSdp(fingerprints) {
   return fingerprints.map(fp => 'a=fInGeRpRiNt:' + fp.algorithm +
                                 ' ' + fp.digest + '\n').join('');
 }
 
 // Firefox only uses a single fingerprint.
 // That doesn't mean we have it create SDP that describes two.
 // This function synthesizes that SDP and tries to set it.
-function testMultipleFingerprints() {
+
+runNetworkTest(async () => {
   // this one fails setRemoteDescription if the identity is not good
-  var pcStrict = new RTCPeerConnection({ peerIdentity: 'someone@example.com'});
+  const pcStrict = new RTCPeerConnection({ peerIdentity: 'someone@example.com'});
   // this one will be manually tweaked to have two fingerprints
-  var pcDouble = new RTCPeerConnection({});
-
-  var offer, match, fingerprints;
-
-  var fail = msg =>
-      (e => ok(false, 'error in ' + msg + ': ' +
-               (e.message ? (e.message + '\n' + e.stack) : e)));
-
-  navigator.mediaDevices.getUserMedia({ video: true })
-    .then(stream => {
-      ok(stream, 'Got test stream');
-      pcDouble.addStream(stream);
-      return pcDouble.createOffer();
-    })
-    .then(o => {
-      offer = o;
-      ok(offer, 'Got offer');
-
-      match = offer.sdp.match(fingerprintRegex);
-      if (!match) {
-        throw new Error('No fingerprint in offer SDP');
-      }
-      fingerprints = makeFingerprints(match[1], match[2]);
-      return getIdentityAssertion(fingerprints);
-    })
-    .then(assertion => {
-      ok(assertion, 'Should have assertion');
+  const pcDouble = new RTCPeerConnection({});
 
-      var sdp = offer.sdp.slice(0, match.index) +
-          'a=identity:' + assertion + '\n' +
-          fingerprintSdp(fingerprints.slice(1)) +
-          offer.sdp.slice(match.index);
+  const stream = await getUserMedia({ video: true });
+  ok(stream, 'Got test stream');
+  const [track] = stream.getTracks();
+  pcDouble.addTrack(track, stream);
+  try {
+    const offer = await pcDouble.createOffer();
+    ok(offer, 'Got offer');
+    const match = offer.sdp.match(fingerprintRegex);
+    if (!match) {
+      throw new Error('No fingerprint in offer SDP');
+    }
+    const fingerprints = makeFingerprints(match[1], match[2]);
+    const assertion = await getIdentityAssertion(fingerprints);
+    ok(assertion, 'Should have assertion');
 
-      return pcStrict.setRemoteDescription({ type: 'offer', sdp });
-    })
-    .then(() => {
-      ok(true, 'Modified fingerprints were accepted');
-    }, error => {
-      var e = SpecialPowers.wrap(error);
-      ok(false, 'error in test: ' +
-         (e.message ? (e.message + '\n' + e.stack) : e));
-    })
-    .then(() => {
-      pcStrict.close();
-      pcDouble.close();
-      SimpleTest.finish();
-    });
-}
+    const sdp = offer.sdp.slice(0, match.index) +
+        'a=identity:' + assertion + '\n' +
+        fingerprintSdp(fingerprints.slice(1)) +
+        offer.sdp.slice(match.index);
 
-SimpleTest.waitForExplicitFinish();
-SpecialPowers.pushPrefEnv({
-  set: [
-    [ 'media.peerconnection.identity.enabled', true ],
-    // Disable permission to skip prompt when on platforms the use loopback
-    // test devices (these would normally trigger a prompt).
-    [ 'media.navigator.permission.disabled', true ],
-    // Since this test doesn't include head.js or pc.js, we need to set the fake
-    // device pref manually. On platforms where loopback devices are used they
-    // should still take precedence, however on some platforms no prefs would
-    // be set and the test would fail.
-    [ 'media.navigator.streams.fake', true ]
-  ]
-}, testMultipleFingerprints);
+    await pcStrict.setRemoteDescription({ type: 'offer', sdp });
+    ok(true, 'Modified fingerprints were accepted');
+  } catch (error) {
+    const e = SpecialPowers.wrap(error);
+    ok(false, 'error in test: ' +
+       (e.message ? (e.message + '\n' + e.stack) : e));
+  }
+  pcStrict.close();
+  pcDouble.close();
+  track.stop();
+  networkTestFinished();
+});
 </script>
-  </body>
+</body>
 </html>
--- a/dom/media/tests/mochitest/mochitest.ini
+++ b/dom/media/tests/mochitest/mochitest.ini
@@ -342,16 +342,18 @@ skip-if = (android_version == '18') # an
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_threeUnbundledConnections.html]
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_selftest.html]
 # Bug 1227781: Crash with bogus TURN server.
 [test_peerConnection_bug1227781.html]
 [test_peerConnection_stats.html]
 skip-if = toolkit == 'android' # android(Bug 1189784, timeouts on 4.3 emulator, Bug 1373858)
+[test_peerConnection_stats_relayProtocol.html]
+skip-if = toolkit == 'android' # android(Bug 1189784, timeouts on 4.3 emulator, Bug 1373858)
 [test_peerConnection_sender_and_receiver_stats.html]
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_trackless_sender_stats.html]
 skip-if = (android_version == '18') # android(Bug 1189784, timeouts on 4.3 emulator)
 [test_peerConnection_verifyDescriptions.html]
 skip-if = (android_version == '18')
 [test_fingerprinting_resistance.html]
 [test_getUserMedia_nonDefaultRate.html]
--- a/dom/media/tests/mochitest/test_peerConnection_stats.html
+++ b/dom/media/tests/mochitest/test_peerConnection_stats.html
@@ -576,19 +576,18 @@ var PC_LOCAL_TEST_LOCAL_STATS = test => 
 
 var PC_REMOTE_TEST_REMOTE_STATS = test => {
   return waitForSyncedRtcp(test.pcRemote).then(stats => {
     checkExpectedFields(stats);
     pedanticChecks(stats);
   });
 }
 
-var test;
 runNetworkTest(function (options) {
-  test = new PeerConnectionTest(options);
+  const test = new PeerConnectionTest(options);
 
   test.chain.insertAfter("PC_LOCAL_WAIT_FOR_MEDIA_FLOW",
     [PC_LOCAL_TEST_LOCAL_STATS]);
 
   test.chain.insertAfter("PC_REMOTE_WAIT_FOR_MEDIA_FLOW",
     [PC_REMOTE_TEST_REMOTE_STATS]);
 
   test.setMediaConstraints([{audio: true}, {video: true}],
new file mode 100644
--- /dev/null
+++ b/dom/media/tests/mochitest/test_peerConnection_stats_relayProtocol.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML>
+<html>
+<head>
+  <script type="application/javascript" src="nonTrickleIce.js"></script>
+  <script type="application/javascript" src="pc.js"></script>
+</head>
+<body>
+<pre id="test">
+<script type="application/javascript">
+  createHTML({
+    bug: "1435789",
+    title: "WebRTC local-candidate relayProtocol stats attribute"
+  });
+var PC_LOCAL_TEST_LOCAL_STATS_RELAYCANDIDATE = test => {
+  return test.pcLocal.getStats().then(stats => {
+    let haveRelayProtocol = {};
+    for (let [k, v] of stats) {
+      if (v.type == "local-candidate") {
+        haveRelayProtocol[v.candidateType + "-" + v.relayProtocol] = v.relayProtocol;
+      }
+    }
+    is(haveRelayProtocol["host-undefined"], undefined, "relayProtocol not set for host candidates");
+    is(haveRelayProtocol["serverreflexive-undefined"], undefined, "relayProtocol not set for serverreflexive candidates");
+    ok(haveRelayProtocol["relayed-udp"], "Has UDP relay candidate");
+    ok(haveRelayProtocol["relayed-tcp"], "Has TCP relay candidate");
+    // TURN/TLS does not work, see https://bugzilla.mozilla.org/show_bug.cgi?id=1323439
+    // With TURN/TLS working, we should have exactly five entries in haveRelayProtocol.
+    todo(haveRelayProtocol["relayed-tls"], "Has TLS relay candidate. See https://bugzilla.mozilla.org/show_bug.cgi?id=1323439");
+    is(Object.keys(haveRelayProtocol).length, 4, "All candidate types are accounted for");
+  });
+}
+
+runNetworkTest(options => {
+  // uses NAT simulator in order to get srflx candidates.
+  SpecialPowers.pushPrefEnv(
+    {
+      'set': [
+        ['media.peerconnection.nat_simulator.filtering_type', 'ENDPOINT_INDEPENDENT'],
+        ['media.peerconnection.nat_simulator.mapping_type', 'ENDPOINT_INDEPENDENT']
+      ]
+    }, function (options) {
+      const test = new PeerConnectionTest(options);
+      makeOffererNonTrickle(test.chain);
+      makeAnswererNonTrickle(test.chain);
+
+      test.chain.removeAfter("PC_LOCAL_WAIT_FOR_MEDIA_FLOW");
+      test.chain.append([PC_LOCAL_TEST_LOCAL_STATS_RELAYCANDIDATE]);
+
+      test.setMediaConstraints([{ audio: true }], [{ audio: true }]);
+      test.run();
+    })
+}, { useIceServer: true });
+</script>
+</pre>
+</body>
+</html>
--- a/dom/media/webrtc/WebrtcGlobal.h
+++ b/dom/media/webrtc/WebrtcGlobal.h
@@ -223,28 +223,30 @@ struct ParamTraits<mozilla::dom::RTCIceC
 
   static void Write(Message* aMsg, const paramType& aParam)
   {
     WriteParam(aMsg, aParam.mCandidateId);
     WriteParam(aMsg, aParam.mCandidateType);
     WriteParam(aMsg, aParam.mComponentId);
     WriteParam(aMsg, aParam.mIpAddress);
     WriteParam(aMsg, aParam.mMozLocalTransport);
+    WriteParam(aMsg, aParam.mRelayProtocol);
     WriteParam(aMsg, aParam.mPortNumber);
     WriteParam(aMsg, aParam.mTransport);
     WriteRTCStats(aMsg, aParam);
   }
 
   static bool Read(const Message* aMsg, PickleIterator* aIter, paramType* aResult)
   {
     if (!ReadParam(aMsg, aIter, &(aResult->mCandidateId)) ||
         !ReadParam(aMsg, aIter, &(aResult->mCandidateType)) ||
         !ReadParam(aMsg, aIter, &(aResult->mComponentId)) ||
         !ReadParam(aMsg, aIter, &(aResult->mIpAddress)) ||
         !ReadParam(aMsg, aIter, &(aResult->mMozLocalTransport)) ||
+        !ReadParam(aMsg, aIter, &(aResult->mRelayProtocol)) ||
         !ReadParam(aMsg, aIter, &(aResult->mPortNumber)) ||
         !ReadParam(aMsg, aIter, &(aResult->mTransport)) ||
         !ReadRTCStats(aMsg, aIter, aResult)) {
       return false;
     }
 
     return true;
  }
--- a/dom/webidl/RTCStatsReport.webidl
+++ b/dom/webidl/RTCStatsReport.webidl
@@ -150,17 +150,18 @@ enum RTCStatsIceCandidateType {
   "relayed"
 };
 
 dictionary RTCIceCandidateStats : RTCStats {
   DOMString componentId;
   DOMString candidateId;
   DOMString ipAddress;
   DOMString transport;
-  DOMString mozLocalTransport; // needs standardization
+  DOMString mozLocalTransport; // obsoleted by relayProtocol
+  DOMString relayProtocol;
   long portNumber;
   RTCStatsIceCandidateType candidateType;
 };
 
 dictionary RTCCodecStats : RTCStats {
   unsigned long payloadType;       // As used in RTP encoding.
   DOMString codec;                 // video/vp8 or equivalent
   unsigned long clockRate;
--- a/ipc/app/MozillaRuntimeMain.cpp
+++ b/ipc/app/MozillaRuntimeMain.cpp
@@ -4,33 +4,21 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "../contentproc/plugin-container.cpp"
 
 #include "mozilla/Bootstrap.h"
 #include "mozilla/WindowsDllBlocklist.h"
 
-#ifdef XP_MACOSX
-#include "mozilla/Sandbox.h"
-#endif
-
 using namespace mozilla;
 
 int
 main(int argc, char *argv[])
 {
-#ifdef XP_MACOSX
-  std::string err;
-  if (!mozilla::EarlyStartMacSandboxIfEnabled(argc, argv, err)) {
-    fprintf(stderr, "Sandbox error: %s\n", err.c_str());
-    MOZ_CRASH("Sandbox initialization failed");
-  }
-#endif
-
 #ifdef HAS_DLL_BLOCKLIST
   DllBlocklist_Initialize(eDllBlocklistInitFlagIsChildProcess);
 #endif
 
   Bootstrap::UniquePtr bootstrap = GetBootstrap();
   if (!bootstrap) {
     return 2;
   }
--- a/ipc/glue/GeckoChildProcessHost.cpp
+++ b/ipc/glue/GeckoChildProcessHost.cpp
@@ -544,22 +544,16 @@ AddAppDirToCommandLine(std::vector<std::
 
 #if defined(XP_MACOSX) && defined(MOZ_CONTENT_SANDBOX)
       // Full path to the profile dir
       nsCOMPtr<nsIFile> profileDir;
       rv = directoryService->Get(NS_APP_USER_PROFILE_50_DIR,
                                  NS_GET_IID(nsIFile),
                                  getter_AddRefs(profileDir));
       if (NS_SUCCEEDED(rv)) {
-        // If the profile doesn't exist, normalization will
-        // fail. But we don't return an error here because some
-        // tests require startup with a missing profile dir.
-        // For users, almost universally, the profile will be in
-        // the home directory and normalization isn't required.
-        mozilla::Unused << profileDir->Normalize();
         nsAutoCString path;
         MOZ_ALWAYS_SUCCEEDS(profileDir->GetNativePath(path));
         aCmdLine.push_back("-profile");
         aCmdLine.push_back(path.get());
       }
 #endif
     }
   }
--- a/js/src/vm/JSContext-inl.h
+++ b/js/src/vm/JSContext-inl.h
@@ -40,25 +40,25 @@ class ContextChecks
     {
     }
 
     /*
      * Set a breakpoint here (break js::ContextChecks::fail) to debug
      * realm/compartment/zone mismatches.
      */
     static void fail(JS::Realm* r1, JS::Realm* r2, int argIndex) {
-        MOZ_CRASH_UNSAFE_PRINTF("*** Realm mismatch %p vs. %p at argument %d\n",
+        MOZ_CRASH_UNSAFE_PRINTF("*** Realm mismatch %p vs. %p at argument %d",
                                 r1, r2, argIndex);
     }
     static void fail(JS::Compartment* c1, JS::Compartment* c2, int argIndex) {
-        MOZ_CRASH_UNSAFE_PRINTF("*** Compartment mismatch %p vs. %p at argument %d\n",
+        MOZ_CRASH_UNSAFE_PRINTF("*** Compartment mismatch %p vs. %p at argument %d",
                                 c1, c2, argIndex);
     }
     static void fail(JS::Zone* z1, JS::Zone* z2, int argIndex) {
-        MOZ_CRASH_UNSAFE_PRINTF("*** Zone mismatch %p vs. %p at argument %d\n",
+        MOZ_CRASH_UNSAFE_PRINTF("*** Zone mismatch %p vs. %p at argument %d",
                                 z1, z2, argIndex);
     }
 
     void check(JS::Realm* r, int argIndex) {
         if (r && r != realm()) {
             fail(realm(), r, argIndex);
         }
     }
@@ -89,17 +89,17 @@ class ContextChecks
                       mozilla::IsSame<T, JS::Symbol>::value,
                       "Should only be called with JSAtom* or JS::Symbol* argument");
 
 #ifdef DEBUG
         // Atoms which move across zone boundaries need to be marked in the new
         // zone, see JS_MarkCrossZoneId.
         if (zone()) {
             if (!cx->runtime()->gc.atomMarking.atomIsMarked(zone(), thing)) {
-                MOZ_CRASH_UNSAFE_PRINTF("*** Atom not marked for zone %p at argument %d\n",
+                MOZ_CRASH_UNSAFE_PRINTF("*** Atom not marked for zone %p at argument %d",
                                         zone(), argIndex);
             }
         }
 #endif
     }
 
     void check(JSString* str, int argIndex) {
         MOZ_ASSERT(JS::CellIsNotGray(str));
--- a/layout/generic/nsFrame.cpp
+++ b/layout/generic/nsFrame.cpp
@@ -2670,23 +2670,22 @@ WrapSeparatorTransform(nsDisplayListBuil
   }
 }
 
 // Try to compute a clip rect to bound the contents of the mask item
 // that will be built for |aMaskedFrame|. If we're not able to compute
 // one, return an empty Maybe.
 // The returned clip rect, if there is one, is relative to |aMaskedFrame|.
 static Maybe<nsRect>
-ComputeClipForMaskItem(nsDisplayListBuilder* aBuilder, nsIFrame* aMaskedFrame,
-                       bool aHandleOpacity)
+ComputeClipForMaskItem(nsDisplayListBuilder* aBuilder, nsIFrame* aMaskedFrame)
 {
   const nsStyleSVGReset* svgReset = aMaskedFrame->StyleSVGReset();
 
   nsSVGUtils::MaskUsage maskUsage;
-  nsSVGUtils::DetermineMaskUsage(aMaskedFrame, aHandleOpacity, maskUsage);
+  nsSVGUtils::DetermineMaskUsage(aMaskedFrame, false, maskUsage);
 
   nsPoint offsetToUserSpace = nsLayoutUtils::ComputeOffsetToUserSpace(aBuilder, aMaskedFrame);
   int32_t devPixelRatio = aMaskedFrame->PresContext()->AppUnitsPerDevPixel();
   gfxPoint devPixelOffsetToUserSpace = nsLayoutUtils::PointToGfxPoint(
       offsetToUserSpace, devPixelRatio);
   gfxMatrix cssToDevMatrix = nsSVGUtils::GetCSSPxToDevPxMatrix(aMaskedFrame);
 
   nsPoint toReferenceFrame;
@@ -2930,26 +2929,28 @@ nsIFrame::BuildDisplayListForStackingCon
   if (usingSVGEffects) {
     dirtyRect =
       nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, dirtyRect);
     visibleRect =
       nsSVGIntegrationUtils::GetRequiredSourceForInvalidArea(this, visibleRect);
     aBuilder->EnterSVGEffectsContents(&hoistedScrollInfoItemsStorage);
   }
 
-
-  bool needsActiveOpacityLayer = false;
-  // We build an opacity item if it's not going to be drawn by SVG content, or
-  // SVG effects. SVG effects won't handle the opacity if we want an active
-  // layer (for async animations), see
-  // nsSVGIntegrationsUtils::PaintMaskAndClipPath or
-  // nsSVGIntegrationsUtils::PaintFilter.
-  bool useOpacity = HasVisualOpacity(effectSet) &&
-                    !nsSVGUtils::CanOptimizeOpacity(this) &&
-                    ((needsActiveOpacityLayer = nsDisplayOpacity::NeedsActiveLayer(aBuilder, this)) || !usingSVGEffects);
+  // We build an opacity item if it's not going to be drawn by SVG content.
+  // We could in principle skip creating an nsDisplayOpacity item if
+  // nsDisplayOpacity::NeedsActiveLayer returns false and usingSVGEffects is
+  // true (the nsDisplayFilter/nsDisplayMasksAndClipPaths could handle the
+  // opacity). Since SVG has perf issues where we sometimes spend a lot of
+  // time creating display list items that might be helpful.  We'd need to
+  // restore our mechanism to do that (changed in bug 1482403), and we'd
+  // need to invalidate the frame if the value that would be return from
+  // NeedsActiveLayer was to change, which we don't currently do.
+  bool useOpacity =
+    HasVisualOpacity(effectSet) && !nsSVGUtils::CanOptimizeOpacity(this);
+
   bool useBlendMode = effects->mMixBlendMode != NS_STYLE_BLEND_NORMAL;
   bool useStickyPosition = disp->mPosition == NS_STYLE_POSITION_STICKY &&
     IsScrollFrameActive(aBuilder,
                         nsLayoutUtils::GetNearestScrollableFrame(GetParent(),
                         nsLayoutUtils::SCROLLABLE_SAME_DOC |
                         nsLayoutUtils::SCROLLABLE_INCLUDE_HIDDEN));
   bool useFixedPosition = disp->mPosition == NS_STYLE_POSITION_FIXED &&
     (nsLayoutUtils::IsFixedPosFrameInDisplayPort(this) || BuilderHasScrolledClip(aBuilder));
@@ -3011,17 +3012,17 @@ nsIFrame::BuildDisplayListForStackingCon
   }
 
   if (clipCapturedBy != ContainerItemType::eNone) {
     clipState.Clear();
   }
 
   Maybe<nsRect> clipForMask;
   if (usingMask) {
-    clipForMask = ComputeClipForMaskItem(aBuilder, this, !useOpacity);
+    clipForMask = ComputeClipForMaskItem(aBuilder, this);
   }
 
   nsDisplayListCollection set(aBuilder);
   {
     DisplayListClipState::AutoSaveRestore nestedClipState(aBuilder);
     nsDisplayListBuilder::AutoInTransformSetter
       inTransformSetter(aBuilder, inTransform);
     nsDisplayListBuilder::AutoEnterFilter
@@ -3190,25 +3191,19 @@ nsIFrame::BuildDisplayListForStackingCon
     if (clipCapturedBy == ContainerItemType::eFilter) {
       clipState.Restore();
     }
     // Revert to the post-filter dirty rect.
     aBuilder->SetVisibleRect(visibleRectOutsideSVGEffects);
 
     // Skip all filter effects while generating glyph mask.
     if (usingFilter && !aBuilder->IsForGenerateGlyphMask()) {
-      // If we are going to create a mask display item, handle opacity effect
-      // in that mask display item; Otherwise, take care of opacity in this
-      // filter display item.
-      bool handleOpacity = !usingMask && !useOpacity;
-
       /* List now emptied, so add the new list to the top. */
-      resultList.AppendToTop(
-        MakeDisplayItem<nsDisplayFilters>(aBuilder, this, &resultList,
-                                          handleOpacity));
+      resultList.AppendToTop(MakeDisplayItem<nsDisplayFilters>(
+        aBuilder, this, &resultList));
     }
 
     if (usingMask) {
       DisplayListClipState::AutoSaveRestore maskClipState(aBuilder);
       // The mask should move with aBuilder->CurrentActiveScrolledRoot(), so
       // that's the ASR we prefer to use for the mask item. However, we can
       // only do this if the mask if clipped with respect to that ASR, because
       // an item always needs to have finite bounds with respect to its ASR.
@@ -3216,19 +3211,18 @@ nsIFrame::BuildDisplayListForStackingCon
       // using containerItemASR, which is the lowest common ancestor clip of
       // the mask's contents. That's not entirely crrect, but it satisfies
       // the base requirement of the ASR system (that items have finite bounds
       // wrt. their ASR).
       const ActiveScrolledRoot* maskASR = clipForMask.isSome()
                                         ? aBuilder->CurrentActiveScrolledRoot()
                                         : containerItemASR;
       /* List now emptied, so add the new list to the top. */
-      resultList.AppendToTop(
-        MakeDisplayItem<nsDisplayMasksAndClipPaths>(aBuilder, this, &resultList,
-                                                    !useOpacity, maskASR));
+      resultList.AppendToTop(MakeDisplayItem<nsDisplayMasksAndClipPaths>(
+        aBuilder, this, &resultList, maskASR));
     }
 
     // Also add the hoisted scroll info items. We need those for APZ scrolling
     // because nsDisplayMasksAndClipPaths items can't build active layers.
     aBuilder->ExitSVGEffectsContents();
     resultList.AppendToTop(&hoistedScrollInfoItemsStorage);
     if (aCreatedContainerItem) {
       *aCreatedContainerItem = false;
@@ -3238,16 +3232,19 @@ nsIFrame::BuildDisplayListForStackingCon
   /* If the list is non-empty and there is CSS group opacity without SVG
    * effects, wrap it up in an opacity item.
    */
   if (useOpacity) {
     // Don't clip nsDisplayOpacity items. We clip their descendants instead.
     // The clip we would set on an element with opacity would clip
     // all descendant content, but some should not be clipped.
     DisplayListClipState::AutoSaveRestore opacityClipState(aBuilder);
+    const bool needsActiveOpacityLayer =
+      nsDisplayOpacity::NeedsActiveLayer(aBuilder, this);
+
     resultList.AppendToTop(
       MakeDisplayItem<nsDisplayOpacity>(aBuilder, this, &resultList,
                                         containerItemASR,
                                         opacityItemForEventsAndPluginsOnly,
                                         needsActiveOpacityLayer));
     if (aCreatedContainerItem) {
       *aCreatedContainerItem = true;
     }
--- a/layout/painting/RetainedDisplayListBuilder.cpp
+++ b/layout/painting/RetainedDisplayListBuilder.cpp
@@ -409,16 +409,23 @@ public:
 
     if (type == DisplayItemType::TYPE_CARET) {
       // The caret can change position while still being owned by the same frame
       // and we don't invalidate in that case. Use the new version since the
       // changed bounds are needed for DLBI.
       return true;
     }
 
+    if (type == DisplayItemType::TYPE_MASK ||
+        type == DisplayItemType::TYPE_FILTER ||
+        type == DisplayItemType::TYPE_SVG_WRAPPER) {
+      // SVG items have some invalidation issues, see bugs 1494110 and 1494663.
+      return true;
+    }
+
     return false;
   }
 
   RetainedDisplayList Finalize()
   {
     for (size_t i = 0; i < mOldDAG.Length(); i++) {
       if (mOldItems[i].IsUsed()) {
         continue;
--- a/layout/painting/nsDisplayList.cpp
+++ b/layout/painting/nsDisplayList.cpp
@@ -6534,16 +6534,40 @@ nsDisplayOpacity::ApplyOpacityToChildren
   for (uint32_t i = 0; i < childCount; i++) {
     children[i].item->ApplyOpacity(aBuilder, mOpacity, mClipChain);
   }
 
   mChildOpacityState = ChildOpacityState::Applied;
   return true;
 }
 
+/**
+ * Returns true if this nsDisplayOpacity contains only a filter or a mask item
+ * that has the same frame as the opacity item. In this case the opacity item
+ * can be optimized away.
+ */
+bool
+nsDisplayOpacity::IsEffectsWrapper() const
+{
+  if (mList.Count() != 1) {
+    return false;
+  }
+
+  const nsDisplayItem* item = mList.GetBottom();
+
+  if (item->Frame() != mFrame) {
+    // The effect item needs to have the same frame as the opacity item.
+    return false;
+  }
+
+  const DisplayItemType type = item->GetType();
+  return type == DisplayItemType::TYPE_MASK ||
+         type == DisplayItemType::TYPE_FILTER;
+}
+
 bool
 nsDisplayOpacity::ShouldFlattenAway(nsDisplayListBuilder* aBuilder)
 {
   if (mFrame->GetPrevContinuation() || mFrame->GetNextContinuation() ||
       mFrame->HasAnyStateBits(NS_FRAME_PART_OF_IBSPLIT)) {
     // If we've been split, then we might need to merge, so
     // don't flatten us away.
     return false;
@@ -6556,16 +6580,23 @@ nsDisplayOpacity::ShouldFlattenAway(nsDi
     // might trigger repainting).
     return false;
   }
 
   if (mList.IsEmpty()) {
     return false;
   }
 
+  if (IsEffectsWrapper()) {
+    MOZ_ASSERT(nsSVGIntegrationUtils::UsingEffectsForFrame(mFrame));
+    static_cast<nsDisplayEffectsBase*>(mList.GetBottom())->SetHandleOpacity();
+    mChildOpacityState = ChildOpacityState::Applied;
+    return true;
+  }
+
   // Return true if we successfully applied opacity to child items, or if
   // WebRender is not in use. In the latter case, the opacity gets flattened and
   // applied during layer building.
   return ApplyOpacityToChildren(aBuilder) || !gfxVars::UseWebRender();
 }
 
 nsDisplayItem::LayerState
 nsDisplayOpacity::GetLayerState(nsDisplayListBuilder* aBuilder,
@@ -9440,35 +9471,33 @@ nsCharClipDisplayItem::ComputeInvalidati
     aInvalidRegion->Or(oldRect, newRect);
   }
 }
 
 nsDisplayEffectsBase::nsDisplayEffectsBase(
   nsDisplayListBuilder* aBuilder,
   nsIFrame* aFrame,
   nsDisplayList* aList,
-  bool aHandleOpacity,
   const ActiveScrolledRoot* aActiveScrolledRoot,
   bool aClearClipChain)
   : nsDisplayWrapList(aBuilder,
                       aFrame,
                       aList,
                       aActiveScrolledRoot,
                       aClearClipChain)
-  , mHandleOpacity(aHandleOpacity)
+  , mHandleOpacity(false)
 {
   MOZ_COUNT_CTOR(nsDisplayEffectsBase);
 }
 
 nsDisplayEffectsBase::nsDisplayEffectsBase(nsDisplayListBuilder* aBuilder,
                                            nsIFrame* aFrame,
-                                           nsDisplayList* aList,
-                                           bool aHandleOpacity)
+                                           nsDisplayList* aList)
   : nsDisplayWrapList(aBuilder, aFrame, aList)
-  , mHandleOpacity(aHandleOpacity)
+  , mHandleOpacity(false)
 {
   MOZ_COUNT_CTOR(nsDisplayEffectsBase);
 }
 
 nsRegion
 nsDisplayEffectsBase::GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                                       bool* aSnap) const
 {
@@ -9507,17 +9536,19 @@ nsDisplayEffectsBase::ComputeInvalidatio
   const nsDisplayItemGeometry* aGeometry,
   nsRegion* aInvalidRegion) const
 {
   auto* geometry = static_cast<const nsDisplaySVGEffectGeometry*>(aGeometry);
   bool snap;
   nsRect bounds = GetBounds(aBuilder, &snap);
   if (geometry->mFrameOffsetToReferenceFrame != ToReferenceFrame() ||
       geometry->mUserSpaceOffset != UserSpaceOffset() ||
-      !geometry->mBBox.IsEqualInterior(BBoxInUserSpace())) {
+      !geometry->mBBox.IsEqualInterior(BBoxInUserSpace()) ||
+      geometry->mOpacity != mFrame->StyleEffects()->mOpacity ||
+      geometry->mHandleOpacity != ShouldHandleOpacity()) {
     // Filter and mask output can depend on the location of the frame's user
     // space and on the frame's BBox. We need to invalidate if either of these
     // change relative to the reference frame.
     // Invalidations from our inactive layer manager are not enough to catch
     // some of these cases because filters can produce output even if there's
     // nothing in the filter input.
     aInvalidRegion->Or(bounds, geometry->mBounds);
   }
@@ -9628,22 +9659,20 @@ ComputeMaskGeometry(PaintFramesParams& a
   IntRect result = ComputeClipExtsInDeviceSpace(ctx);
   aParams.maskRect = result;
 }
 
 nsDisplayMasksAndClipPaths::nsDisplayMasksAndClipPaths(
                               nsDisplayListBuilder* aBuilder,
                               nsIFrame* aFrame,
                               nsDisplayList* aList,
-                              bool aHandleOpacity,
                               const ActiveScrolledRoot* aActiveScrolledRoot)
   : nsDisplayEffectsBase(aBuilder,
                          aFrame,
                          aList,
-                         aHandleOpacity,
                          aActiveScrolledRoot,
                          true)
 {
   MOZ_COUNT_CTOR(nsDisplayMasksAndClipPaths);
 
   nsPresContext* presContext = mFrame->PresContext();
   uint32_t flags =
     aBuilder->GetBackgroundPaintFlags() | nsCSSRendering::PAINTBG_MASK_IMAGE;
@@ -9831,21 +9860,16 @@ nsDisplayMasksAndClipPaths::ComputeInval
   nsDisplayEffectsBase::ComputeInvalidationRegion(
     aBuilder, aGeometry, aInvalidRegion);
 
   auto* geometry =
     static_cast<const nsDisplayMasksAndClipPathsGeometry*>(aGeometry);
   bool snap;
   nsRect bounds = GetBounds(aBuilder, &snap);
 
-  if (mFrame->StyleEffects()->mOpacity != geometry->mOpacity ||
-      mHandleOpacity != geometry->mHandleOpacity) {
-    aInvalidRegion->Or(*aInvalidRegion, bounds);
-  }
-
   if (mDestRects.Length() != geometry->mDestRects.Length()) {
     aInvalidRegion->Or(bounds, geometry->mBounds);
   } else {
     for (size_t i = 0; i < mDestRects.Length(); i++) {
       if (!mDestRects[i].IsEqualInterior(geometry->mDestRects[i])) {
         aInvalidRegion->Or(bounds, geometry->mBounds);
         break;
       }
@@ -10027,17 +10051,17 @@ nsDisplayMasksAndClipPaths::GetClipWithR
 #ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayMasksAndClipPaths::PrintEffects(nsACString& aTo)
 {
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
   bool first = true;
   aTo += " effects=(";
-  if (mFrame->StyleEffects()->mOpacity != 1.0f && mHandleOpacity) {
+  if (mHandleOpacity) {
     first = false;
     aTo += nsPrintfCString("opacity(%f)", mFrame->StyleEffects()->mOpacity);
   }
   nsSVGClipPathFrame* clipPathFrame;
   // XXX Check return value?
   SVGObserverUtils::GetAndObserveClipPath(firstFrame, &clipPathFrame);
   if (clipPathFrame) {
     if (!first) {
@@ -10064,19 +10088,18 @@ nsDisplayMasksAndClipPaths::PrintEffects
     aTo += "mask";
   }
   aTo += ")";
 }
 #endif
 
 nsDisplayFilters::nsDisplayFilters(nsDisplayListBuilder* aBuilder,
                                    nsIFrame* aFrame,
-                                   nsDisplayList* aList,
-                                   bool aHandleOpacity)
-  : nsDisplayEffectsBase(aBuilder, aFrame, aList, aHandleOpacity)
+                                   nsDisplayList* aList)
+  : nsDisplayEffectsBase(aBuilder, aFrame, aList)
   , mEffectsBounds(aFrame->GetVisualOverflowRectRelativeToSelf())
 {
   MOZ_COUNT_CTOR(nsDisplayFilters);
 }
 
 already_AddRefed<Layer>
 nsDisplayFilters::BuildLayer(
   nsDisplayListBuilder* aBuilder,
@@ -10315,17 +10338,17 @@ nsDisplayFilters::CreateWebRenderCommand
 #ifdef MOZ_DUMP_PAINTING
 void
 nsDisplayFilters::PrintEffects(nsACString& aTo)
 {
   nsIFrame* firstFrame =
     nsLayoutUtils::FirstContinuationOrIBSplitSibling(mFrame);
   bool first = true;
   aTo += " effects=(";
-  if (mFrame->StyleEffects()->mOpacity != 1.0f && mHandleOpacity) {
+  if (mHandleOpacity) {
     first = false;
     aTo += nsPrintfCString("opacity(%f)", mFrame->StyleEffects()->mOpacity);
   }
   // We may exist for a mix of CSS filter functions and/or references to SVG
   // filters.  If we have invalid references to SVG filters then we paint
   // nothing, but otherwise we will apply one or more filters.
   if (SVGObserverUtils::GetAndObserveFilters(firstFrame, nullptr) !=
         SVGObserverUtils::eHasRefsSomeInvalid) {
--- a/layout/painting/nsDisplayList.h
+++ b/layout/painting/nsDisplayList.h
@@ -5785,16 +5785,17 @@ public:
     const StackingContextHelper& aSc,
     mozilla::layers::WebRenderLayerManager* aManager,
     nsDisplayListBuilder* aDisplayListBuilder) override;
 
   float GetOpacity() const { return mOpacity; }
 
 private:
   bool ApplyOpacityToChildren(nsDisplayListBuilder* aBuilder);
+  bool IsEffectsWrapper() const;
 
   float mOpacity;
   bool mForEventsAndPluginsOnly : 1;
   enum class ChildOpacityState : uint8_t
   {
     // Our child list has changed since the last time ApplyOpacityToChildren was
     // called.
     Unknown,
@@ -6683,23 +6684,21 @@ private:
  * A base class for different effects types.
  */
 class nsDisplayEffectsBase : public nsDisplayWrapList
 {
 public:
   nsDisplayEffectsBase(nsDisplayListBuilder* aBuilder,
                        nsIFrame* aFrame,
                        nsDisplayList* aList,
-                       bool aHandleOpacity,
                        const ActiveScrolledRoot* aActiveScrolledRoot,
                        bool aClearClipChain = false);
   nsDisplayEffectsBase(nsDisplayListBuilder* aBuilder,
                        nsIFrame* aFrame,
-                       nsDisplayList* aList,
-                       bool aHandleOpacity);
+                       nsDisplayList* aList);
 
   nsDisplayEffectsBase(nsDisplayListBuilder* aBuilder,
                        const nsDisplayEffectsBase& aOther)
     : nsDisplayWrapList(aBuilder, aOther)
     , mEffectsBounds(aOther.mEffectsBounds)
     , mHandleOpacity(aOther.mHandleOpacity)
   {
     MOZ_COUNT_CTOR(nsDisplayEffectsBase);
@@ -6711,22 +6710,25 @@ public:
 
   nsRegion GetOpaqueRegion(nsDisplayListBuilder* aBuilder,
                            bool* aSnap) const override;
   void HitTest(nsDisplayListBuilder* aBuilder,
                const nsRect& aRect,
                HitTestState* aState,
                nsTArray<nsIFrame*>* aOutFrames) override;
 
+  void RestoreState() override { mHandleOpacity = false; }
+
   bool ShouldFlattenAway(nsDisplayListBuilder* aBuilder) override
   {
     return false;
   }
 
-  bool ShouldHandleOpacity() { return mHandleOpacity; }
+  void SetHandleOpacity() { mHandleOpacity = true; }
+  bool ShouldHandleOpacity() const { return mHandleOpacity; }
 
   gfxRect BBoxInUserSpace() const;
   gfxPoint UserSpaceOffset() const;
 
   void ComputeInvalidationRegion(nsDisplayListBuilder* aBuilder,
                                  const nsDisplayItemGeometry* aGeometry,
                                  nsRegion* aInvalidRegion) const override;
 
@@ -6752,17 +6754,16 @@ protected:
 class nsDisplayMasksAndClipPaths : public nsDisplayEffectsBase
 {
 public:
   typedef mozilla::layers::ImageLayer ImageLayer;
 
   nsDisplayMasksAndClipPaths(nsDisplayListBuilder* aBuilder,
                              nsIFrame* aFrame,
                              nsDisplayList* aList,
-                             bool aHandleOpacity,
                              const ActiveScrolledRoot* aActiveScrolledRoot);
   nsDisplayMasksAndClipPaths(nsDisplayListBuilder* aBuilder,
                              const nsDisplayMasksAndClipPaths& aOther)
     : nsDisplayEffectsBase(aBuilder, aOther)
     , mDestRects(aOther.mDestRects)
   {
   }
 
@@ -6864,18 +6865,17 @@ private:
  * Note that the filters may just be simple CSS filter functions.  That is,
  * they won't necessarily be references to SVG 'filter' elements.
  */
 class nsDisplayFilters : public nsDisplayEffectsBase
 {
 public:
   nsDisplayFilters(nsDisplayListBuilder* aBuilder,
                    nsIFrame* aFrame,
-                   nsDisplayList* aList,
-                   bool aHandleOpacity);
+                   nsDisplayList* aList);
 
   nsDisplayFilters(nsDisplayListBuilder* aBuilder,
                    const nsDisplayFilters& aOther)
     : nsDisplayEffectsBase(aBuilder, aOther)
     , mEffectsBounds(aOther.mEffectsBounds)
   {
   }
 
--- a/layout/painting/nsDisplayListInvalidation.cpp
+++ b/layout/painting/nsDisplayListInvalidation.cpp
@@ -126,34 +126,34 @@ nsDisplaySolidColorRegionGeometry::MoveB
 
 nsDisplaySVGEffectGeometry::nsDisplaySVGEffectGeometry(
   nsDisplayEffectsBase* aItem,
   nsDisplayListBuilder* aBuilder)
   : nsDisplayItemGeometry(aItem, aBuilder)
   , mBBox(aItem->BBoxInUserSpace())
   , mUserSpaceOffset(aItem->UserSpaceOffset())
   , mFrameOffsetToReferenceFrame(aItem->ToReferenceFrame())
+  , mOpacity(aItem->Frame()->StyleEffects()->mOpacity)
+  , mHandleOpacity(aItem->ShouldHandleOpacity())
 {
 }
 
 void
 nsDisplaySVGEffectGeometry::MoveBy(const nsPoint& aOffset)
 {
   mBounds.MoveBy(aOffset);
   mFrameOffsetToReferenceFrame += aOffset;
 }
 
 nsDisplayMasksAndClipPathsGeometry::nsDisplayMasksAndClipPathsGeometry(
                                       nsDisplayMasksAndClipPaths* aItem,
                                       nsDisplayListBuilder* aBuilder)
   : nsDisplaySVGEffectGeometry(aItem, aBuilder)
   , nsImageGeometryMixin(aItem, aBuilder)
   , mDestRects(aItem->GetDestRects())
-  , mOpacity(aItem->Frame()->StyleEffects()->mOpacity)
-  , mHandleOpacity(aItem->ShouldHandleOpacity())
 {
 }
 
 nsDisplayFiltersGeometry::nsDisplayFiltersGeometry(nsDisplayFilters* aItem,
                                                    nsDisplayListBuilder* aBuilder)
   : nsDisplaySVGEffectGeometry(aItem, aBuilder)
   , nsImageGeometryMixin(aItem, aBuilder)
 {
--- a/layout/painting/nsDisplayListInvalidation.h
+++ b/layout/painting/nsDisplayListInvalidation.h
@@ -297,34 +297,34 @@ public:
   nsDisplaySVGEffectGeometry(nsDisplayEffectsBase* aItem,
                              nsDisplayListBuilder* aBuilder);
 
   void MoveBy(const nsPoint& aOffset) override;
 
   gfxRect mBBox;
   gfxPoint mUserSpaceOffset;
   nsPoint mFrameOffsetToReferenceFrame;
+  float mOpacity;
+  bool mHandleOpacity;
 };
 
 class nsDisplayMasksAndClipPathsGeometry
   : public nsDisplaySVGEffectGeometry
   , public nsImageGeometryMixin<nsDisplayMasksAndClipPathsGeometry>
 {
 public:
   nsDisplayMasksAndClipPathsGeometry(nsDisplayMasksAndClipPaths* aItem,
                                      nsDisplayListBuilder* aBuilder);
 
   bool InvalidateForSyncDecodeImages() const override
   {
     return ShouldInvalidateToSyncDecodeImages();
   }
 
   nsTArray<nsRect> mDestRects;
-  float mOpacity;
-  bool mHandleOpacity;
 };
 
 class nsDisplayFiltersGeometry
   : public nsDisplaySVGEffectGeometry
   , public nsImageGeometryMixin<nsDisplayFiltersGeometry>
 {
 public:
   nsDisplayFiltersGeometry(nsDisplayFilters* aItem,
--- a/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
+++ b/media/webrtc/signaling/src/peerconnection/PeerConnectionMedia.cpp
@@ -1151,16 +1151,20 @@ static void ToRTCIceCandidateStats(
     cand.mIpAddress.Construct(
         NS_ConvertASCIItoUTF16(candidate.cand_addr.host.c_str()));
     cand.mPortNumber.Construct(candidate.cand_addr.port);
     cand.mTransport.Construct(
         NS_ConvertASCIItoUTF16(candidate.cand_addr.transport.c_str()));
     if (candidateType == RTCStatsType::Local_candidate) {
       cand.mMozLocalTransport.Construct(
           NS_ConvertASCIItoUTF16(candidate.local_addr.transport.c_str()));
+      if (RTCStatsIceCandidateType(candidate.type) == RTCStatsIceCandidateType::Relayed) {
+        cand.mRelayProtocol.Construct(
+            NS_ConvertASCIItoUTF16(candidate.local_addr.transport.c_str()));
+      }
     }
     report->mIceCandidateStats.Value().AppendElement(cand, fallible);
     if (candidate.trickled) {
       report->mTrickledIceCandidateStats.Value().AppendElement(cand, fallible);
     }
   }
 }
 
--- a/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp
+++ b/media/webrtc/signaling/src/peerconnection/WebrtcGlobalInformation.cpp
@@ -975,19 +975,19 @@ static uint32_t GetCandidateIpAndTranspo
     CANDIDATE_BITMASK_UDP = 1,
     CANDIDATE_BITMASK_TCP = 1 << 1,
     CANDIDATE_BITMASK_IPV6 = 1 << 2,
   };
 
   uint32_t res = 0;
 
   nsAutoCString transport;
-  // prefer local transport for local relay candidates
-  if (cand->mMozLocalTransport.WasPassed()) {
-    transport.Assign(NS_ConvertUTF16toUTF8(cand->mMozLocalTransport.Value()));
+  // prefer relay transport for local relay candidates
+  if (cand->mRelayProtocol.WasPassed()) {
+    transport.Assign(NS_ConvertUTF16toUTF8(cand->mRelayProtocol.Value()));
   } else {
     transport.Assign(NS_ConvertUTF16toUTF8(cand->mTransport.Value()));
   }
   if (transport == kNrIceTransportUdp) {
     res |= CANDIDATE_BITMASK_UDP;
   } else if (transport == kNrIceTransportTcp) {
     res |= CANDIDATE_BITMASK_TCP;
   }
--- a/mfbt/tests/moz.build
+++ b/mfbt/tests/moz.build
@@ -4,16 +4,18 @@
 # 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/.
 
 if CONFIG['MOZ_WIDGET_TOOLKIT']:
     TEST_DIRS += [
         'gtest',
     ]
 
+# Important: for these tests to be run, they also need to be added
+# to testing/cppunittest.ini.
 CppUnitTests([
     'TestAlgorithm',
     'TestArray',
     'TestArrayUtils',
     'TestAtomics',
     'TestBinarySearch',
     'TestBloomFilter',
     'TestBufferList',
--- a/security/sandbox/mac/Sandbox.h
+++ b/security/sandbox/mac/Sandbox.h
@@ -40,50 +40,40 @@ typedef struct _MacSandboxPluginInfo {
 
 typedef struct _MacSandboxInfo {
   _MacSandboxInfo()
     : type(MacSandboxType_Default)
     , level(0)
     , hasFilePrivileges(false)
     , hasSandboxedProfile(false)
     , hasAudio(false)
-    , hasWindowServer(false)
     , shouldLog(true)
   {
   }
   _MacSandboxInfo(const struct _MacSandboxInfo& other) = default;
 
   MacSandboxType type;
   int32_t level;
   bool hasFilePrivileges;
   bool hasSandboxedProfile;
   bool hasAudio;
-  bool hasWindowServer;
   MacSandboxPluginInfo pluginInfo;
   std::string appPath;
   std::string appBinaryPath;
   std::string appDir;
   std::string profileDir;
   std::string debugWriteDir;
 
   std::string testingReadPath1;
   std::string testingReadPath2;
   std::string testingReadPath3;
   std::string testingReadPath4;
 
-  std::string parentPort;
-  std::string crashServerPort;
-
   bool shouldLog;
 } MacSandboxInfo;
 
 namespace mozilla {
 
 bool StartMacSandbox(MacSandboxInfo const &aInfo, std::string &aErrorMessage);
-bool EarlyStartMacSandboxIfEnabled(int aArgc, char** aArgv,
-                                   std::string &aErrorMessage);
-#ifdef DEBUG
-void AssertMacSandboxEnabled();
-#endif /* DEBUG */
 
 } // namespace mozilla
 
 #endif // mozilla_Sandbox_h
--- a/security/sandbox/mac/Sandbox.mm
+++ b/security/sandbox/mac/Sandbox.mm
@@ -10,18 +10,16 @@
 // linking to nsCocoaFeatures.mm in XUL.
 
 #include "Sandbox.h"
 
 #include <stdio.h>
 #include <stdlib.h>
 #include <CoreFoundation/CoreFoundation.h>
 
-#include <iostream>
-#include <sstream>
 #include <vector>
 
 #include "mozilla/Assertions.h"
 
 // XXX There are currently problems with the /usr/include/sandbox.h file on
 // some/all of the Macs in Mozilla's build system. Further,
 // sandbox_init_with_parameters is not included in the header.  For the time
 // being (until this problem is resolved), we refer directly to what we need
@@ -221,32 +219,26 @@ bool StartMacSandbox(MacSandboxInfo cons
       params.push_back("SANDBOX_LEVEL_2");
       params.push_back(aInfo.level == 2 ? "TRUE" : "FALSE");
       params.push_back("SANDBOX_LEVEL_3");
       params.push_back(aInfo.level == 3 ? "TRUE" : "FALSE");
       params.push_back("MAC_OS_MINOR");
       params.push_back(macOSMinor.c_str());
       params.push_back("APP_PATH");
       params.push_back(aInfo.appPath.c_str());
+      params.push_back("APP_BINARY_PATH");
+      params.push_back(aInfo.appBinaryPath.c_str());
+      params.push_back("APP_DIR");
+      params.push_back(aInfo.appDir.c_str());
       params.push_back("PROFILE_DIR");
       params.push_back(aInfo.profileDir.c_str());
       params.push_back("HOME_PATH");
       params.push_back(getenv("HOME"));
       params.push_back("HAS_SANDBOXED_PROFILE");
       params.push_back(aInfo.hasSandboxedProfile ? "TRUE" : "FALSE");
-      params.push_back("HAS_WINDOW_SERVER");
-      params.push_back(aInfo.hasWindowServer ? "TRUE" : "FALSE");
-      if (!aInfo.parentPort.empty()) {
-        params.push_back("PARENT_PORT");
-        params.push_back(aInfo.parentPort.c_str());
-      }
-      if (!aInfo.crashServerPort.empty()) {
-        params.push_back("CRASH_PORT");
-        params.push_back(aInfo.crashServerPort.c_str());
-      }
       if (!aInfo.testingReadPath1.empty()) {
         params.push_back("TESTING_READ_PATH1");
         params.push_back(aInfo.testingReadPath1.c_str());
       }
       if (!aInfo.testingReadPath2.empty()) {
         params.push_back("TESTING_READ_PATH2");
         params.push_back(aInfo.testingReadPath2.c_str());
       }
@@ -325,191 +317,9 @@ bool StartMacSandbox(MacSandboxInfo cons
   }
   if (rv) {
     return false;
   }
 
   return true;
 }
 
-/*
- * Fill |aInfo| with content sandbox params parsed from the provided
- * command line arguments. Return false if any sandbox parameters needed
- * for early startup of the sandbox are not present in the arguments.
- */
-bool
-GetContentSandboxParamsFromArgs(int aArgc, char** aArgv, MacSandboxInfo& aInfo)
-{
-  // Ensure we find these paramaters in the command
-  // line arguments. Return false if any are missing.
-  bool foundSandboxLevel = false;
-  bool foundValidSandboxLevel = false;
-  bool foundParentPort = false;
-  bool foundAppPath = false;
-
-  // Read access directories used in testing
-  int nTestingReadPaths = 0;
-  std::string testingReadPaths[MAX_TESTING_READ_PATHS] = {};
-
-  // Collect sandbox params from CLI arguments
-  for (int i = 0; i < aArgc; i++) {
-
-    if ((strcmp(aArgv[i], "-sbLevel") == 0) && (i + 1 < aArgc)) {
-      std::stringstream ss(aArgv[i+1]);
-      int level = 0;
-      ss >> level;
-      foundSandboxLevel = true;
-      aInfo.level = level;
-      foundValidSandboxLevel = level > 0 && level <= 3 ? true : false;
-      if (!foundValidSandboxLevel) {
-        break;
-      }
-      i++;
-      continue;
-    }
-
-    if (strcmp(aArgv[i], "-sbLogging") == 0) {
-      aInfo.shouldLog = true;
-      continue;
-    }
-
-    if (strcmp(aArgv[i], "-sbAllowFileAccess") == 0) {
-      aInfo.hasFilePrivileges = true;
-      continue;
-    }
-
-    if (strcmp(aArgv[i], "-sbAllowAudio") == 0) {
-      aInfo.hasAudio = true;
-      continue;
-    }
-
-    if (strcmp(aArgv[i], "-sbAllowWindowServer") == 0) {
-      aInfo.hasWindowServer = true;
-      continue;
-    }
-
-    if ((strcmp(aArgv[i], "-sbAppPath") == 0) && (i + 1 < aArgc)) {
-      foundAppPath = true;
-      aInfo.appPath.assign(aArgv[i+1]);
-      i++;
-      continue;
-    }
-
-    if ((strcmp(aArgv[i], "-sbTestingReadPath") == 0) && (i + 1 < aArgc)) {
-      MOZ_ASSERT(nTestingReadPaths < MAX_TESTING_READ_PATHS);
-      testingReadPaths[nTestingReadPaths] = aArgv[i+1];
-      nTestingReadPaths++;
-      i++;
-      continue;
-    }
-
-    if ((strcmp(aArgv[i], "-profile") == 0) && (i + 1 < aArgc)) {
-      aInfo.hasSandboxedProfile = true;
-      aInfo.profileDir.assign(aArgv[i+1]);
-      i++;
-      continue;
-    }
-
-#ifdef DEBUG
-    if ((strcmp(aArgv[i], "-sbDebugWriteDir") == 0) && (i + 1 < aArgc)) {
-      aInfo.debugWriteDir.assign(aArgv[i+1]);
-      i++;
-      continue;
-    }
-#endif // DEBUG
-
-    // Handle positional arguments
-    if (strstr(aArgv[i], "org.mozilla.machname") != NULL) {
-      foundParentPort = true;
-      aInfo.parentPort.assign(aArgv[i]);
-      continue;
-    }
-
-    if (strstr(aArgv[i], "gecko-crash-server-pipe") != NULL) {
-      aInfo.crashServerPort.assign(aArgv[i]);
-      continue;
-    }
-  }
-
-  if (!foundSandboxLevel) {
-    fprintf(stderr, "Content sandbox disabled due to "
-                    "missing sandbox CLI level parameter.\n");
-    return false;
-  }
-
-  if (!foundValidSandboxLevel) {
-    fprintf(stderr, "Content sandbox disabled due to invalid"
-                    "sandbox level (%d)\n", aInfo.level);
-    return false;
-  }
-
-  if (!foundParentPort) {
-    fprintf(stderr, "Content sandbox disabled due to "
-                    "missing sandbox CLI parent port parameter.\n");
-    return false;
-  }
-
-  if (!foundAppPath) {
-    fprintf(stderr, "Content sandbox disabled due to "
-                    "missing sandbox CLI app path parameter.\n");
-    return false;
-  }
-
-  aInfo.testingReadPath1 = testingReadPaths[0];
-  aInfo.testingReadPath2 = testingReadPaths[1];
-  aInfo.testingReadPath3 = testingReadPaths[2];
-  aInfo.testingReadPath4 = testingReadPaths[3];
-
-  return true;
-}
-
-/*
- * Returns true if no errors were encountered or if early sandbox startup is
- * not enabled for this process. Returns false if an error was encountered.
- */
-bool
-EarlyStartMacSandboxIfEnabled(int aArgc, char** aArgv,
-                              std::string &aErrorMessage)
-{
-  bool earlyStartupEnabled = false;
-
-  // Check for the -sbStartup CLI parameter which
-  // indicates we should start the sandbox now.
-  for (int i = 0; i < aArgc; i++) {
-    if (strcmp(aArgv[i], "-sbStartup") == 0) {
-      earlyStartupEnabled = true;
-      break;
-    }
-  }
-
-  // The sandbox will be started later when/if parent
-  // sends the sandbox startup message. Return true
-  // indicating no errors occurred.
-  if (!earlyStartupEnabled) {
-    return true;
-  }
-
-  MacSandboxInfo info;
-  info.type = MacSandboxType_Content;
-  if (!GetContentSandboxParamsFromArgs(aArgc, aArgv, info)) {
-    return false;
-  }
-
-  return StartMacSandbox(info, aErrorMessage);
-}
-
-#ifdef DEBUG
-/*
- * Ensures that a process sandbox is enabled by attempting to enable
- * a new sandbox policy and ASSERT'ing that this fails. This depends
- * on sandbox_init() failing when called again after a sandbox has
- * already been successfully enabled.
- */
-void
-AssertMacSandboxEnabled()
-{
-  char *errorbuf = NULL;
-  int rv = sandbox_init("(version 1)(deny default)", 0, &errorbuf);
-  MOZ_ASSERT(rv != 0);
-}
-#endif /* DEBUG */
-
 } // namespace mozilla
--- a/security/sandbox/mac/SandboxPolicies.h
+++ b/security/sandbox/mac/SandboxPolicies.h
@@ -1,18 +1,16 @@
 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef mozilla_SandboxPolicies_h
 #define mozilla_SandboxPolicies_h
 
-#define MAX_TESTING_READ_PATHS 4
-
 namespace mozilla {
 
 static const char pluginSandboxRules[] = R"SANDBOX_LITERAL(
   (version 1)
 
   (define should-log (param "SHOULD_LOG"))
   (define plugin-binary-path (param "PLUGIN_BINARY_PATH"))
   (define app-path (param "APP_PATH"))
@@ -47,27 +45,26 @@ static const char contentSandboxRules[] 
   (version 1)
 
   (define should-log (param "SHOULD_LOG"))
   (define sandbox-level-1 (param "SANDBOX_LEVEL_1"))
   (define sandbox-level-2 (param "SANDBOX_LEVEL_2"))
   (define sandbox-level-3 (param "SANDBOX_LEVEL_3"))
   (define macosMinorVersion (string->number (param "MAC_OS_MINOR")))
   (define appPath (param "APP_PATH"))
+  (define appBinaryPath (param "APP_BINARY_PATH"))
+  (define appdir-path (param "APP_DIR"))
   (define hasProfileDir (param "HAS_SANDBOXED_PROFILE"))
   (define profileDir (param "PROFILE_DIR"))
-  (define hasWindowServer (param "HAS_WINDOW_SERVER"))
   (define home-path (param "HOME_PATH"))
   (define debugWriteDir (param "DEBUG_WRITE_DIR"))
   (define testingReadPath1 (param "TESTING_READ_PATH1"))
   (define testingReadPath2 (param "TESTING_READ_PATH2"))
   (define testingReadPath3 (param "TESTING_READ_PATH3"))
   (define testingReadPath4 (param "TESTING_READ_PATH4"))
-  (define parentPort (param "PARENT_PORT"))
-  (define crashPort (param "CRASH_PORT"))
 
   (if (string=? should-log "TRUE")
     (deny default)
     (deny default (with no-log)))
   (debug deny)
   ; These are not included in (deny default)
   (deny process-info*)
   ; This isn't available in some older macOS releases.
@@ -79,22 +76,22 @@ static const char contentSandboxRules[] 
   (if (defined? 'file-map-executable)
     (deny file-map-executable))
 
   (if (defined? 'file-map-executable)
     (allow file-map-executable file-read*
       (subpath "/System")
       (subpath "/usr/lib")
       (subpath "/Library/GPUBundles")
-      (subpath appPath))
+      (subpath appdir-path))
     (allow file-read*
         (subpath "/System")
         (subpath "/usr/lib")
         (subpath "/Library/GPUBundles")
-        (subpath appPath)))
+        (subpath appdir-path)))
 
   ; Allow read access to standard system paths.
   (allow file-read*
     (require-all (file-mode #o0004)
       (require-any
         (subpath "/Library/Filesystems/NetFSPlugins")
         (subpath "/usr/share"))))
 
@@ -183,24 +180,16 @@ static const char contentSandboxRules[] 
   (define (allow-shared-list domain)
     (allow file-read*
            (home-regex (string-append "/Library/Preferences/" (regex-quote domain)))))
 
   (allow ipc-posix-shm-read-data ipc-posix-shm-write-data
     (ipc-posix-name-regex #"^CFPBS:"))
 
   (allow signal (target self))
-  (if (string? parentPort)
-    (allow mach-lookup (global-name parentPort)))
-  (if (string? crashPort)
-    (allow mach-lookup (global-name crashPort)))
-  (if (string=? hasWindowServer "TRUE")
-    (allow mach-lookup (global-name "com.apple.windowserver.active")))
-  (allow mach-lookup (global-name "com.apple.coreservices.launchservicesd"))
-  (allow mach-lookup (global-name "com.apple.lsd.mapdb"))
 
   (if (>= macosMinorVersion 13)
     (allow mach-lookup
       ; bug 1392988
       (xpc-service-name "com.apple.coremedia.videodecoder")
       (xpc-service-name "com.apple.coremedia.videoencoder")))
 
 ; bug 1312273
@@ -236,17 +225,19 @@ static const char contentSandboxRules[] 
       (literal "/")
       (literal "/private/tmp")
       (literal "/private/var/tmp")
       (home-literal "/.CFUserTextEncoding")
       (home-literal "/Library/Preferences/com.apple.DownloadAssessment.plist")
       (home-subpath "/Library/Colors")
       (home-subpath "/Library/Keyboard Layouts")
       (home-subpath "/Library/Input Methods")
-      (home-subpath "/Library/Spelling"))
+      (home-subpath "/Library/Spelling")
+      (literal appPath)
+      (literal appBinaryPath))
 
   (if (defined? 'file-map-executable)
     (begin
       (when testingReadPath1
         (allow file-read* file-map-executable (subpath testingReadPath1)))
       (when testingReadPath2
         (allow file-read* file-map-executable (subpath testingReadPath2)))
       (when testingReadPath3
--- a/testing/cppunittest.ini
+++ b/testing/cppunittest.ini
@@ -1,62 +1,74 @@
 [ShowSSEConfig]
 [TestPrintf]
 [TestAppShellSteadyState]
+[TestAlgorithm]
 [TestArray]
 [TestArrayUtils]
 [TestAtomics]
 [TestBinarySearch]
 [TestBloomFilter]
+[TestBufferList]
 [TestCasting]
 [TestCeilingFloor]
 [TestCheckedInt]
 [TestCountPopulation]
 [TestCountZeroes]
 [TestDefineEnum]
+[TestDoublyLinkedList]
 [TestDllInterceptor]
 skip-if = os != 'win'
 [TestEndian]
 [TestEnumeratedArray]
 [TestEnumSet]
 [TestEnumTypeTraits]
 [TestFastBernoulliTrial]
 [TestFloatingPoint]
+[TestFunctionTypeTraits]
 [TestIntegerPrintfMacros]
 [TestIntegerRange]
 [TestJSONWriter]
 [TestLinkedList]
 [TestMacroArgs]
 [TestMacroForEach]
 [TestMathAlgorithms]
 [TestMaybe]
+[TestNonDereferenceable]
+[TestNotNull]
 [TestParseFTPList]
 [TestPLDHash]
 [TestPair]
 [TestPoisonArea]
 skip-if = os == 'android' # Bug 1147630
+[TestRange]
 [TestRefPtr]
+[TestResult]
 [TestRollingMean]
 [TestScopeExit]
 [TestSegmentedVector]
 [TestSHA1]
 [TestSmallPointerArray]
 [TestSaturate]
 [TestSplayTree]
 [TestSPSCQueue]
 [TestSyncRunnable]
 [TestTemplateLib]
+[TestTextUtils]
+[TestThreadSafeWeakPtr]
 [TestTuple]
 [TestTypeTraits]
 [TestTypedEnum]
 [TestUniquePtr]
+[TestUtf8]
 [TestVariant]
 [TestVector]
 [TestVolatileBuffer]
 [TestWeakPtr]
+[TestWrappingOperations]
 [TestXorShift128PlusRNG]
 [buffered_stun_socket_unittest]
 [ice_unittest]
 [test_nr_socket_unittest]
 [jsapi-tests]
 [multi_tcp_socket_unittest]
 [nrappkit_unittest]
 [rlogringbuffer_unittest]
--- a/testing/mochitest/tests/SimpleTest/EventUtils.js
+++ b/testing/mochitest/tests/SimpleTest/EventUtils.js
@@ -2330,16 +2330,18 @@ function synthesizeDropAfterDragOver(aRe
   if (aResult) {
     effect = "none";
   } else if (effect != "none") {
     event = createDragEventObject("drop", aDestElement, aDestWindow,
                                   aDataTransfer, aDragEvent);
     sendDragEvent(event, aDestElement, aDestWindow);
   }
 
+  synthesizeMouseAtCenter(aDestElement, { type: "mouseup" }, aDestWindow);
+
   return effect;
 }
 
 /**
  * Emulate a drag and drop by emulating a dragstart and firing events dragenter,
  * dragover, and drop.
  *
  * @param aSrcElement   The element to use to start the drag.
@@ -2458,16 +2460,17 @@ async function synthesizePlainDragAndDro
     await new Promise(r => setTimeout(r, 0));
 
     event = createDragEventObject("drop", destElement, destWindow,
                                   dataTransfer, {});
     sendDragEvent(event, destElement, destWindow);
 
     await new Promise(r => setTimeout(r, 0));
 
+    synthesizeMouseAtCenter(destElement, { type: "mouseup" }, destWindow);
   } finally {
     ds.endDragSession(true, 0);
   }
 }
 
 var PluginUtils =
 {
   withTestPlugin : function(callback)
--- a/toolkit/content/aboutwebrtc/aboutWebrtc.js
+++ b/toolkit/content/aboutwebrtc/aboutWebrtc.js
@@ -845,17 +845,17 @@ ICEStats.prototype = {
   candidateToString(c) {
     if (!c) {
       return "*";
     }
 
     var type = c.candidateType;
 
     if (c.type == "local-candidate" && c.candidateType == "relayed") {
-      type = `${c.candidateType}-${c.mozLocalTransport}`;
+      type = `${c.candidateType}-${c.relayProtocol}`;
     }
 
     return `${c.ipAddress}:${c.portNumber}/${c.transport}(${type})`;
   },
 };
 
 function FoldableSection(parentElement, options = {}) {
   this._foldableElement = document.createElement("div");
--- a/toolkit/recordreplay/ProcessRedirectDarwin.cpp
+++ b/toolkit/recordreplay/ProcessRedirectDarwin.cpp
@@ -711,24 +711,17 @@ Preamble_gettimeofday(CallArguments* aAr
     return PreambleResult::PassThrough;
   }
   return PreambleResult::Redirect;
 }
 
 static PreambleResult
 Preamble_fcntl(CallArguments* aArguments)
 {
-  // We don't record any outputs for fcntl other than its return value, but
-  // some commands have an output parameter they write additional data to.
-  // Handle this by only allowing a limited set of commands to be used when
-  // events are not passed through and we are recording/replaying the outputs.
-  if (AreThreadEventsPassedThrough()) {
-    return PreambleResult::Redirect;
-  }
-
+  // Make sure fcntl is only used with a limited set of commands.
   auto& cmd = aArguments->Arg<1, size_t>();
   switch (cmd) {
   case F_GETFL:
   case F_SETFL:
   case F_GETFD:
   case F_SETFD:
   case F_NOCACHE:
   case F_SETLK:
--- a/xpcom/base/nsMacUtilsImpl.cpp
+++ b/xpcom/base/nsMacUtilsImpl.cpp
@@ -1,23 +1,16 @@
 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 /* vim: set ts=8 sts=2 et sw=2 tw=80: */
 /* This Source Code Form is subject to the terms of the Mozilla Public
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #include "nsMacUtilsImpl.h"
 
-#include "base/command_line.h"
-#include "nsDirectoryServiceDefs.h"
-#include "nsCOMPtr.h"
-#include "nsIFile.h"
-#include "nsIProperties.h"
-#include "nsServiceManagerUtils.h"
-
 #include <CoreFoundation/CoreFoundation.h>
 
 NS_IMPL_ISUPPORTS(nsMacUtilsImpl, nsIMacUtils)
 
 nsresult
 nsMacUtilsImpl::GetArchString(nsAString& aArchString)
 {
   if (!mBinaryArchs.IsEmpty()) {
@@ -127,69 +120,8 @@ nsMacUtilsImpl::GetIsTranslated(bool* aI
 #else
   // Translation only exists for ppc code.  Other architectures aren't
   // translated.
   *aIsTranslated = false;
 #endif
 
   return NS_OK;
 }
-
-#if defined(MOZ_CONTENT_SANDBOX)
-bool
-nsMacUtilsImpl::GetAppPath(nsCString &aAppPath)
-{
-  nsAutoCString appPath;
-  nsAutoCString appBinaryPath(
-    (CommandLine::ForCurrentProcess()->argv()[0]).c_str());
-
-  nsAutoCString::const_iterator start, end;
-  appBinaryPath.BeginReading(start);
-  appBinaryPath.EndReading(end);
-  if (RFindInReadable(NS_LITERAL_CSTRING(".app/Contents/MacOS/"), start, end)) {
-    end = start;
-    ++end; ++end; ++end; ++end;
-    appBinaryPath.BeginReading(start);
-    appPath.Assign(Substring(start, end));
-  } else {
-    return false;
-  }
-
-  nsCOMPtr<nsIFile> app;
-  nsresult rv = NS_NewLocalFile(NS_ConvertUTF8toUTF16(appPath),
-                                true, getter_AddRefs(app));
-  if (NS_FAILED(rv)) {
-    return false;
-  }
-
-  rv = app->Normalize();
-  if (NS_FAILED(rv)) {
-    return false;
-  }
-  app->GetNativePath(aAppPath);
-
-  return true;
-}
-
-#if defined(DEBUG)
-// Given a path to a file, return the directory which contains it.
-nsAutoCString
-nsMacUtilsImpl::GetDirectoryPath(const char *aPath)
-{
-  nsCOMPtr<nsIFile> file = do_CreateInstance(NS_LOCAL_FILE_CONTRACTID);
-  if (!file ||
-      NS_FAILED(file->InitWithNativePath(nsDependentCString(aPath)))) {
-    MOZ_CRASH("Failed to create or init an nsIFile");
-  }
-  nsCOMPtr<nsIFile> directoryFile;
-  if (NS_FAILED(file->GetParent(getter_AddRefs(directoryFile))) ||
-      !directoryFile) {
-    MOZ_CRASH("Failed to get parent for an nsIFile");
-  }
-  directoryFile->Normalize();
-  nsAutoCString directoryPath;
-  if (NS_FAILED(directoryFile->GetNativePath(directoryPath))) {
-    MOZ_CRASH("Failed to get path for an nsIFile");
-  }
-  return directoryPath;
-}
-#endif /* DEBUG */
-#endif /* MOZ_CONTENT_SANDBOX */
--- a/xpcom/base/nsMacUtilsImpl.h
+++ b/xpcom/base/nsMacUtilsImpl.h
@@ -16,24 +16,16 @@ class nsMacUtilsImpl final : public nsIM
 public:
   NS_DECL_ISUPPORTS
   NS_DECL_NSIMACUTILS
 
   nsMacUtilsImpl()
   {
   }
 
-#if defined(MOZ_CONTENT_SANDBOX)
-  static bool GetAppPath(nsCString &aAppPath);
-
-#ifdef DEBUG
-  static nsAutoCString GetDirectoryPath(const char *aPath);
-#endif /* DEBUG */
-#endif /* MOZ_CONTENT_SANDBOX */
-
 private:
   ~nsMacUtilsImpl()
   {
   }
 
   nsresult GetArchString(nsAString& aArchString);
 
   // A string containing a "-" delimited list of architectures