Merge mozilla-central to autoland. a=merge CLOSED TREE
authorGurzau Raul <rgurzau@mozilla.com>
Fri, 03 May 2019 01:17:27 +0300
changeset 472372 36c6d8c0df0eac2eb3403865f656a7f7bcb8826f
parent 472371 24b46555e58ff7fc20b6c84db9c10f2fba79cc23 (current diff)
parent 472302 bdf36faf780ba706bbebc8cbcd32ba892a899440 (diff)
child 472373 47e5e0e6249438e34b11bb582f8a69accf82ae6a
push id35954
push userrgurzau@mozilla.com
push dateFri, 03 May 2019 04:14:31 +0000
treeherdermozilla-central@d7b02bc7cf44 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone68.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge mozilla-central to autoland. a=merge CLOSED TREE
Cargo.lock
docshell/base/nsDocShell.cpp
--- a/devtools/client/debugger/src/client/firefox/workers.js
+++ b/devtools/client/debugger/src/client/firefox/workers.js
@@ -21,33 +21,39 @@ export async function updateWorkerClient
   if (!supportsWorkers(tabTarget)) {
     return {};
   }
 
   const newWorkerClients = {};
 
   const { workers } = await tabTarget.listWorkers();
   for (const workerTargetFront of workers) {
-    await workerTargetFront.attach();
-    const [, workerThread] = await workerTargetFront.attachThread(options);
+    try {
+      await workerTargetFront.attach();
+      const [, workerThread] = await workerTargetFront.attachThread(options);
 
-    if (workerClients[workerThread.actor]) {
-      if (workerClients[workerThread.actor].thread != workerThread) {
-        throw new Error(`Multiple clients for actor ID: ${workerThread.actor}`);
+      const actor = workerThread.actor;
+      if (workerClients[actor]) {
+        if (workerClients[actor].thread != workerThread) {
+          console.error(`Multiple clients for actor ID: ${workerThread.actor}`);
+        }
+        newWorkerClients[actor] = workerClients[actor];
+      } else {
+        addThreadEventListeners(workerThread);
+        workerThread.resume();
+
+        const consoleFront = await workerTargetFront.getFront("console");
+        await consoleFront.startListeners([]);
+
+        newWorkerClients[actor] = {
+          url: workerTargetFront.url,
+          thread: workerThread,
+          console: consoleFront
+        };
       }
-      newWorkerClients[workerThread.actor] = workerClients[workerThread.actor];
-    } else {
-      addThreadEventListeners(workerThread);
-      workerThread.resume();
-
-      const consoleFront = await workerTargetFront.getFront("console");
-      await consoleFront.startListeners([]);
-
-      newWorkerClients[workerThread.actor] = {
-        url: workerTargetFront.url,
-        thread: workerThread,
-        console: consoleFront
-      };
+    } catch (e) {
+      // If any of the workers have terminated since the list command initiated
+      // then we will get errors. Ignore these.
     }
   }
 
   return newWorkerClients;
 }
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -255,17 +255,17 @@ static uint32_t gNumberOfPrivateDocShell
 // spoofing. Initialize this to a non-bolean value so we know to check
 // the pref on the creation of the first docshell.
 static uint32_t gValidateOrigin = 0xffffffff;
 
 #ifdef DEBUG
 static mozilla::LazyLogModule gDocShellLog("nsDocShell");
 #endif
 static mozilla::LazyLogModule gDocShellLeakLog("nsDocShellLeak");
-;
+extern mozilla::LazyLogModule gPageCacheLog;
 
 const char kBrandBundleURL[] = "chrome://branding/locale/brand.properties";
 const char kAppstringsBundleURL[] =
     "chrome://global/locale/appstrings.properties";
 
 bool nsDocShell::sUseErrorPages = false;
 
 // Global reference to the URI fixup service.
@@ -3587,20 +3587,22 @@ nsresult nsDocShell::AddChildSHEntryToPa
   nsCOMPtr<nsIDocShell> parent = do_QueryInterface(GetAsSupports(mParent), &rv);
   if (parent) {
     rv = parent->AddChildSHEntry(mOSHE, aNewEntry, aChildOffset, mLoadType,
                                  aCloneChildren);
   }
 
   if (rootSH) {
     mLoadedEntryIndex = rootSH->Index();
-#ifdef DEBUG_PAGE_CACHE
-    printf("Previous index: %d, Loaded index: %d\n\n", mPreviousEntryIndex,
-           mLoadedEntryIndex);
-#endif
+
+    if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))) {
+      MOZ_LOG(gPageCacheLog, LogLevel::Verbose,
+              ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,
+               mLoadedEntryIndex));
+    }
   }
 
   return rv;
 }
 
 NS_IMETHODIMP
 nsDocShell::SetUseGlobalHistory(bool aUseGlobalHistory) {
   mUseGlobalHistory = aUseGlobalHistory;
@@ -7181,16 +7183,18 @@ bool nsDocShell::CanSavePresentation(uin
   // If the session history entry has the saveLayoutState flag set to false,
   // then we should not cache the presentation.
   if (!mOSHE->GetSaveLayoutStateFlag()) {
     return false;
   }
 
   // If the document is not done loading, don't cache it.
   if (!mScriptGlobal || mScriptGlobal->IsLoading()) {
+    MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,
+            ("Blocked due to document still loading"));
     return false;
   }
 
   if (mScriptGlobal->WouldReuseInnerWindow(aNewDocument)) {
     return false;
   }
 
   // Avoid doing the work of saving the presentation state in the case where
@@ -7276,25 +7280,25 @@ nsresult nsDocShell::CaptureState() {
 
   if (!mScriptGlobal) {
     return NS_ERROR_FAILURE;
   }
 
   nsCOMPtr<nsISupports> windowState = mScriptGlobal->SaveWindowState();
   NS_ENSURE_TRUE(windowState, NS_ERROR_FAILURE);
 
-#ifdef DEBUG_PAGE_CACHE
-  nsCOMPtr<nsIURI> uri = mOSHE->GetURI();
-  nsAutoCString spec;
-  if (uri) {
-    uri->GetSpec(spec);
-  }
-  printf("Saving presentation into session history\n");
-  printf("  SH URI: %s\n", spec.get());
-#endif
+  if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))) {
+    nsCOMPtr<nsIURI> uri = mOSHE->GetURI();
+    nsAutoCString spec;
+    if (uri) {
+      uri->GetSpec(spec);
+    }
+    MOZ_LOG(gPageCacheLog, LogLevel::Debug,
+            ("Saving presentation into session history, URI: %s", spec.get()));
+  }
 
   mOSHE->SetWindowState(windowState);
 
   // Suspend refresh URIs and save off the timer queue
   mOSHE->SetRefreshURIList(mSavedRefreshURIList);
 
   // Capture the current content viewer bounds.
   if (mContentViewer) {
@@ -7427,55 +7431,51 @@ nsresult nsDocShell::RestorePresentation
                                          bool* aRestoring) {
   MOZ_ASSERT(!mIsBeingDestroyed);
 
   NS_ASSERTION(mLoadType & LOAD_CMD_HISTORY,
                "RestorePresentation should only be called for history loads");
 
   nsCOMPtr<nsIContentViewer> viewer = aSHEntry->GetContentViewer();
 
-#ifdef DEBUG_PAGE_CACHE
-  nsCOMPtr<nsIURI> uri = aSHEntry->GetURI();
-
   nsAutoCString spec;
-  if (uri) {
-    uri->GetSpec(spec);
-  }
-#endif
+  if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Debug))) {
+    nsCOMPtr<nsIURI> uri = aSHEntry->GetURI();
+    if (uri) {
+      uri->GetSpec(spec);
+    }
+  }
 
   *aRestoring = false;
 
   if (!viewer) {
-#ifdef DEBUG_PAGE_CACHE
-    printf("no saved presentation for uri: %s\n", spec.get());
-#endif
+    MOZ_LOG(gPageCacheLog, LogLevel::Debug,
+            ("no saved presentation for uri: %s", spec.get()));
     return NS_OK;
   }
 
   // We need to make sure the content viewer's container is this docshell.
   // In subframe navigation, it's possible for the docshell that the
   // content viewer was originally loaded into to be replaced with a
   // different one.  We don't currently support restoring the presentation
   // in that case.
 
   nsCOMPtr<nsIDocShell> container;
   viewer->GetContainer(getter_AddRefs(container));
   if (!::SameCOMIdentity(container, GetAsSupports(this))) {
-#ifdef DEBUG_PAGE_CACHE
-    printf("No valid container, clearing presentation\n");
-#endif
+    MOZ_LOG(gPageCacheLog, LogLevel::Debug,
+            ("No valid container, clearing presentation"));
     aSHEntry->SetContentViewer(nullptr);
     return NS_ERROR_FAILURE;
   }
 
   NS_ASSERTION(mContentViewer != viewer, "Restoring existing presentation");
 
