Bug 1269361 - Add mPrivateBrowsingId to OriginAttributes r=ehsan,jdm
authorJames Andreou <jandreou@mozilla.com>
Thu, 02 Jun 2016 17:02:29 -0400
changeset 339273 ff298d2993a32aeaca0eacac32d8e673298cf5c5
parent 339272 16b4946069a9470a94f33791de7440966844747d
child 339274 192969a0735a5973a3f5234b6ccd3c2bc4a5a48f
push id6249
push userjlund@mozilla.com
push dateMon, 01 Aug 2016 13:59:36 +0000
treeherdermozilla-beta@bad9d4f5bf7e [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersehsan, jdm
bugs1269361
milestone49.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
Bug 1269361 - Add mPrivateBrowsingId to OriginAttributes r=ehsan,jdm
caps/BasePrincipal.cpp
caps/BasePrincipal.h
docshell/base/LoadContext.cpp
docshell/base/LoadContext.h
docshell/base/SerializedLoadContext.cpp
docshell/base/nsDocShell.cpp
docshell/base/nsDocShell.h
dom/base/ChromeUtils.cpp
dom/base/nsFrameLoader.cpp
dom/ipc/TabChild.cpp
dom/ipc/TabContext.cpp
dom/ipc/TabContext.h
dom/ipc/TabParent.cpp
dom/tests/mochitest/localstorage/test_localStorageQuotaPrivateBrowsing_perwindowpb.html
dom/webidl/ChromeUtils.webidl
extensions/cookie/nsPermissionManager.cpp
netwerk/base/LoadContextInfo.cpp
netwerk/base/nsNetUtil.cpp
netwerk/ipc/NeckoParent.cpp
netwerk/test/TestCookie.cpp
--- a/caps/BasePrincipal.cpp
+++ b/caps/BasePrincipal.cpp
@@ -40,70 +40,80 @@ PrincipalOriginAttributes::InheritFromDo
 
   // addonId is computed from the principal URI and never propagated
   mUserContextId = aAttrs.mUserContextId;
 
   // TODO:
   // Bug 1225349 - PrincipalOriginAttributes should inherit mSignedPkg
   // accordingly by URI
   mSignedPkg = aAttrs.mSignedPkg;
+
+  mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
 }
 
 void
 PrincipalOriginAttributes::InheritFromNecko(const NeckoOriginAttributes& aAttrs)
 {
   mAppId = aAttrs.mAppId;
   mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
 
   // addonId is computed from the principal URI and never propagated
   mUserContextId = aAttrs.mUserContextId;
   mSignedPkg = aAttrs.mSignedPkg;
+
+  mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
 }
 
 void
 DocShellOriginAttributes::InheritFromDocToChildDocShell(const PrincipalOriginAttributes& aAttrs)
 {
   mAppId = aAttrs.mAppId;
   mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
 
   // addonId is computed from the principal URI and never propagated
   mUserContextId = aAttrs.mUserContextId;
 
   // TODO:
   // Bug 1225353 - DocShell/NeckoOriginAttributes should inherit
   // mSignedPkg accordingly by mSignedPkgInBrowser
   mSignedPkg = aAttrs.mSignedPkg;
+
+  mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
 }
 
 void
 NeckoOriginAttributes::InheritFromDocToNecko(const PrincipalOriginAttributes& aAttrs)
 {
   mAppId = aAttrs.mAppId;
   mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
 
   // addonId is computed from the principal URI and never propagated
   mUserContextId = aAttrs.mUserContextId;
 
   // TODO:
   // Bug 1225353 - DocShell/NeckoOriginAttributes should inherit
   // mSignedPkg accordingly by mSignedPkgInBrowser
+
+  mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
 }
 
 void
 NeckoOriginAttributes::InheritFromDocShellToNecko(const DocShellOriginAttributes& aAttrs)
 {
   mAppId = aAttrs.mAppId;
   mInIsolatedMozBrowser = aAttrs.mInIsolatedMozBrowser;
 
   // addonId is computed from the principal URI and never propagated
   mUserContextId = aAttrs.mUserContextId;
 
   // TODO:
   // Bug 1225353 - DocShell/NeckoOriginAttributes should inherit
   // mSignedPkg accordingly by mSignedPkgInBrowser
+
+  mPrivateBrowsingId = aAttrs.mPrivateBrowsingId;
 }
 
 void
 OriginAttributes::CreateSuffix(nsACString& aStr) const
 {
   UniquePtr<URLParams> params(new URLParams());
   nsAutoString value;
 
@@ -140,16 +150,22 @@ OriginAttributes::CreateSuffix(nsACStrin
     params->Set(NS_LITERAL_STRING("userContextId"), value);
   }
 
   if (!mSignedPkg.IsEmpty()) {
     MOZ_RELEASE_ASSERT(mSignedPkg.FindCharInSet(dom::quota::QuotaManager::kReplaceChars) == kNotFound);
     params->Set(NS_LITERAL_STRING("signedPkg"), mSignedPkg);
   }
 
+  if (mPrivateBrowsingId) {
+    value.Truncate();
+    value.AppendInt(mPrivateBrowsingId);
+    params->Set(NS_LITERAL_STRING("privateBrowsingId"), value);
+  }
+
   aStr.Truncate();
 
   params->Serialize(value);
   if (!value.IsEmpty()) {
     aStr.AppendLiteral("^");
     aStr.Append(NS_ConvertUTF16toUTF8(value));
   }
 
@@ -166,16 +182,20 @@ namespace {
 class MOZ_STACK_CLASS PopulateFromSuffixIterator final
   : public URLParams::ForEachIterator
 {
 public:
   explicit PopulateFromSuffixIterator(OriginAttributes* aOriginAttributes)
     : mOriginAttributes(aOriginAttributes)
   {
     MOZ_ASSERT(aOriginAttributes);
+    // If mPrivateBrowsingId is passed in as >0 and is not present in the suffix,
+    // then it will remain >0 when it should be 0 according to the suffix. Set to 0 before
+    // iterating to fix this.
+    mOriginAttributes->mPrivateBrowsingId = 0;
   }
 
   bool URLParamsIterator(const nsString& aName,
                          const nsString& aValue) override
   {
     if (aName.EqualsLiteral("appId")) {
       nsresult rv;
       int64_t val  = aValue.ToInteger64(&rv);
@@ -212,16 +232,26 @@ public:
     }
 
     if (aName.EqualsLiteral("signedPkg")) {
       MOZ_RELEASE_ASSERT(mOriginAttributes->mSignedPkg.IsEmpty());
       mOriginAttributes->mSignedPkg.Assign(aValue);
       return true;
     }
 
+    if (aName.EqualsLiteral("privateBrowsingId")) {
+      nsresult rv;
+      int64_t val = aValue.ToInteger64(&rv);
+      NS_ENSURE_SUCCESS(rv, false);
+      NS_ENSURE_TRUE(val >= 0 && val <= UINT32_MAX, false);
+      mOriginAttributes->mPrivateBrowsingId = static_cast<uint32_t>(val);
+
+      return true;
+    }
+
     // No other attributes are supported.
     return false;
   }
 
 private:
   OriginAttributes* mOriginAttributes;
 };
 
@@ -257,16 +287,22 @@ OriginAttributes::PopulateFromOrigin(con
     aOriginNoSuffix = origin;
     return true;
   }
 
   aOriginNoSuffix = Substring(origin, 0, pos);
   return PopulateFromSuffix(Substring(origin, pos));
 }
 
+void
+OriginAttributes::SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing)
+{
+  mPrivateBrowsingId = aInPrivateBrowsing ? 1 : 0;
+}
+
 BasePrincipal::BasePrincipal()
 {}
 
 BasePrincipal::~BasePrincipal()
 {}
 
 NS_IMETHODIMP
 BasePrincipal::GetOrigin(nsACString& aOrigin)
