Merge inbound to mozilla-central. a=merge
authorGurzau Raul <rgurzau@mozilla.com>
Fri, 03 May 2019 01:02:21 +0300
changeset 472302 bdf36faf780ba706bbebc8cbcd32ba892a899440
parent 472279 6df281b9388839efca4fc89ae62aa2c696aaf76b (current diff)
parent 472301 e10505182ad2c7f5955999964a08fb9c2c71a038 (diff)
child 472372 36c6d8c0df0eac2eb3403865f656a7f7bcb8826f
child 472389 0c983ed54af0730f3360b76156b8e0fa41cc4ebc
push id35953
push userrgurzau@mozilla.com
push dateThu, 02 May 2019 22:03:33 +0000
treeherdermozilla-central@bdf36faf780b [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersmerge
milestone68.0a1
first release with
nightly linux32
bdf36faf780b / 68.0a1 / 20190502220333 / files
nightly linux64
bdf36faf780b / 68.0a1 / 20190502220333 / files
nightly mac
bdf36faf780b / 68.0a1 / 20190502220333 / files
nightly win32
bdf36faf780b / 68.0a1 / 20190502220333 / files
nightly win64
bdf36faf780b / 68.0a1 / 20190502220333 / files
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
releases
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Merge inbound to mozilla-central. a=merge
docshell/base/nsDocShell.cpp
dom/base/Document.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"]) {