-#ifdef DEBUG_PAGE_CACHE
-  printf("restoring presentation from session history: %s\n", spec.get());
-#endif
+  MOZ_LOG(gPageCacheLog, LogLevel::Debug,
+          ("restoring presentation from session history: %s", spec.get()));
 
   SetHistoryEntry(&mLSHE, aSHEntry);
 
   // Post an event that will remove the request after we've returned
   // to the event loop.  This mimics the way it is called by nsIChannel
   // implementations.
 
   // Revoke any pending restore (just in case)
@@ -7611,20 +7611,19 @@ nsresult nsDocShell::RestoreFromHistory(
   mFiredUnloadEvent = false;
 
   mURIResultedInDocument = true;
   RefPtr<ChildSHistory> rootSH = GetRootSessionHistory();
   if (rootSH) {
     mPreviousEntryIndex = rootSH->Index();
     rootSH->LegacySHistory()->UpdateIndex();
     mLoadedEntryIndex = rootSH->Index();
-#ifdef DEBUG_PAGE_CACHE
-    printf("Previous index: %d, Loaded index: %d\n\n", mPreviousEntryIndex,
-           mLoadedEntryIndex);
-#endif
+    MOZ_LOG(gPageCacheLog, LogLevel::Verbose,
+            ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,
+             mLoadedEntryIndex));
   }
 
   // Rather than call Embed(), we will retrieve the viewer from the session
   // history entry and swap it in.
   // XXX can we refactor this so that we can just call Embed()?
   PersistLayoutHistoryState();
   nsresult rv;
   if (mContentViewer) {
@@ -7982,20 +7981,19 @@ nsresult nsDocShell::RestoreFromHistory(
   // event will hide the infobar, which will immediately resize the window
   // back to the larger size.  A future optimization might be to restore
   // the presentation at the "wrong" size, then fire the locationchanged
   // event and check whether the docshell's new size is the same as the
   // cached viewer size (skipping the resize if they are equal).
 
   if (newRootView) {
     if (!newBounds.IsEmpty() && !newBounds.IsEqualEdges(oldBounds)) {
-#ifdef DEBUG_PAGE_CACHE
-      printf("resize widget(%d, %d, %d, %d)\n", newBounds.x, newBounds.y,
-             newBounds.width, newBounds.height);
-#endif
+      MOZ_LOG(gPageCacheLog, LogLevel::Debug,
+              ("resize widget(%d, %d, %d, %d)", newBounds.x, newBounds.y,
+               newBounds.width, newBounds.height));
       mContentViewer->SetBounds(newBounds);
     } else {
       nsIScrollableFrame* rootScrollFrame =
           presShell->GetRootScrollFrameAsScrollable();
       if (rootScrollFrame) {
         rootScrollFrame->PostScrolledAreaEventForCurrentArea();
       }
     }
@@ -10813,20 +10811,19 @@ bool nsDocShell::OnNewURI(nsIURI* aURI, 
   // If this was a history load or a refresh, or it was a history load but
   // later changed to LOAD_NORMAL_REPLACE due to redirection, update the index
   // in session history.
   if (rootSH && ((mLoadType & (LOAD_CMD_HISTORY | LOAD_CMD_RELOAD)) ||
                  mLoadType == LOAD_NORMAL_REPLACE)) {
     mPreviousEntryIndex = rootSH->Index();
     rootSH->LegacySHistory()->UpdateIndex();
     mLoadedEntryIndex = rootSH->Index();
-#ifdef DEBUG_PAGE_CACHE
-    printf("Previous index: %d, Loaded index: %d\n\n", mPreviousEntryIndex,
-           mLoadedEntryIndex);
-#endif
+    MOZ_LOG(gPageCacheLog, LogLevel::Verbose,
+            ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,
+             mLoadedEntryIndex));
   }
 
   // aCloneSHChildren exactly means "we are not loading a new document".
   uint32_t locationFlags =
       aCloneSHChildren ? uint32_t(LOCATION_CHANGE_SAME_DOCUMENT) : 0;
 
   bool onLocationChangeNeeded =
       SetCurrentURI(aURI, aChannel, aFireOnLocationChange, locationFlags);
@@ -11498,20 +11495,19 @@ nsresult nsDocShell::AddToSessionHistory
 
     if (addToSHistory) {
       // Add to session history
       mPreviousEntryIndex = mSessionHistory->Index();
 
       bool shouldPersist = ShouldAddToSessionHistory(aURI, aChannel);
       rv = mSessionHistory->LegacySHistory()->AddEntry(entry, shouldPersist);
       mLoadedEntryIndex = mSessionHistory->Index();
-#ifdef DEBUG_PAGE_CACHE
-      printf("Previous index: %d, Loaded index: %d\n\n", mPreviousEntryIndex,
-             mLoadedEntryIndex);
-#endif
+      MOZ_LOG(gPageCacheLog, LogLevel::Verbose,
+              ("Previous index: %d, Loaded index: %d", mPreviousEntryIndex,
+               mLoadedEntryIndex));
     }
   } else {
     // This is a subframe.
     if (!mOSHE || !LOAD_TYPE_HAS_FLAGS(mLoadType, LOAD_FLAGS_REPLACE_HISTORY)) {
       rv = AddChildSHEntryToParent(entry, mChildOffset, aCloneChildren);
     }
   }
 
--- a/docshell/shistory/nsSHEntry.cpp
+++ b/docshell/shistory/nsSHEntry.cpp
@@ -16,18 +16,21 @@
 #include "nsIInputStream.h"
 #include "nsILayoutHistoryState.h"
 #include "nsIStructuredCloneContainer.h"
 #include "nsIURI.h"
 #include "nsSHEntryShared.h"
 #include "nsSHistory.h"
 
 #include "mozilla/net/ReferrerPolicy.h"
+#include "mozilla/Logging.h"
 #include "nsIReferrerInfo.h"
 
+extern mozilla::LazyLogModule gPageCacheLog;
+
 namespace dom = mozilla::dom;
 
 static uint32_t gEntryID = 0;
 
 nsSHEntry::nsSHEntry()
     : mShared(new nsSHEntryShared()),
       mLoadType(0),
       mID(gEntryID++),
--- a/dom/base/Document.cpp
+++ b/dom/base/Document.cpp
@@ -313,16 +313,18 @@
 
 #define XML_DECLARATION_BITS_DECLARATION_EXISTS (1 << 0)
 #define XML_DECLARATION_BITS_ENCODING_EXISTS (1 << 1)
 #define XML_DECLARATION_BITS_STANDALONE_EXISTS (1 << 2)
 #define XML_DECLARATION_BITS_STANDALONE_YES (1 << 3)
 
 extern bool sDisablePrefetchHTTPSPref;
 
+mozilla::LazyLogModule gPageCacheLog("PageCache");
+
 namespace mozilla {
 namespace dom {
 
 typedef nsTArray<Link*> LinkArray;
 
 static LazyLogModule gDocumentLeakPRLog("DocumentLeak");
 static LazyLogModule gCspPRLog("CSP");
 LazyLogModule gUserInteractionPRLog("UserInteraction");
@@ -7634,44 +7636,53 @@ void Document::CollectDescendantDocument
       if (aCallback(subdoc)) {
         aDescendants.AppendElement(entry->mSubDocument);
       }
       subdoc->CollectDescendantDocuments(aDescendants, aCallback);
     }
   }
 }
 
-#ifdef DEBUG_bryner
-#  define DEBUG_PAGE_CACHE
-#endif
-
 bool Document::CanSavePresentation(nsIRequest* aNewRequest) {
   if (!IsBFCachingAllowed()) {
     return false;
   }
 
+  nsAutoCString uri;
+  if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))) {
+    if (mDocumentURI) {
+      mDocumentURI->GetSpec(uri);
+    }
+  }
+
   if (EventHandlingSuppressed()) {
+    MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,
+            ("Save of %s blocked on event handling suppression", uri.get()));
     return false;
   }
 
   // Do not allow suspended windows to be placed in the
   // bfcache.  This method is also used to verify a document
   // coming out of the bfcache is ok to restore, though.  So
   // we only want to block suspend windows that aren't also
   // frozen.
   nsPIDOMWindowInner* win = GetInnerWindow();
   if (win && win->IsSuspended() && !win->IsFrozen()) {
+    MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,
+            ("Save of %s blocked on suspended Window", uri.get()));
     return false;
   }
 
   // Check our event listener manager for unload/beforeunload listeners.
   nsCOMPtr<EventTarget> piTarget = do_QueryInterface(mScriptGlobalObject);
   if (piTarget) {
     EventListenerManager* manager = piTarget->GetExistingListenerManager();
     if (manager && manager->HasUnloadListeners()) {
+      MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,
+              ("Save of %s blocked due to unload handlers", uri.get()));
       return false;
     }
   }
 
   // Check if we have pending network requests
   nsCOMPtr<nsILoadGroup> loadGroup = GetDocumentLoadGroup();
   if (loadGroup) {
     nsCOMPtr<nsISimpleEnumerator> requests;
@@ -7698,75 +7709,88 @@ bool Document::CanSavePresentation(nsIRe
         nsCOMPtr<nsIChannel> channel = do_QueryInterface(request);
         if (channel) {
           nsCOMPtr<nsILoadInfo> li = channel->LoadInfo();
           if (li->InternalContentPolicyType() ==
               nsIContentPolicy::TYPE_INTERNAL_IMAGE_FAVICON) {
             continue;
           }
         }
-#ifdef DEBUG_PAGE_CACHE
-        nsAutoCString requestName, docSpec;
-        request->GetName(requestName);
-        if (mDocumentURI) mDocumentURI->GetSpec(docSpec);
-
-        printf("document %s has request %s\n", docSpec.get(),
-               requestName.get());
-#endif
+
+        if (MOZ_UNLIKELY(MOZ_LOG_TEST(gPageCacheLog, LogLevel::Verbose))) {
+          nsAutoCString requestName;
+          request->GetName(requestName);
+          MOZ_LOG(gPageCacheLog, LogLevel::Verbose,
+                  ("Save of %s blocked because document has request %s",
+                   uri.get(), requestName.get()));
+        }
+
         return false;
       }
     }
   }
 
   // Check if we have active GetUserMedia use
   if (MediaManager::Exists() && win &&
       MediaManager::Get()->IsWindowStillActive(win->WindowID())) {
+    MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,
+            ("Save of %s blocked due to GetUserMedia", uri.get()));
     return false;
   }
 
 #ifdef MOZ_WEBRTC
   // Check if we have active PeerConnections
   if (win && win->HasActivePeerConnections()) {
+    MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,
+            ("Save of %s blocked due to PeerConnection", uri.get()));
     return false;
   }
 #endif  // MOZ_WEBRTC
 
   // Don't save presentations for documents containing EME content, so that
   // CDMs reliably shutdown upon user navigation.
   if (ContainsEMEContent()) {
     return false;
   }
 
   // Don't save presentations for documents containing MSE content, to
   // reduce memory usage.
   if (ContainsMSEContent()) {
+    MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,
+            ("Save of %s blocked due to MSE use", uri.get()));
     return false;
   }
 
   if (mSubDocuments) {
     for (auto iter = mSubDocuments->Iter(); !iter.Done(); iter.Next()) {
       auto entry = static_cast<SubDocMapEntry*>(iter.Get());
       Document* subdoc = entry->mSubDocument;
 
       // The aIgnoreRequest we were passed is only for us, so don't pass it on.
       bool canCache = subdoc ? subdoc->CanSavePresentation(nullptr) : false;
       if (!canCache) {
+        MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,
+                ("Save of %s blocked due to subdocument blocked", uri.get()));
         return false;
       }
     }
   }
 
   if (win) {
     auto* globalWindow = nsGlobalWindowInner::Cast(win);
 #ifdef MOZ_WEBSPEECH
     if (globalWindow->HasActiveSpeechSynthesis()) {
+      MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,
+              ("Save of %s blocked due to Speech use", uri.get()));
       return false;
     }
 #endif
     if (globalWindow->HasUsedVR()) {
+      MOZ_LOG(gPageCacheLog, mozilla::LogLevel::Verbose,
+              ("Save of %s blocked due to having used VR", uri.get()));
       return false;
     }
   }
 
   return true;
 }
 
 void Document::Destroy() {
--- a/dom/base/nsGlobalWindowOuter.cpp
+++ b/dom/base/nsGlobalWindowOuter.cpp
@@ -304,16 +304,17 @@ using mozilla::TimeStamp;
     if (!mInnerWindow) {                                \
       return err_rval;                                  \
     }                                                   \
   }                                                     \
   return GetCurrentInnerWindowInternal()->method args;  \
   PR_END_MACRO
 
 static LazyLogModule gDOMLeakPRLogOuter("DOMLeakOuter");