--- a/caps/BasePrincipal.h
+++ b/caps/BasePrincipal.h
@@ -28,17 +28,18 @@ class OriginAttributes : public dom::Ori
 {
 public:
   bool operator==(const OriginAttributes& aOther) const
   {
     return mAppId == aOther.mAppId &&
            mInIsolatedMozBrowser == aOther.mInIsolatedMozBrowser &&
            mAddonId == aOther.mAddonId &&
            mUserContextId == aOther.mUserContextId &&
-           mSignedPkg == aOther.mSignedPkg;
+           mSignedPkg == aOther.mSignedPkg &&
+           mPrivateBrowsingId == aOther.mPrivateBrowsingId;
   }
   bool operator!=(const OriginAttributes& aOther) const
   {
     return !(*this == aOther);
   }
 
   // Serializes/Deserializes non-default values into the suffix format, i.e.
   // |!key1=value1&key2=value2|. If there are no non-default attributes, this
@@ -46,16 +47,20 @@ public:
   void CreateSuffix(nsACString& aStr) const;
   bool PopulateFromSuffix(const nsACString& aStr);
 
   // Populates the attributes from a string like
   // |uri!key1=value1&key2=value2| and returns the uri without the suffix.
   bool PopulateFromOrigin(const nsACString& aOrigin,
                           nsACString& aOriginNoSuffix);
 
+  // Helper function to match mIsPrivateBrowsing to existing private browsing
+  // flags. Once all other flags are removed, this can be removed too.
+  void SyncAttributesWithPrivateBrowsing(bool aInPrivateBrowsing);
+
 protected:
   OriginAttributes() {}
   explicit OriginAttributes(const OriginAttributesDictionary& aOther)
     : OriginAttributesDictionary(aOther) {}
 };
 
 class PrincipalOriginAttributes;
 class DocShellOriginAttributes;
@@ -170,16 +175,20 @@ public:
     if (mUserContextId.WasPassed() && mUserContextId.Value() != aAttrs.mUserContextId) {
       return false;
     }
 
     if (mSignedPkg.WasPassed() && mSignedPkg.Value() != aAttrs.mSignedPkg) {
       return false;
     }
 