+extern LazyLogModule gPageCacheLog;
 
 static int32_t gOpenPopupSpamCount = 0;
 
 static bool gSyncContentBlockingNotifications = false;
 
 nsGlobalWindowOuter::OuterWindowByIdTable*
     nsGlobalWindowOuter::sOuterWindowsById = nullptr;
 
@@ -7388,35 +7389,33 @@ already_AddRefed<nsISupports> nsGlobalWi
   // calls to SetTimeoutOrInterval will create entries in the timeout
   // list that will only run after this window has come out of the bfcache.
   // Also, while we're frozen, we won't dispatch online/offline events
   // to the page.
   inner->Freeze();
 
   nsCOMPtr<nsISupports> state = new WindowStateHolder(inner);
 
-#ifdef DEBUG_PAGE_CACHE
-  printf("saving window state, state = %p\n", (void*)state);
-#endif
+  MOZ_LOG(gPageCacheLog, LogLevel::Debug,
+          ("saving window state, state = %p", (void*)state));
 
   return state.forget();
 }
 
 nsresult nsGlobalWindowOuter::RestoreWindowState(nsISupports* aState) {
   if (!mContext || !GetWrapperPreserveColor()) {
     // The window may be getting torn down; don't bother restoring state.
     return NS_OK;
   }
 
   nsCOMPtr<WindowStateHolder> holder = do_QueryInterface(aState);
   NS_ENSURE_TRUE(holder, NS_ERROR_FAILURE);
 
-#ifdef DEBUG_PAGE_CACHE
-  printf("restoring window state, state = %p\n", (void*)holder);
-#endif
+  MOZ_LOG(gPageCacheLog, LogLevel::Debug,
+          ("restoring window state, state = %p", (void*)holder));
 
   // And we're ready to go!
   nsGlobalWindowInner* inner = GetCurrentInnerWindowInternal();
 
   // if a link is focused, refocus with the FLAG_SHOWRING flag set. This makes
   // it easy to tell which link was last clicked when going back a page.
   Element* focusedElement = inner->GetFocusedElement();
   if (nsContentUtils::ContentIsLink(focusedElement)) {
--- a/dom/base/nsJSEnvironment.cpp
+++ b/dom/base/nsJSEnvironment.cpp
@@ -2054,19 +2054,21 @@ void nsJSContext::PokeShrinkingGC() {
 }
 
 // static
 void nsJSContext::MaybePokeCC() {
   if (sCCRunner || sICCRunner || !sHasRunGC || sShuttingDown) {
     return;
   }
 
-  uint32_t sinceLastCCEnd = TimeUntilNow(sLastCCEndTime);
-  if (sinceLastCCEnd && sinceLastCCEnd < NS_CC_DELAY) {
-    return;
+  if (!sLastCCEndTime.IsNull()) {
+    uint32_t sinceLastCCEnd = TimeUntilNow(sLastCCEndTime);
+    if (sinceLastCCEnd < NS_CC_DELAY) {
+      return;
+    }
   }
 
   // If GC hasn't run recently and forget skippable only cycle was run,
   // don't start a new cycle too soon.
   if ((sCleanupsSinceLastGC > NS_MAJOR_FORGET_SKIPPABLE_CALLS) &&
       !sLastForgetSkippableCycleEndTime.IsNull()) {
     uint32_t sinceLastForgetSkippableCycle =
         TimeUntilNow(sLastForgetSkippableCycleEndTime);
--- a/layout/base/nsDocumentViewer.cpp
+++ b/layout/base/nsDocumentViewer.cpp
@@ -128,16 +128,18 @@ using namespace mozilla::dom;
 #define BEFOREUNLOAD_REQUIRES_INTERACTION_PREFNAME \
   "dom.require_user_interaction_for_beforeunload"
 
 //-----------------------------------------------------
 // LOGGING
 #include "LayoutLogging.h"
 #include "mozilla/Logging.h"
 
+extern mozilla::LazyLogModule gPageCacheLog;
+
 #ifdef NS_PRINTING
 static mozilla::LazyLogModule gPrintingLog("printing");
 
 #  define PR_PL(_p1) MOZ_LOG(gPrintingLog, mozilla::LogLevel::Debug, _p1);
 #endif  // NS_PRINTING
 
 #define PRT_YESNO(_p) ((_p) ? "YES" : "NO")
 //-----------------------------------------------------
@@ -2104,20 +2106,19 @@ nsDocumentViewer::Show(void) {
       treeItem->GetSameTypeRootTreeItem(getter_AddRefs(root));
       nsCOMPtr<nsIWebNavigation> webNav = do_QueryInterface(root);
       RefPtr<ChildSHistory> history = webNav->GetSessionHistory();
       if (history) {
         int32_t prevIndex, loadedIndex;
         nsCOMPtr<nsIDocShell> docShell = do_QueryInterface(treeItem);
         docShell->GetPreviousEntryIndex(&prevIndex);
         docShell->GetLoadedEntryIndex(&loadedIndex);
-#ifdef DEBUG_PAGE_CACHE
-        printf("About to evict content viewers: prev=%d, loaded=%d\n",
-               prevIndex, loadedIndex);
-#endif
+        MOZ_LOG(gPageCacheLog, LogLevel::Verbose,
+                ("About to evict content viewers: prev=%d, loaded=%d",
+                 prevIndex, loadedIndex));
         history->LegacySHistory()->EvictOutOfRangeContentViewers(loadedIndex);
       }
     }
   }
 
   if (mWindow) {
     // When attached to a top level xul window, we do not need to call
     // Show on the widget. Underlying window management code handles
--- a/netwerk/base/nsIProtocolHandler.idl
+++ b/netwerk/base/nsIProtocolHandler.idl
@@ -325,9 +325,15 @@ interface nsIProtocolHandler : nsISuppor
      * The URIs for this protocol can be loaded by extensions.
      */
     const unsigned long URI_LOADABLE_BY_EXTENSIONS = (1 << 21);
 
     /**
      * The URIs for this protocol can not be loaded into private contexts.
      */
     const unsigned long URI_DISALLOW_IN_PRIVATE_CONTEXT = (1 << 22);
+
+    /**
+     * This protocol handler forbids accessing cookies e.g. for mail related
+     * protocols. Only used in Mailnews (comm-central).
+     */
+    const unsigned long URI_FORBIDS_COOKIE_ACCESS = (1 << 23);
 };
--- a/netwerk/cookie/CookieSettings.cpp
+++ b/netwerk/cookie/CookieSettings.cpp
@@ -2,16 +2,19 @@
 /* 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 "mozilla/net/CookieSettings.h"
 #include "mozilla/Unused.h"
 #include "nsGlobalWindowInner.h"
+#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
+#  include "nsIProtocolHandler.h"
+#endif
 #include "nsPermission.h"
 #include "nsPermissionManager.h"
 
 namespace mozilla {
 namespace net {
 
 namespace {
 
@@ -129,18 +132,33 @@ CookieSettings::CookiePermission(nsIPrin
   }
 
   // Let's ask the permission manager.
   nsPermissionManager* pm = nsPermissionManager::GetInstance();
   if (NS_WARN_IF(!pm)) {
     return NS_ERROR_FAILURE;
   }
 
-  rv = pm->TestPermissionFromPrincipal(aPrincipal, NS_LITERAL_CSTRING("cookie"),
-                                       aCookiePermission);
+#if defined(MOZ_THUNDERBIRD) || defined(MOZ_SUITE)
+  // Check if this protocol doesn't allow cookies.
+  bool hasFlags;
+  nsCOMPtr<nsIURI> uri;
+  aPrincipal->GetURI(getter_AddRefs(uri));
+  rv = NS_URIChainHasFlags(uri, nsIProtocolHandler::URI_FORBIDS_COOKIE_ACCESS,
+                           &hasFlags);
+  if (NS_FAILED(rv) || hasFlags) {
+    *aCookiePermission = nsPermissionManager::DENY_ACTION;
+    rv = NS_OK;  // Reset, so it's not caught as a bad status after the `else`.
+  } else         // Note the tricky `else` which controls the call below.
+#endif
+
+    // Note that when compiled for Thunderbird/SeaMonkey, the following
+    // statement is controlled by the `else` in the `#ifdef` block above.
+    rv = pm->TestPermissionFromPrincipal(
+        aPrincipal, NS_LITERAL_CSTRING("cookie"), aCookiePermission);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
   // Let's store the permission, also if the result is UNKNOWN in order to avoid
   // race conditions.
 
   nsCOMPtr<nsIPermission> permission = nsPermission::Create(
--- a/security/nss/Makefile
+++ b/security/nss/Makefile
@@ -82,20 +82,20 @@ NSPR_CONFIGURE_OPTS += --enable-debug-rt
 endif
 ifdef USE_STATIC_RTL
 NSPR_CONFIGURE_OPTS += --enable-static-rtl
 endif
 ifdef NS_USE_GCC
 NSPR_CONFIGURE_ENV = CC=gcc CXX=g++
 endif
 ifdef CC
-NSPR_CONFIGURE_ENV = CC=$(CC)
+NSPR_CONFIGURE_ENV = CC="$(CC)"
 endif
 ifdef CCC
-NSPR_CONFIGURE_ENV += CXX=$(CCC)
+NSPR_CONFIGURE_ENV += CXX="$(CCC)"
 endif
 # Remove -arch definitions. NSPR can't handle that.
 NSPR_CONFIGURE_ENV := $(filter-out -arch x86_64,$(NSPR_CONFIGURE_ENV))
 NSPR_CONFIGURE_ENV := $(filter-out -arch i386,$(NSPR_CONFIGURE_ENV))
 NSPR_CONFIGURE_ENV := $(filter-out -arch ppc,$(NSPR_CONFIGURE_ENV))
 
 #
 # Some pwd commands on Windows (for example, the pwd
--- a/security/nss/TAG-INFO
+++ b/security/nss/TAG-INFO
@@ -1,1 +1,1 @@
-56826bedabba
+4e4eb31ce200
--- a/security/nss/build.sh
+++ b/security/nss/build.sh
@@ -89,17 +89,18 @@ while [ $# -gt 0 ]; do
         --ubsan=?*) enable_ubsan "${1#*=}" ;;
         --fuzz) fuzz=1 ;;
         --fuzz=oss) fuzz=1; fuzz_oss=1 ;;
         --fuzz=tls) fuzz=1; fuzz_tls=1 ;;
         --sancov) enable_sancov ;;
         --sancov=?*) enable_sancov "${1#*=}" ;;
         --emit-llvm) gyp_params+=(-Demit_llvm=1 -Dsign_libs=0) ;;
         --no-zdefs) gyp_params+=(-Dno_zdefs=1) ;;
-        --test) gyp_params+=(-Dtest_build=1) ;;
+        --test) gyp_params+=(-Dtest_build=1 -Dstatic_libs=1) ;;
+        --static) gyp_params+=(-Dstatic_libs=1) ;;
         --ct-verif) gyp_params+=(-Dct_verif=1) ;;
         --nspr) nspr_clean; rebuild_nspr=1 ;;
         --with-nspr=?*) set_nspr_path "${1#*=}"; no_local_nspr=1 ;;
         --system-nspr) set_nspr_path "/usr/include/nspr/:"; no_local_nspr=1 ;;
         --system-sqlite) gyp_params+=(-Duse_system_sqlite=1) ;;
         --enable-fips) gyp_params+=(-Ddisable_fips=0) ;;
         --enable-libpkix) gyp_params+=(-Ddisable_libpkix=0) ;;
         --mozpkix-only) gyp_params+=(-Dmozpkix_only=1 -Ddisable_tests=1 -Dsign_libs=0) ;;
--- a/security/nss/coreconf/config.gypi
+++ b/security/nss/coreconf/config.gypi
@@ -94,16 +94,17 @@
     'disable_libpkix%': 1,
     'disable_werror%': 0,
     'mozilla_client%': 0,
     'comm_client%': 0,
     'moz_fold_libs%': 0,
     'moz_folded_library_name%': '',
     'sanitizer_flags%': 0,
     'test_build%': 0,
+    'static_libs%': 0,
     'no_zdefs%': 0,
     'fuzz%': 0,
     'fuzz_tls%': 0,
     'fuzz_oss%': 0,
     'sign_libs%': 1,
     'use_pprof%': 0,
     'ct_verif%': 0,
     'emit_llvm%': 0,
@@ -117,16 +118,17 @@
     'mozpkix_only%': 0,
   },
   'target_defaults': {
     # Settings specific to targets should go here.
     # This is mostly for linking to libraries.
     'variables': {
       'mapfile%': '',
       'test_build%': 0,
+      'static_libs%': 0,
       'debug_optimization_level%': '0',
       'release_optimization_level%': '2',
     },
     'standalone_static_library': 0,
     'include_dirs': [
       '<(nspr_include_dir)',
       '<(nss_dist_dir)/private/<(module)',
     ],
@@ -137,16 +139,21 @@
         ],
       }],
       [ 'disable_fips==1', {
         'defines': [
           'NSS_FIPS_DISABLED',
           'NSS_NO_INIT_SUPPORT',
         ],
       }],
+      [ 'static_libs==1', {
+        'variables': {
+          'standalone_static_library': '1',
+        },
+      }],
       [ 'OS!="android" and OS!="mac" and OS!="win"', {
         'libraries': [
           '-lpthread',
         ],
       }],
       [ 'OS=="linux"', {
         'libraries': [
           '-ldl',
@@ -252,17 +259,17 @@
               ],
               'outputs': [
                 '<(INTERMEDIATE_DIR)/out.>(mapfile)',
               ],
               'action': ['<@(process_map_file)'],
             }],
           }]
         ],
-      }, 'test_build==1 and _type=="shared_library"', {
+      }, 'static_libs==1 and _type=="shared_library"', {
         # When linking a shared lib against a static one, XCode doesn't
         # export the latter's symbols by default. -all_load fixes that.
         'xcode_settings': {
           'OTHER_LDFLAGS': [
             '-all_load',
           ],
         },
       }],
--- a/security/nss/coreconf/coreconf.dep
+++ b/security/nss/coreconf/coreconf.dep
@@ -5,9 +5,8 @@
 
 /*
  * A dummy header file that is a dependency for all the object files.
  * Used to force a full recompilation of NSS in Mozilla's Tinderbox
  * depend builds.  See comments in rules.mk.
  */
 
 #error "Do not include this header file."
-
--- a/security/nss/coreconf/fuzz.sh
+++ b/security/nss/coreconf/fuzz.sh
@@ -9,17 +9,17 @@ if [ -z "$CC" ]; then
         echo "Fuzzing requires clang!"
         exit 1
     fi
     export CC=clang
     export CCC=clang++
     export CXX=clang++
 fi
 
-gyp_params+=(-Dtest_build=1 -Dfuzz=1 -Dsign_libs=0)
+gyp_params+=(-Dtest_build=1 -Dstatic_libs=1 -Dfuzz=1 -Dsign_libs=0)
 
 # Add debug symbols even for opt builds.
 nspr_params+=(--enable-debug-symbols)
 
 if [ "$fuzz_oss" = 1 ]; then
   gyp_params+=(-Dno_zdefs=1 -Dfuzz_oss=1)
 else
   enable_sanitizer asan
--- a/security/nss/gtests/pk11_gtest/pk11_gtest.gyp
+++ b/security/nss/gtests/pk11_gtest/pk11_gtest.gyp
@@ -24,30 +24,30 @@
         'pk11_prng_unittest.cc',
         'pk11_rsapkcs1_unittest.cc',
         'pk11_rsapss_unittest.cc',
         'pk11_der_private_key_import_unittest.cc',
         '<(DEPTH)/gtests/common/gtests.cc'
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
-        '<(DEPTH)/lib/util/util.gyp:nssutil3',
         '<(DEPTH)/cpputil/cpputil.gyp:cpputil',
         '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
+        '<(DEPTH)/lib/util/util.gyp:nssutil3',
       ],
       'conditions': [
-        [ 'test_build==1', {
+        [ 'static_libs==1', {
           'dependencies': [
+            '<(DEPTH)/lib/base/base.gyp:nssb',
+            '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
+            '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
+            '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
+            '<(DEPTH)/lib/dev/dev.gyp:nssdev',
             '<(DEPTH)/lib/nss/nss.gyp:nss_static',
             '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
-            '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
-            '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
-            '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
-            '<(DEPTH)/lib/base/base.gyp:nssb',
-            '<(DEPTH)/lib/dev/dev.gyp:nssdev',
             '<(DEPTH)/lib/pki/pki.gyp:nsspki',
             '<(DEPTH)/lib/ssl/ssl.gyp:ssl',
           ],
         }, {
           'dependencies': [
             '<(DEPTH)/lib/nss/nss.gyp:nss3',
             '<(DEPTH)/lib/ssl/ssl.gyp:ssl3',
           ],
--- a/security/nss/gtests/softoken_gtest/softoken_gtest.gyp
+++ b/security/nss/gtests/softoken_gtest/softoken_gtest.gyp
@@ -14,17 +14,17 @@
         'softoken_gtest.cc',
       ],
       'dependencies': [
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/lib/util/util.gyp:nssutil3',
         '<(DEPTH)/gtests/google_test/google_test.gyp:gtest',
       ],
       'conditions': [
-        [ 'test_build==1', {
+        [ 'static_libs==1', {
           'dependencies': [
             '<(DEPTH)/lib/nss/nss.gyp:nss_static',
             '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
             '<(DEPTH)/lib/cryptohi/cryptohi.gyp:cryptohi',
             '<(DEPTH)/lib/certhigh/certhigh.gyp:certhi',
             '<(DEPTH)/lib/certdb/certdb.gyp:certdb',
             '<(DEPTH)/lib/base/base.gyp:nssb',
             '<(DEPTH)/lib/dev/dev.gyp:nssdev',
--- a/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
+++ b/security/nss/gtests/ssl_gtest/ssl_gtest.gyp
@@ -71,17 +71,17 @@
         '<(DEPTH)/lib/pki/pki.gyp:nsspki',
         '<(DEPTH)/lib/dev/dev.gyp:nssdev',
         '<(DEPTH)/lib/base/base.gyp:nssb',
         '<(DEPTH)/lib/zlib/zlib.gyp:nss_zlib',
         '<(DEPTH)/cpputil/cpputil.gyp:cpputil',
         '<(DEPTH)/lib/libpkix/libpkix.gyp:libpkix',
       ],
       'conditions': [
-        [ 'test_build==1', {
+        [ 'static_libs==1', {
           'dependencies': [
             '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap_static',
           ],
         }, {
           'dependencies': [
             '<(DEPTH)/lib/sqlite/sqlite.gyp:sqlite3',
             '<(DEPTH)/lib/pk11wrap/pk11wrap.gyp:pk11wrap',
             '<(DEPTH)/lib/softoken/softoken.gyp:softokn',
--- a/security/nss/help.txt
+++ b/security/nss/help.txt
@@ -35,16 +35,17 @@ NSS build tool options:
                      --fuzz=tls to enable TLS fuzzing mode
                      --fuzz=oss to build for OSS-Fuzz
     --sancov         do sanitize coverage builds
                      --sancov=func sets coverage to function level for example
     --emit-llvm      emit LLVM bitcode while building
                      (requires the gold linker, use clang-3.8 for SAW)
     --no-zdefs       don't set -Wl,-z,defs
     --test           ignore map files and export everything we have
+    --static         create static libraries and use static linking
     --ct-verif       build with valgrind for ct-verif
     --nspr           force a rebuild of NSPR
     --with-nspr      use the NSPR build at the given locations
                      --with-nspr=<include>:<lib> sets include and lib paths
     --system-nspr    attempt to use system nspr
                      shorthand for --with-nspr=/usr/include/nspr:
     --system-sqlite  use system sqlite
     --enable-fips    enable FIPS checks
--- a/security/nss/lib/pk11wrap/pk11load.c
+++ b/security/nss/lib/pk11wrap/pk11load.c
@@ -348,17 +348,17 @@ SECMOD_SetRootCerts(PK11SlotInfo *slot, 
             /* increment module count & store new list */
             mod->slotInfo = psi_list;
             mod->slotInfoCount++;
         }
         psi->hasRootCerts = 1;
     }
 }
 
-#ifndef NSS_TEST_BUILD
+#ifndef NSS_STATIC_SOFTOKEN
 static const char *my_shlib_name =
     SHLIB_PREFIX "nss" SHLIB_VERSION "." SHLIB_SUFFIX;
 static const char *softoken_shlib_name =
     SHLIB_PREFIX "softokn" SOFTOKEN_SHLIB_VERSION "." SHLIB_SUFFIX;
 static const PRCallOnceType pristineCallOnce;
 static PRCallOnceType loadSoftokenOnce;
 static PRLibrary *softokenLib;
 static PRInt32 softokenLoadCount;
@@ -398,17 +398,17 @@ secmod_LoadPKCS11Module(SECMODModule *mo
     PRBool alreadyLoaded = PR_FALSE;
     char *disableUnload = NULL;
 
     if (mod->loaded)
         return SECSuccess;
 
     /* internal modules get loaded from their internal list */
     if (mod->internal && (mod->dllName == NULL)) {
-#ifdef NSS_TEST_BUILD
+#ifdef NSS_STATIC_SOFTOKEN
         entry = (CK_C_GetFunctionList)NSC_GetFunctionList;
 #else
         /*
          * Loads softoken as a dynamic library,
          * even though the rest of NSS assumes this as the "internal" module.
          */
         if (!softokenLib &&
             PR_SUCCESS != PR_CallOnce(&loadSoftokenOnce, &softoken_LoadDSO))
@@ -425,17 +425,17 @@ secmod_LoadPKCS11Module(SECMODModule *mo
         }
 
         if (!entry)
             return SECFailure;
 #endif
 
         if (mod->isModuleDB) {
             mod->moduleDBFunc = (CK_C_GetFunctionList)
-#ifdef NSS_TEST_BUILD
+#ifdef NSS_STATIC_SOFTOKEN
                 NSC_ModuleDBFunc;
 #else
                 PR_FindSymbol(softokenLib, "NSC_ModuleDBFunc");
 #endif
         }
 
         if (mod->moduleDBOnly) {
             mod->loaded = PR_TRUE;
@@ -607,17 +607,17 @@ SECMOD_UnloadModule(SECMODModule *mod)
     }
     mod->moduleID = 0;
     mod->loaded = PR_FALSE;
 
     /* do we want the semantics to allow unloading the internal library?
      * if not, we should change this to SECFailure and move it above the
      * mod->loaded = PR_FALSE; */
     if (mod->internal && (mod->dllName == NULL)) {
-#ifndef NSS_TEST_BUILD
+#ifndef NSS_STATIC_SOFTOKEN
         if (0 == PR_ATOMIC_DECREMENT(&softokenLoadCount)) {
             if (softokenLib) {
                 disableUnload = PR_GetEnvSecure("NSS_DISABLE_UNLOAD");
                 if (!disableUnload) {
 #ifdef DEBUG
                     PRStatus status = PR_UnloadLibrary(softokenLib);
                     PORT_Assert(PR_SUCCESS == status);
 #else
--- a/security/nss/lib/pk11wrap/pk11wrap.gyp
+++ b/security/nss/lib/pk11wrap/pk11wrap.gyp
@@ -5,17 +5,17 @@
   'includes': [
     '../../coreconf/config.gypi'
   ],
   'targets': [
     {
       'target_name': 'pk11wrap_static',
       'type': 'static_library',
       'defines': [
-        'NSS_TEST_BUILD',
+        'NSS_STATIC_SOFTOKEN',
       ],
       'dependencies': [
         'pk11wrap_base',
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/lib/softoken/softoken.gyp:softokn_static',
       ],
     },
     {
--- a/security/nss/lib/softoken/pkcs11.c
+++ b/security/nss/lib/softoken/pkcs11.c
@@ -3152,17 +3152,17 @@ nsc_CommonFinalize(CK_VOID_PTR pReserved
 
     /* tell freeBL to clean up after itself */
     BL_Cleanup();
 
     /* reset fork status in freebl. We must do this before BL_Unload so that
      * this call doesn't force freebl to be reloaded. */
     BL_SetForkState(PR_FALSE);
 
-#ifndef NSS_TEST_BUILD
+#ifndef NSS_STATIC_SOFTOKEN
     /* unload freeBL shared library from memory. This may only decrement the
      * OS refcount if it's been loaded multiple times, eg. by libssl */
     BL_Unload();
 #endif
 
     /* clean up the default OID table */
     SECOID_Shutdown();
 
--- a/security/nss/lib/softoken/softoken.gyp
+++ b/security/nss/lib/softoken/softoken.gyp
@@ -5,17 +5,17 @@
   'includes': [
     '../../coreconf/config.gypi'
   ],
   'targets': [
     {
       'target_name': 'softokn_static',
       'type': 'static_library',
       'defines': [
-        'NSS_TEST_BUILD',
+        'NSS_STATIC_SOFTOKEN',
       ],
       'dependencies': [
         'softokn_base',
         '<(DEPTH)/exports.gyp:nss_exports',
         '<(DEPTH)/lib/freebl/freebl.gyp:freebl_static',
       ],
       'conditions': [
         [ 'use_system_sqlite==1', {
--- a/toolkit/xre/nsNativeAppSupportCocoa.mm
+++ b/toolkit/xre/nsNativeAppSupportCocoa.mm
@@ -156,18 +156,19 @@ NS_IMETHODIMP nsNativeAppSupportCocoa::S
   // the original running process (exiting the current process), or be processed by
   // the current process (if -no-remote is specified).
 
   mozilla::MacAutoreleasePool pool;
 
   NSArray* arguments = [[NSProcessInfo processInfo] arguments];
   BOOL shallProceedLikeNoRemote = NO;
   for (NSString* arg in arguments) {
-    if ([arg isEqualToString:@"-no-remote"] || [arg isEqualToString:@"-headless"] ||
-        [arg isEqualToString:@"--no-remote"] || [arg isEqualToString:@"--headless"]) {
+    if ([arg isEqualToString:@"-no-remote"] || [arg isEqualToString:@"--no-remote"] ||
+        [arg isEqualToString:@"-headless"] || [arg isEqualToString:@"--headless"] ||
+        [arg isEqualToString:@"-createProfile"] || [arg isEqualToString:@"--createProfile"]) {
       shallProceedLikeNoRemote = YES;
       break;
     }
   }
 
   BOOL mozillaRestarting = NO;
   if ([[[[NSProcessInfo processInfo] environment] objectForKey:@"MOZ_APP_RESTART"]
           isEqualToString:@"1"]) {