+    if (mPrivateBrowsingId.WasPassed() && mPrivateBrowsingId.Value() != aAttrs.mPrivateBrowsingId) {
+      return false;
+    }
+
     return true;
   }
 };
 
 /*
  * Base class from which all nsIPrincipal implementations inherit. Use this for
  * default implementations and other commonalities between principal
  * implementations.
--- a/docshell/base/LoadContext.cpp
+++ b/docshell/base/LoadContext.cpp
@@ -47,17 +47,17 @@ LoadContext::LoadContext(nsIPrincipal* a
   , mUsePrivateBrowsing(false)
   , mUseRemoteTabs(false)
 #ifdef DEBUG
   , mIsNotNull(true)
 #endif
 {
   PrincipalOriginAttributes poa = BasePrincipal::Cast(aPrincipal)->OriginAttributesRef();
   mOriginAttributes.InheritFromDocToChildDocShell(poa);
-
+  mOriginAttributes.SyncAttributesWithPrivateBrowsing(mUsePrivateBrowsing);
   if (!aOptionalBase) {
     return;
   }
 
   MOZ_ALWAYS_SUCCEEDS(aOptionalBase->GetIsContent(&mIsContent));
   MOZ_ALWAYS_SUCCEEDS(aOptionalBase->GetUsePrivateBrowsing(&mUsePrivateBrowsing));
   MOZ_ALWAYS_SUCCEEDS(aOptionalBase->GetUseRemoteTabs(&mUseRemoteTabs));
 }
--- a/docshell/base/LoadContext.h
+++ b/docshell/base/LoadContext.h
@@ -49,16 +49,17 @@ public:
     , mIsContent(aToCopy.mIsContent)
     , mUsePrivateBrowsing(aToCopy.mUsePrivateBrowsing)
     , mUseRemoteTabs(aToCopy.mUseRemoteTabs)
     , mOriginAttributes(aAttrs)
 #ifdef DEBUG
     , mIsNotNull(aToCopy.mIsNotNull)
 #endif
   {
+    MOZ_ASSERT(aToCopy.mUsePrivateBrowsing == (aAttrs.mPrivateBrowsingId != 0));
   }
 
   // appId/inIsolatedMozBrowser arguments override those in SerializedLoadContext
   // provided by child process.
   LoadContext(const IPC::SerializedLoadContext& aToCopy,
               uint64_t aNestedFrameId,
               DocShellOriginAttributes& aAttrs)
     : mTopFrameElement(nullptr)
@@ -66,16 +67,17 @@ public:
     , mIsContent(aToCopy.mIsContent)
     , mUsePrivateBrowsing(aToCopy.mUsePrivateBrowsing)
     , mUseRemoteTabs(aToCopy.mUseRemoteTabs)
     , mOriginAttributes(aAttrs)
 #ifdef DEBUG
     , mIsNotNull(aToCopy.mIsNotNull)
 #endif
   {
+    MOZ_ASSERT(aToCopy.mUsePrivateBrowsing == (aAttrs.mPrivateBrowsingId != 0));
   }
 
   LoadContext(dom::Element* aTopFrameElement,
               bool aIsContent,
               bool aUsePrivateBrowsing,
               bool aUseRemoteTabs,
               const DocShellOriginAttributes& aAttrs)
     : mTopFrameElement(do_GetWeakReference(aTopFrameElement))
@@ -83,16 +85,17 @@ public:
     , mIsContent(aIsContent)
     , mUsePrivateBrowsing(aUsePrivateBrowsing)
     , mUseRemoteTabs(aUseRemoteTabs)
     , mOriginAttributes(aAttrs)
 #ifdef DEBUG
     , mIsNotNull(true)
 #endif
   {
+    MOZ_ASSERT(aUsePrivateBrowsing == (aAttrs.mPrivateBrowsingId != 0));
   }
 
   // Constructor taking reserved appId for the safebrowsing cookie.
   explicit LoadContext(uint32_t aAppId)
     : mTopFrameElement(nullptr)
     , mNestedFrameId(0)
     , mIsContent(false)
     , mUsePrivateBrowsing(false)
--- a/docshell/base/SerializedLoadContext.cpp
+++ b/docshell/base/SerializedLoadContext.cpp
@@ -36,16 +36,17 @@ SerializedLoadContext::SerializedLoadCon
     nsCOMPtr<nsIPrivateBrowsingChannel> pbChannel = do_QueryInterface(aChannel);
     if (pbChannel &&
         NS_SUCCEEDED(pbChannel->IsPrivateModeOverriden(&isPrivate,
                                                        &isOverriden)) &&
         isOverriden) {
       mUsePrivateBrowsing = isPrivate;
       mIsPrivateBitValid = true;
     }
+    mOriginAttributes.SyncAttributesWithPrivateBrowsing(mUsePrivateBrowsing);
   }
 }
 
 SerializedLoadContext::SerializedLoadContext(nsIWebSocketChannel* aChannel)
 {
   nsCOMPtr<nsILoadContext> loadContext;
   if (aChannel) {
     NS_QueryNotificationCallbacks(aChannel, loadContext);
@@ -56,16 +57,17 @@ SerializedLoadContext::SerializedLoadCon
 void
 SerializedLoadContext::Init(nsILoadContext* aLoadContext)
 {
   if (aLoadContext) {
     mIsNotNull = true;
     mIsPrivateBitValid = true;
     aLoadContext->GetIsContent(&mIsContent);
     aLoadContext->GetUsePrivateBrowsing(&mUsePrivateBrowsing);
+    mOriginAttributes.SyncAttributesWithPrivateBrowsing(mUsePrivateBrowsing);
     aLoadContext->GetUseRemoteTabs(&mUseRemoteTabs);
     if (!aLoadContext->GetOriginAttributes(mOriginAttributes)) {
       NS_WARNING("GetOriginAttributes failed");
     }
   } else {
     mIsNotNull = false;
     mIsPrivateBitValid = false;
     // none of below values really matter when mIsNotNull == false:
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -809,16 +809,17 @@ nsDocShell::nsDocShell()
   , mInvisible(false)
   , mHasLoadedNonBlankURI(false)
   , mDefaultLoadFlags(nsIRequest::LOAD_NORMAL)
   , mBlankTiming(false)
   , mFrameType(FRAME_TYPE_REGULAR)
   , mParentCharsetSource(0)
   , mJSRunToCompletionDepth(0)
 {
+  AssertOriginAttributesMatchPrivateBrowsing();
   mHistoryID = ++gDocshellIDCounter;
   if (gDocShellCount++ == 0) {
     NS_ASSERTION(sURIFixup == nullptr,
                  "Huh, sURIFixup not null in first nsDocShell ctor!");
 
     CallGetService(NS_URIFIXUP_CONTRACTID, &sURIFixup);
   }
 
@@ -2177,17 +2178,17 @@ nsDocShell::SetAllowJavascript(bool aAll
   RecomputeCanExecuteScripts();
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::GetUsePrivateBrowsing(bool* aUsePrivateBrowsing)
 {
   NS_ENSURE_ARG_POINTER(aUsePrivateBrowsing);
-
+  AssertOriginAttributesMatchPrivateBrowsing();
   *aUsePrivateBrowsing = mInPrivateBrowsing;
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::SetUsePrivateBrowsing(bool aUsePrivateBrowsing)
 {
   nsContentUtils::ReportToConsoleNonLocalized(
@@ -2200,16 +2201,19 @@ nsDocShell::SetUsePrivateBrowsing(bool a
 }
 
 NS_IMETHODIMP
 nsDocShell::SetPrivateBrowsing(bool aUsePrivateBrowsing)
 {
   bool changed = aUsePrivateBrowsing != mInPrivateBrowsing;
   if (changed) {
     mInPrivateBrowsing = aUsePrivateBrowsing;
+
+    mOriginAttributes.SyncAttributesWithPrivateBrowsing(mInPrivateBrowsing);
+
     if (mAffectPrivateSessionLifetime) {
       if (aUsePrivateBrowsing) {
         IncreasePrivateDocShellCount();
       } else {
         DecreasePrivateDocShellCount();
       }
     }
   }
@@ -2269,16 +2273,17 @@ nsDocShell::SetRemoteTabs(bool aUseRemot
   return NS_OK;
 }
 
 NS_IMETHODIMP
 nsDocShell::SetAffectPrivateSessionLifetime(bool aAffectLifetime)
 {
   bool change = aAffectLifetime != mAffectPrivateSessionLifetime;
   if (change && mInPrivateBrowsing) {
+    AssertOriginAttributesMatchPrivateBrowsing();
     if (aAffectLifetime) {
       IncreasePrivateDocShellCount();
     } else {
       DecreasePrivateDocShellCount();
     }
   }
   mAffectPrivateSessionLifetime = aAffectLifetime;
 
@@ -2961,16 +2966,17 @@ nsDocShell::GetSessionStorageForPrincipa
 {
   nsCOMPtr<nsIDOMStorageManager> manager = TopSessionStorageManager();
   if (!manager) {
     return NS_ERROR_UNEXPECTED;
   }
 
   nsCOMPtr<nsPIDOMWindowOuter> domWin = GetWindow();
 
+  AssertOriginAttributesMatchPrivateBrowsing();
   if (aCreate) {
     return manager->CreateStorage(domWin->GetCurrentInnerWindow(), aPrincipal,
                                   aDocumentURI, mInPrivateBrowsing, aStorage);
   }
 
   return manager->GetStorage(domWin->GetCurrentInnerWindow(), aPrincipal,
                              mInPrivateBrowsing, aStorage);
 }
@@ -3655,16 +3661,21 @@ nsDocShell::FindItemWithName(const char1
     // the item is active for the special cases.
     if (foundItem) {
       foundItem.swap(*aResult);
     }
     return NS_OK;
   }
 }
 
+void
+nsDocShell::AssertOriginAttributesMatchPrivateBrowsing(){
+  MOZ_ASSERT((mOriginAttributes.mPrivateBrowsingId != 0) == mInPrivateBrowsing);
+}
+
 nsresult
 nsDocShell::DoFindItemWithName(const char16_t* aName,
                                nsISupports* aRequestor,
                                nsIDocShellTreeItem* aOriginalRequestor,
                                nsIDocShellTreeItem** aResult)
 {
   // First we check our name.
   if (mName.Equals(aName) && ItemIsActive(this) &&
@@ -5758,16 +5769,17 @@ nsDocShell::Destroy()
   mSecurityUI = nullptr;
 
   // Cancel any timers that were set for this docshell; this is needed
   // to break the cycle between us and the timers.
   CancelRefreshURITimers();
 
   if (mInPrivateBrowsing) {
     mInPrivateBrowsing = false;
+    mOriginAttributes.SyncAttributesWithPrivateBrowsing(mInPrivateBrowsing);
     if (mAffectPrivateSessionLifetime) {
       DecreasePrivateDocShellCount();
     }
   }
 
   return NS_OK;
 }
 
@@ -6415,16 +6427,17 @@ nsDocShell::SetTitle(const char16_t* aTi
   // tree owner.
   if (!parent) {
     nsCOMPtr<nsIBaseWindow> treeOwnerAsWin(do_QueryInterface(mTreeOwner));
     if (treeOwnerAsWin) {
       treeOwnerAsWin->SetTitle(aTitle);
     }
   }
 
+  AssertOriginAttributesMatchPrivateBrowsing();
   if (mCurrentURI && mLoadType != LOAD_ERROR_PAGE && mUseGlobalHistory &&
       !mInPrivateBrowsing) {
     nsCOMPtr<IHistory> history = services::GetHistoryService();
     if (history) {
       history->SetURITitle(mCurrentURI, mTitle);
     } else if (mGlobalHistory) {
       mGlobalHistory->SetPageTitle(mCurrentURI, nsString(mTitle));
     }
--- a/docshell/base/nsDocShell.h
+++ b/docshell/base/nsDocShell.h
@@ -1029,16 +1029,20 @@ private:
 
   // Separate function to do the actual name (i.e. not _top, _self etc.)
   // searching for FindItemWithName.
   nsresult DoFindItemWithName(const char16_t* aName,
                               nsISupports* aRequestor,
                               nsIDocShellTreeItem* aOriginalRequestor,
                               nsIDocShellTreeItem** aResult);
 
+  // Helper assertion to enforce that mInPrivateBrowsing is in sync with
+  // OriginAttributes.mPrivateBrowsingId
+  void AssertOriginAttributesMatchPrivateBrowsing();
+
   // Notify consumers of a search being loaded through the observer service:
   void MaybeNotifyKeywordSearchLoading(const nsString& aProvider,
                                        const nsString& aKeyword);
 
 #ifdef DEBUG
   // We're counting the number of |nsDocShells| to help find leaks
   static unsigned long gNumberOfDocShells;
 #endif /* DEBUG */
--- a/dom/base/ChromeUtils.cpp
+++ b/dom/base/ChromeUtils.cpp
@@ -174,13 +174,14 @@ ChromeUtils::FillNonDefaultOriginAttribu
 ChromeUtils::IsOriginAttributesEqual(dom::GlobalObject& aGlobal,
                                      const dom::OriginAttributesDictionary& aA,
                                      const dom::OriginAttributesDictionary& aB)
 {
   return aA.mAddonId == aB.mAddonId &&
          aA.mAppId == aB.mAppId &&
          aA.mInIsolatedMozBrowser == aB.mInIsolatedMozBrowser &&
          aA.mSignedPkg == aB.mSignedPkg &&
-         aA.mUserContextId == aB.mUserContextId;
+         aA.mUserContextId == aB.mUserContextId &&
+         aA.mPrivateBrowsingId == aB.mPrivateBrowsingId;
 }
 
 } // namespace dom
 } // namespace mozilla
--- a/dom/base/nsFrameLoader.cpp
+++ b/dom/base/nsFrameLoader.cpp
@@ -2141,16 +2141,26 @@ nsFrameLoader::MaybeCreateDocShell()
   }
 
   // Grab the userContextId from owner if XUL
   nsresult rv = PopulateUserContextIdFromAttribute(attrs);
   if (NS_WARN_IF(NS_FAILED(rv))) {
     return rv;
   }
 
+  bool isPrivate = false;
+  nsCOMPtr<nsILoadContext> parentContext = do_QueryInterface(docShell);
+  NS_ENSURE_STATE(parentContext);
+
+  rv = parentContext->GetUsePrivateBrowsing(&isPrivate);
+  if (NS_WARN_IF(NS_FAILED(rv))) {
+    return rv;
+  }
+  attrs.SyncAttributesWithPrivateBrowsing(isPrivate);
+
   nsDocShell::Cast(mDocShell)->SetOriginAttributes(attrs);
 
   if (OwnerIsMozBrowserOrAppFrame()) {
     // For inproc frames, set the docshell properties.
     nsAutoString name;
     if (mOwnerContent->GetAttr(kNameSpaceID_None, nsGkAtoms::name, name)) {
       docShell->SetName(name);
     }
@@ -3386,16 +3396,19 @@ nsFrameLoader::GetNewTabContext(MutableT
     attrs.mUserContextId = userContextId;
   }
 
   nsAutoString presentationURLStr;
   mOwnerContent->GetAttr(kNameSpaceID_None,
                          nsGkAtoms::mozpresentation,
                          presentationURLStr);
 
+  bool isPrivate = mOwnerContent->HasAttr(kNameSpaceID_None, nsGkAtoms::mozprivatebrowsing);
+  attrs.SyncAttributesWithPrivateBrowsing(isPrivate);
+
   bool tabContextUpdated =
     aTabContext->SetTabContext(OwnerIsMozBrowserFrame(),
                                mIsPrerendered,
                                ownApp,
                                containingApp,
                                attrs,
                                signedPkgOrigin,
                                presentationURLStr);
--- a/dom/ipc/TabChild.cpp
+++ b/dom/ipc/TabChild.cpp
@@ -807,16 +807,18 @@ TabChild::Init()
     nullptr, 0,              // no parents
     LayoutDeviceIntRect(0, 0, 0, 0),
     nullptr                  // HandleWidgetEvent
   );
 
   baseWindow->InitWindow(0, mPuppetWidget, 0, 0, 0, 0);
   baseWindow->Create();
 
+  // Set the tab context attributes then pass to docShell
+  SetPrivateBrowsingAttributes(mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW);
   NotifyTabContextUpdated();
 
   // IPC uses a WebBrowser object for which DNS prefetching is turned off
   // by default. But here we really want it, so enable it explicitly
   nsCOMPtr<nsIWebBrowserSetup> webBrowserSetup =
     do_QueryInterface(baseWindow);
   if (webBrowserSetup) {
     webBrowserSetup->SetProperty(nsIWebBrowserSetup::SETUP_ALLOW_DNS_PREFETCH,
--- a/dom/ipc/TabContext.cpp
+++ b/dom/ipc/TabContext.cpp
@@ -155,16 +155,22 @@ TabContext::SetTabContext(const TabConte
   NS_ENSURE_FALSE(mInitialized, false);
 
   *this = aContext;
   mInitialized = true;
 
   return true;
 }
 
+void
+TabContext::SetPrivateBrowsingAttributes(bool aIsPrivateBrowsing)
+{
+  mOriginAttributes.SyncAttributesWithPrivateBrowsing(aIsPrivateBrowsing);
+}
+
 bool
 TabContext::UpdateTabContextAfterSwap(const TabContext& aContext)
 {
   // This is only used after already initialized.
   MOZ_ASSERT(mInitialized);
 
   // The only permissable change is to `mIsMozBrowserElement`.  All other fields
   // must match for the change to be accepted.
--- a/dom/ipc/TabContext.h
+++ b/dom/ipc/TabContext.h
@@ -149,16 +149,21 @@ protected:
    */
 
   /**
    * Set this TabContext to match the given TabContext.
    */
   bool SetTabContext(const TabContext& aContext);
 
   /**
+   * Set the tab context's origin attributes to a private browsing value.
+   */
+  void SetPrivateBrowsingAttributes(bool aIsPrivateBrowsing);
+
+  /**
    * Set the TabContext for this frame. This can either be:
    *  - an app frame (with the given own app) inside the given owner app. Either
    *    apps can be null.
    *  - a browser frame inside the given owner app (which may be null).
    *  - a non-browser, non-app frame. Both own app and owner app should be null.
    */
   bool SetTabContext(bool aIsMozBrowserElement,
                      bool aIsPrerendered,
--- a/dom/ipc/TabParent.cpp
+++ b/dom/ipc/TabParent.cpp
@@ -2769,19 +2769,21 @@ TabParent::RecvRespondStartSwipeEvent(co
 
 already_AddRefed<nsILoadContext>
 TabParent::GetLoadContext()
 {
   nsCOMPtr<nsILoadContext> loadContext;
   if (mLoadContext) {
     loadContext = mLoadContext;
   } else {
+    bool isPrivate = mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW;
+    SetPrivateBrowsingAttributes(isPrivate);
     loadContext = new LoadContext(GetOwnerElement(),
                                   true /* aIsContent */,
-                                  mChromeFlags & nsIWebBrowserChrome::CHROME_PRIVATE_WINDOW,
+                                  isPrivate,
                                   mChromeFlags & nsIWebBrowserChrome::CHROME_REMOTE_WINDOW,
                                   OriginAttributesRef());
     mLoadContext = loadContext;
   }
   return loadContext.forget();
 }
 
 NS_IMETHODIMP
--- a/dom/tests/mochitest/localstorage/test_localStorageQuotaPrivateBrowsing_perwindowpb.html
+++ b/dom/tests/mochitest/localstorage/test_localStorageQuotaPrivateBrowsing_perwindowpb.html
@@ -133,17 +133,21 @@ function onMessageReceived(event, aWindo
   switch (event.data) {
     // Indication of the frame onload event
     case "frame loaded":
       if (--slaveLoadsPending)
         break;
       // Just fall through...
     // Indication of successfully finished step of a test
     case "perf":
-      slave.postMessage("step", slaveOrigin);
+      // postMessage should send to the slaveOrigin. However with the addition of private
+      // browsing flags in origin attributes this will cause postMessage to fail. The origin of this
+      // window has false privatebrowsing, while the recipient is in a private window.
+      // To fix this issue and preserve the integrity of the test a * is passed to get around origin equality.
+      slave.postMessage("step", "*");
       break;
     // Indication of all test parts finish (from any of the frames)
     case "done":
       aWindow.content.localStorage.clear();
       slaveLoadsPending = 1;
       doNextTest(aWindow);
       break;
     // Any other message indicates error or succes message of a test
--- a/dom/webidl/ChromeUtils.webidl
+++ b/dom/webidl/ChromeUtils.webidl
@@ -75,16 +75,18 @@ interface ChromeUtils : ThreadSafeChrome
  * (3) Update the methods on mozilla::OriginAttributesPattern, including matching.
  */
 dictionary OriginAttributesDictionary {
   unsigned long appId = 0;
   unsigned long userContextId = 0;
   boolean inIsolatedMozBrowser = false;
   DOMString addonId = "";
   DOMString signedPkg = "";
+  unsigned long privateBrowsingId = 0;
 };
 dictionary OriginAttributesPatternDictionary {
   unsigned long appId;
   unsigned long userContextId;
   boolean inIsolatedMozBrowser;
   DOMString addonId;
   DOMString signedPkg;
+  unsigned long privateBrowsingId;
 };
--- a/extensions/cookie/nsPermissionManager.cpp
+++ b/extensions/cookie/nsPermissionManager.cpp
@@ -99,16 +99,40 @@ LogToConsole(const nsAString& aMsg)
 #define ENSURE_NOT_CHILD_PROCESS_NORET \
   ENSURE_NOT_CHILD_PROCESS_(;)
 
 ////////////////////////////////////////////////////////////////////////////////
 
 namespace {
 
 nsresult
+GetOriginFromPrincipal(nsIPrincipal* aPrincipal, nsACString& aOrigin)
+{
+  nsresult rv = aPrincipal->GetOriginNoSuffix(aOrigin);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  nsAutoCString suffix;
+  rv = aPrincipal->GetOriginSuffix(suffix);
+  NS_ENSURE_SUCCESS(rv, rv);
+
+  mozilla::PrincipalOriginAttributes attrs;
+  if (!attrs.PopulateFromSuffix(suffix)) {
+    return NS_ERROR_FAILURE;
+  }
+
+  // mPrivateBrowsingId must be set to false because PermissionManager is not supposed to have
+  // any knowledge of private browsing. Allowing it to be true changes the suffix being hashed.
+  attrs.mPrivateBrowsingId = 0;
+
+  attrs.CreateSuffix(suffix);
+  aOrigin.Append(suffix);
+  return NS_OK;
+}
+
+nsresult
 GetPrincipalFromOrigin(const nsACString& aOrigin, nsIPrincipal** aPrincipal)
 {
   nsAutoCString originNoSuffix;
   mozilla::PrincipalOriginAttributes attrs;
   if (!attrs.PopulateFromOrigin(aOrigin, originNoSuffix)) {
     return NS_ERROR_FAILURE;
   }
 
@@ -389,17 +413,17 @@ UpgradeHostToOriginAndInsert(const nsACS
       return NS_OK;
     }
 
     nsCOMPtr<nsIPrincipal> principal;
     rv = GetPrincipal(uri, aAppId, aIsInIsolatedMozBrowserElement, getter_AddRefs(principal));
     NS_ENSURE_SUCCESS(rv, rv);
 
     nsAutoCString origin;
-    rv = principal->GetOrigin(origin);
+    rv = GetOriginFromPrincipal(principal, origin);
     NS_ENSURE_SUCCESS(rv, rv);
 
     return aHelper->Insert(origin, aType, aPermission,
                            aExpireType, aExpireTime, aModificationTime);
     return NS_OK;
   }
 
   // The user may use this host at non-standard ports or protocols, we can use their history
@@ -497,17 +521,17 @@ UpgradeHostToOriginAndInsert(const nsACS
       if (NS_WARN_IF(NS_FAILED(rv))) continue;
 
       // We now have a URI which we can make a nsIPrincipal out of
       nsCOMPtr<nsIPrincipal> principal;
       rv = GetPrincipal(uri, aAppId, aIsInIsolatedMozBrowserElement, getter_AddRefs(principal));
       if (NS_WARN_IF(NS_FAILED(rv))) continue;
 
       nsAutoCString origin;
-      rv = principal->GetOrigin(origin);
+      rv = GetOriginFromPrincipal(principal, origin);
       if (NS_WARN_IF(NS_FAILED(rv))) continue;
 
       // Ensure that we don't insert the same origin repeatedly
       if (insertedOrigins.Contains(origin)) {
         continue;
       }
 
       foundHistory = true;
@@ -542,30 +566,30 @@ UpgradeHostToOriginAndInsert(const nsACS
 
     // http:// URI default
     rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("http://") + hostSegment);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = GetPrincipal(uri, aAppId, aIsInIsolatedMozBrowserElement, getter_AddRefs(principal));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = principal->GetOrigin(origin);
+    rv = GetOriginFromPrincipal(principal, origin);
     NS_ENSURE_SUCCESS(rv, rv);
 
     aHelper->Insert(origin, aType, aPermission,
                     aExpireType, aExpireTime, aModificationTime);
 
     // https:// URI default
     rv = NS_NewURI(getter_AddRefs(uri), NS_LITERAL_CSTRING("https://") + hostSegment);
     NS_ENSURE_SUCCESS(rv, rv);
 
     rv = GetPrincipal(uri, aAppId, aIsInIsolatedMozBrowserElement, getter_AddRefs(principal));
     NS_ENSURE_SUCCESS(rv, rv);
 
-    rv = principal->GetOrigin(origin);
+    rv = GetOriginFromPrincipal(principal, origin);
     NS_ENSURE_SUCCESS(rv, rv);
 
     aHelper->Insert(origin, aType, aPermission,
                     aExpireType, aExpireTime, aModificationTime);
   }
 
   return NS_OK;
 }
@@ -578,17 +602,17 @@ IsExpandedPrincipal(nsIPrincipal* aPrinc
 }
 
 } // namespace
 
 ////////////////////////////////////////////////////////////////////////////////
 
 nsPermissionManager::PermissionKey::PermissionKey(nsIPrincipal* aPrincipal)
 {
-  MOZ_ALWAYS_SUCCEEDS(aPrincipal->GetOrigin(mOrigin));
+  MOZ_ALWAYS_SUCCEEDS(GetOriginFromPrincipal(aPrincipal, mOrigin));
 }
 
 /**
  * Simple callback used by |AsyncClose| to trigger a treatment once
  * the database is closed.
  *
  * Note: Beware that, if you hold onto a |CloseDatabaseListener| from a
  * |nsPermissionManager|, this will create a cycle.
@@ -1537,17 +1561,17 @@ nsPermissionManager::AddInternal(nsIPrin
                                  uint32_t              aExpireType,
                                  int64_t               aExpireTime,
                                  int64_t               aModificationTime,
                                  NotifyOperationType   aNotifyOperation,
                                  DBOperationType       aDBOperation,
                                  const bool            aIgnoreSessionPermissions)
 {
   nsAutoCString origin;
-  nsresult rv = aPrincipal->GetOrigin(origin);
+  nsresult rv = GetOriginFromPrincipal(aPrincipal, origin);
   NS_ENSURE_SUCCESS(rv, rv);
 
   if (!IsChildProcess()) {
     IPC::Permission permission(origin, aType, aPermission,
                                aExpireType, aExpireTime);
 
     nsTArray<ContentParent*> cplist;
     ContentParent::GetAll(cplist);
--- a/netwerk/base/LoadContextInfo.cpp
+++ b/netwerk/base/LoadContextInfo.cpp
@@ -18,16 +18,17 @@ namespace net {
 
 NS_IMPL_ISUPPORTS(LoadContextInfo, nsILoadContextInfo)
 
 LoadContextInfo::LoadContextInfo(bool aIsPrivate, bool aIsAnonymous, NeckoOriginAttributes aOriginAttributes)
   : mIsPrivate(aIsPrivate)
   , mIsAnonymous(aIsAnonymous)
   , mOriginAttributes(aOriginAttributes)
 {
+  mOriginAttributes.SyncAttributesWithPrivateBrowsing(mIsPrivate);
 }
 
 LoadContextInfo::~LoadContextInfo()
 {
 }
 
 NS_IMETHODIMP LoadContextInfo::GetIsPrivate(bool *aIsPrivate)
 {
@@ -63,17 +64,19 @@ NS_IMETHODIMP LoadContextInfoFactory::Ge
 {
   nsCOMPtr<nsILoadContextInfo> info = GetLoadContextInfo(false, false, NeckoOriginAttributes());
   info.forget(aDefault);
   return NS_OK;
 }
 
 NS_IMETHODIMP LoadContextInfoFactory::GetPrivate(nsILoadContextInfo * *aPrivate)
 {
-  nsCOMPtr<nsILoadContextInfo> info = GetLoadContextInfo(true, false, NeckoOriginAttributes());
+  NeckoOriginAttributes attrs;
+  attrs.SyncAttributesWithPrivateBrowsing(aPrivate);
+  nsCOMPtr<nsILoadContextInfo> info = GetLoadContextInfo(true, false, attrs);
   info.forget(aPrivate);
   return NS_OK;
 }
 
 NS_IMETHODIMP LoadContextInfoFactory::GetAnonymous(nsILoadContextInfo * *aAnonymous)
 {
   nsCOMPtr<nsILoadContextInfo> info = GetLoadContextInfo(false, true, NeckoOriginAttributes());
   info.forget(aAnonymous);
@@ -138,16 +141,18 @@ GetLoadContextInfo(nsILoadContext *aLoad
     return new LoadContextInfo(false, aIsAnonymous,
                                NeckoOriginAttributes(nsILoadContextInfo::NO_APP_ID, false));
   }
 
   bool pb = aLoadContext->UsePrivateBrowsing();
   DocShellOriginAttributes doa;
   aLoadContext->GetOriginAttributes(doa);
 
+  doa.SyncAttributesWithPrivateBrowsing(pb);
+
   NeckoOriginAttributes noa;
   noa.InheritFromDocShellToNecko(doa);
 
   return new LoadContextInfo(pb, aIsAnonymous, noa);
 }
 
 LoadContextInfo*
 GetLoadContextInfo(nsIDOMWindow *aWindow,
--- a/netwerk/base/nsNetUtil.cpp
+++ b/netwerk/base/nsNetUtil.cpp
@@ -1269,16 +1269,17 @@ NS_GetOriginAttributes(nsIChannel *aChan
     NS_QueryNotificationCallbacks(aChannel, loadContext);
     if (!loadContext) {
         return false;
     }
 
     DocShellOriginAttributes doa;
     loadContext->GetOriginAttributes(doa);
     aAttributes.InheritFromDocShellToNecko(doa);
+    aAttributes.SyncAttributesWithPrivateBrowsing(NS_UsePrivateBrowsing(aChannel));
     return true;
 }
 
 bool
 NS_GetAppInfo(nsIChannel *aChannel,
               uint32_t *aAppID,
               bool *aIsInIsolatedMozBrowserElement)
 {
--- a/netwerk/ipc/NeckoParent.cpp
+++ b/netwerk/ipc/NeckoParent.cpp
@@ -147,16 +147,17 @@ NeckoParent::GetValidatedAppInfo(const S
     if (aSerialized.mOriginAttributes.mUserContextId != tabContext.OriginAttributesRef().mUserContextId) {
       continue;
     }
     aAttrs = DocShellOriginAttributes();
     aAttrs.mAppId = appId;
     aAttrs.mInIsolatedMozBrowser = inBrowserElement;
     aAttrs.mSignedPkg = aSerialized.mOriginAttributes.mSignedPkg;
     aAttrs.mUserContextId = aSerialized.mOriginAttributes.mUserContextId;
+    aAttrs.mPrivateBrowsingId = aSerialized.mOriginAttributes.mPrivateBrowsingId;
 
     return nullptr;
   }
 
   if (contextArray.Length() != 0) {
     return "App does not have permission";
   }
 
@@ -183,16 +184,17 @@ NeckoParent::CreateChannelLoadContext(co
   const char* error = GetValidatedAppInfo(aSerialized, aContent, attrs);
   if (error) {
     return error;
   }
 
   // if !UsingNeckoIPCSecurity(), we may not have a LoadContext to set. This is
   // the common case for most xpcshell tests.
   if (aSerialized.IsNotNull()) {
+    attrs.SyncAttributesWithPrivateBrowsing(aSerialized.mUsePrivateBrowsing);
     switch (aBrowser.type()) {
       case PBrowserOrId::TPBrowserParent:
       {
         RefPtr<TabParent> tabParent =
           TabParent::GetFrom(aBrowser.get_PBrowserParent());
         dom::Element* topFrameElement = nullptr;
         if (tabParent) {
           topFrameElement = tabParent->GetOwnerElement();
@@ -899,16 +901,17 @@ NeckoParent::RecvPredPredict(const ipc::
   nsCOMPtr<nsIURI> sourceURI = DeserializeURI(aSourceURI);
 
   // We only actually care about the loadContext.mPrivateBrowsing, so we'll just
   // pass dummy params for nestFrameId, and originAttributes.
   uint64_t nestedFrameId = 0;
   DocShellOriginAttributes attrs(NECKO_UNKNOWN_APP_ID, false);
   nsCOMPtr<nsILoadContext> loadContext;
   if (aLoadContext.IsNotNull()) {
+    attrs.SyncAttributesWithPrivateBrowsing(aLoadContext.mUsePrivateBrowsing);
     loadContext = new LoadContext(aLoadContext, nestedFrameId, attrs);
   }
 
   // Get the current predictor
   nsresult rv = NS_OK;
   nsCOMPtr<nsINetworkPredictor> predictor =
     do_GetService("@mozilla.org/network/predictor;1", &rv);
   NS_ENSURE_SUCCESS(rv, false);
@@ -931,16 +934,17 @@ NeckoParent::RecvPredLearn(const ipc::UR
   nsCOMPtr<nsIURI> sourceURI = DeserializeURI(aSourceURI);
 
   // We only actually care about the loadContext.mPrivateBrowsing, so we'll just
   // pass dummy params for nestFrameId, and originAttributes;
   uint64_t nestedFrameId = 0;
   DocShellOriginAttributes attrs(NECKO_UNKNOWN_APP_ID, false);
   nsCOMPtr<nsILoadContext> loadContext;
   if (aLoadContext.IsNotNull()) {
+    attrs.SyncAttributesWithPrivateBrowsing(aLoadContext.mUsePrivateBrowsing);
     loadContext = new LoadContext(aLoadContext, nestedFrameId, attrs);
   }
 
   // Get the current predictor
   nsresult rv = NS_OK;
   nsCOMPtr<nsINetworkPredictor> predictor =
     do_GetService("@mozilla.org/network/predictor;1", &rv);
   NS_ENSURE_SUCCESS(rv, false);
--- a/netwerk/test/TestCookie.cpp
+++ b/netwerk/test/TestCookie.cpp
@@ -743,10 +743,13 @@ main(int32_t argc, char *argv[])
     sBuffer = nullptr;
 
     return 0;
 }
 
 // Stubs to make this test happy
 
 mozilla::dom::OriginAttributesDictionary::OriginAttributesDictionary()
-  : mAppId(0), mInIsolatedMozBrowser(false), mUserContextId(0)
+  : mAppId(0),
+    mInIsolatedMozBrowser(false),
+    mPrivateBrowsingId(0),
+    mUserContextId(0)
 {}