Commit 8f2ceafb authored by Nika Layzell's avatar Nika Layzell
Browse files

Bug 1580565 - Part 4: Use WindowContext to manage BrowsingContext cached status, r=farre

The existing infrastructure which stored cached BrowsingContexts on the
BrowsingContextGroup was added before WindowContexts were added, and can cause
racing issues with partially discarded trees during process switches.

Differential Revision: https://phabricator.services.mozilla.com/D71238
parent 989454dc
This diff is collapsed.
......@@ -11,6 +11,7 @@
#include "mozilla/LinkedList.h"
#include "mozilla/Maybe.h"
#include "mozilla/RefPtr.h"
#include "mozilla/Span.h"
#include "mozilla/Tuple.h"
#include "mozilla/WeakPtr.h"
#include "mozilla/dom/BindingDeclarations.h"
......@@ -32,6 +33,7 @@
#include "nsILoadContext.h"
class nsDocShellLoadState;
class nsGlobalWindowInner;
class nsGlobalWindowOuter;
class nsILoadInfo;
class nsIPrincipal;
......@@ -149,8 +151,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
public:
enum class Type { Chrome, Content };
using Children = nsTArray<RefPtr<BrowsingContext>>;
static void Init();
static LogModule* GetLog();
static void CleanupContexts(uint64_t aProcessId);
......@@ -186,7 +186,7 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
// `EnsureAttached()` must be called before the BrowsingContext is used for a
// DocShell, BrowserParent, or BrowserBridgeChild.
static already_AddRefed<BrowsingContext> CreateDetached(
BrowsingContext* aParent, BrowsingContext* aOpener,
nsGlobalWindowInner* aParent, BrowsingContext* aOpener,
const nsAString& aName, Type aType);
void EnsureAttached();
......@@ -253,13 +253,6 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
// Prepare this BrowsingContext to leave the current process.
void PrepareForProcessChange();
// Remove all children from the current BrowsingContext and cache
// them to allow them to be attached again.
void CacheChildren(bool aFromIPC = false);
// Restore cached browsing contexts.
void RestoreChildren(Children&& aChildren, bool aFromIPC = false);
// Triggers a load in the process which currently owns this BrowsingContext.
nsresult LoadURI(nsDocShellLoadState* aLoadState, bool aSetNavigating = false);
......@@ -273,8 +266,7 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
void DisplayLoadError(const nsAString& aURI);
// Determine if the current BrowsingContext was 'cached' by the logic in
// CacheChildren.
// Determine if the current BrowsingContext is in the BFCache.
bool IsCached();
// Check that this browsing context is targetable for navigations (i.e. that
......@@ -302,6 +294,10 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
}
BrowsingContext* Top();
// NOTE: Unlike `GetEmbedderWindowGlobal`, `GetParentWindow` does not cross
// toplevel content browser boundaries.
WindowContext* GetParentWindow() const { return mParentWindow; }
already_AddRefed<BrowsingContext> GetOpener() const {
RefPtr<BrowsingContext> opener(Get(GetOpenerId()));
if (!mIsDiscarded && opener && !opener->mIsDiscarded) {
......@@ -342,8 +338,12 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
uint32_t SandboxFlags() { return GetSandboxFlags(); }
void GetChildren(Children& aChildren);
Span<RefPtr<BrowsingContext>> Children() const;
void GetChildren(nsTArray<RefPtr<BrowsingContext>>& aChildren);
const nsTArray<RefPtr<WindowContext>>& GetWindowContexts() {
return mWindowContexts;
}
void GetWindowContexts(nsTArray<RefPtr<WindowContext>>& aWindows);
void RegisterWindowContext(WindowContext* aWindow);
......@@ -454,22 +454,17 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS(BrowsingContext)
NS_DECL_NSILOADCONTEXT
const Children& GetChildren() { return mChildren; }
const nsTArray<RefPtr<WindowContext>>& GetWindowContexts() {
return mWindowContexts;
}
// Perform a pre-order walk of this BrowsingContext subtree.
void PreOrderWalk(const std::function<void(BrowsingContext*)>& aCallback) {
aCallback(this);
for (auto& child : GetChildren()) {
for (auto& child : Children()) {
child->PreOrderWalk(aCallback);
}
}
// Perform an post-order walk of this BrowsingContext subtree.
void PostOrderWalk(const std::function<void(BrowsingContext*)>& aCallback) {
for (auto& child : GetChildren()) {
for (auto& child : Children()) {
child->PostOrderWalk(aCallback);
}
......@@ -486,7 +481,7 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
void Focus(CallerType aCallerType, ErrorResult& aError);
void Blur(ErrorResult& aError);
WindowProxyHolder GetFrames(ErrorResult& aError);
int32_t Length() const { return mChildren.Length(); }
int32_t Length() const { return Children().Length(); }
Nullable<WindowProxyHolder> GetTop(ErrorResult& aError);
void GetOpener(JSContext* aCx, JS::MutableHandle<JS::Value> aOpener,
ErrorResult& aError) const;
......@@ -527,18 +522,26 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
// deserialized before other BrowsingContext in the BrowsingContextGroup
// have been initialized.
uint64_t mParentId = 0;
already_AddRefed<BrowsingContext> GetParent();
already_AddRefed<WindowContext> GetParent();
already_AddRefed<BrowsingContext> GetOpener();
uint64_t GetOpenerId() const { return mozilla::Get<IDX_OpenerId>(mFields); }
bool mCached = false;
bool mWindowless = false;
bool mUseRemoteTabs = false;
bool mUseRemoteSubframes = false;
OriginAttributes mOriginAttributes;
FieldTuple mFields;
bool operator==(const IPCInitializer& aOther) const {
return mId == aOther.mId && mParentId == aOther.mParentId &&
mWindowless == aOther.mWindowless &&
mUseRemoteTabs == aOther.mUseRemoteTabs &&
mUseRemoteSubframes == aOther.mUseRemoteSubframes &&
mOriginAttributes == aOther.mOriginAttributes &&
mFields == aOther.mFields;
}
};
// Create an IPCInitializer object for this BrowsingContext.
......@@ -569,7 +572,7 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
protected:
virtual ~BrowsingContext();
BrowsingContext(BrowsingContext* aParent, BrowsingContextGroup* aGroup,
BrowsingContext(WindowContext* aParentWindow, BrowsingContextGroup* aGroup,
uint64_t aBrowsingContextId, Type aType,
FieldTuple&& aFields);
......@@ -720,10 +723,11 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
const uint64_t mBrowsingContextId;
RefPtr<BrowsingContextGroup> mGroup;
RefPtr<WindowContext> mParentWindow;
// NOTE: `mParent` must be the same as `mParentWindow->GetBrowsingContext()`
// at all times.
// FIXME: Consider removing this field?
RefPtr<BrowsingContext> mParent;
// Note: BrowsingContext_Binding::ClearCachedChildrenValue must be called any
// time this array is mutated to keep the JS-exposed reflection in sync.
Children mChildren;
nsCOMPtr<nsIDocShell> mDocShell;
RefPtr<Element> mEmbedderElement;
......@@ -832,7 +836,6 @@ extern bool GetRemoteOuterWindowProxy(JSContext* aCx, BrowsingContext* aContext,
using BrowsingContextTransaction = BrowsingContext::BaseTransaction;
using BrowsingContextInitializer = BrowsingContext::IPCInitializer;
using BrowsingContextChildren = BrowsingContext::Children;
using MaybeDiscardedBrowsingContext = MaybeDiscarded<BrowsingContext>;
// Specialize the transaction object for every translation unit it's used in.
......
......@@ -69,6 +69,35 @@ void BrowsingContextGroup::Unsubscribe(ContentParent* aOriginProcess) {
MOZ_DIAGNOSTIC_ASSERT(aOriginProcess);
mSubscribers.RemoveEntry(aOriginProcess);
aOriginProcess->OnBrowsingContextGroupUnsubscribe(this);
// If this origin process still embeds any non-discarded BrowsingContexts in
// this BrowsingContextGroup, make sure to discard them, as this process is
// going away.
nsTArray<RefPtr<BrowsingContext>> toDiscard;
for (auto& context : mContexts) {
if (context.GetKey()->Canonical()->IsEmbeddedInProcess(
aOriginProcess->ChildID())) {
toDiscard.AppendElement(context.GetKey());
}
}
for (auto& context : toDiscard) {
context->Detach(/* aFromIPC */ true);
}
}
static void CollectContextInitializers(
Span<RefPtr<BrowsingContext>> aContexts,
nsTArray<SyncedContextInitializer>& aInits) {
// The order that we record these initializers is important, as it will keep
// the order that children are attached to their parent in the newly connected
// content process consistent.
for (auto& context : aContexts) {
aInits.AppendElement(context->GetIPCInitializer());
for (auto& window : context->GetWindowContexts()) {
aInits.AppendElement(window->GetIPCInitializer());
CollectContextInitializers(window->Children(), aInits);
}
}
}
void BrowsingContextGroup::EnsureSubscribed(ContentParent* aProcess) {
......@@ -79,79 +108,33 @@ void BrowsingContextGroup::EnsureSubscribed(ContentParent* aProcess) {
Subscribe(aProcess);
bool sendFocused = false;
bool sendActive = false;
BrowsingContext* focused = nullptr;
BrowsingContext* active = nullptr;
nsFocusManager* fm = nsFocusManager::GetFocusManager();
if (fm) {
focused = fm->GetFocusedBrowsingContextInChrome();
active = fm->GetActiveBrowsingContextInChrome();
}
nsTArray<BrowsingContext::IPCInitializer> inits(mContexts.Count());
nsTArray<WindowContext::IPCInitializer> windowInits(mContexts.Count());
// FIXME: This won't send non-discarded children of discarded BCs, but those
// BCs will be in the process of being destroyed anyway.
// FIXME: Prevent that situation from occuring.
nsTArray<SyncedContextInitializer> inits(mContexts.Count() * 2);
CollectContextInitializers(mToplevels, inits);
auto addInits = [&](BrowsingContext* aContext) {
inits.AppendElement(aContext->GetIPCInitializer());
if (focused == aContext) {
sendFocused = true;
}
if (active == aContext) {
sendActive = true;
// Send all of our contexts to the target content process.
Unused << aProcess->SendRegisterBrowsingContextGroup(inits);
// If the focused or active BrowsingContexts belong in this group, tell the
// newly subscribed process.
if (nsFocusManager* fm = nsFocusManager::GetFocusManager()) {
BrowsingContext* focused = fm->GetFocusedBrowsingContextInChrome();
if (focused && focused->Group() != this) {
focused = nullptr;
}
for (auto& window : aContext->GetWindowContexts()) {
windowInits.AppendElement(window->GetIPCInitializer());
BrowsingContext* active = fm->GetActiveBrowsingContextInChrome();
if (active && active->Group() != this) {
active = nullptr;
}
};
// First, perform a pre-order walk of our BrowsingContext objects from our
// toplevels. This should visit every active BrowsingContext.
for (auto& context : mToplevels) {
MOZ_DIAGNOSTIC_ASSERT(!IsContextCached(context),
"cached contexts must have a parent");
context->PreOrderWalk(addInits);
}
// Ensure that cached BrowsingContext objects are also visited, by visiting
// them after mToplevels.
for (auto iter = mCachedContexts.Iter(); !iter.Done(); iter.Next()) {
iter.Get()->GetKey()->PreOrderWalk(addInits);
}
// We should have visited every browsing context.
MOZ_DIAGNOSTIC_ASSERT(inits.Length() == mContexts.Count(),
"Visited the wrong number of contexts!");
// Send all of our contexts to the target content process.
Unused << aProcess->SendRegisterBrowsingContextGroup(inits, windowInits);
if (sendActive || sendFocused) {
Unused << aProcess->SendSetupFocusedAndActive(
sendFocused ? focused : nullptr, sendActive ? active : nullptr);
}
}
bool BrowsingContextGroup::IsContextCached(BrowsingContext* aContext) const {
MOZ_DIAGNOSTIC_ASSERT(aContext);
return mCachedContexts.Contains(aContext);
}
void BrowsingContextGroup::CacheContext(BrowsingContext* aContext) {
mCachedContexts.PutEntry(aContext);
}
void BrowsingContextGroup::CacheContexts(
const BrowsingContext::Children& aContexts) {
for (BrowsingContext* child : aContexts) {
mCachedContexts.PutEntry(child);
if (focused || active) {
Unused << aProcess->SendSetupFocusedAndActive(focused, active);
}
}
}
bool BrowsingContextGroup::EvictCachedContext(BrowsingContext* aContext) {
return mCachedContexts.EnsureRemoved(aContext);
}
BrowsingContextGroup::~BrowsingContextGroup() {
UnsubscribeAllContentParents();
}
......@@ -260,8 +243,30 @@ void BrowsingContextGroup::RemoveDocument(const nsACString& aKey,
}
}
already_AddRefed<BrowsingContextGroup> BrowsingContextGroup::Select(
WindowContext* aParent, BrowsingContext* aOpener) {
if (aParent) {
return do_AddRef(aParent->Group());
}
if (aOpener) {
return do_AddRef(aOpener->Group());
}
return MakeAndAddRef<BrowsingContextGroup>();
}
already_AddRefed<BrowsingContextGroup> BrowsingContextGroup::Select(
uint64_t aParentId, uint64_t aOpenerId) {
RefPtr<WindowContext> parent = WindowContext::GetById(aParentId);
MOZ_RELEASE_ASSERT(parent || aParentId == 0);
RefPtr<BrowsingContext> opener = BrowsingContext::Get(aOpenerId);
MOZ_RELEASE_ASSERT(opener || aOpenerId == 0);
return Select(parent, opener);
}
NS_IMPL_CYCLE_COLLECTION_WRAPPERCACHE(BrowsingContextGroup, mContexts,
mToplevels, mSubscribers, mCachedContexts,
mToplevels, mSubscribers,
mTimerEventQueue, mWorkerEventQueue)
NS_IMPL_CYCLE_COLLECTION_ROOT_NATIVE(BrowsingContextGroup, AddRef)
......
......@@ -21,6 +21,7 @@ class ThrottledEventQueue;
namespace dom {
class BrowsingContext;
class WindowContext;
class ContentParent;
// A BrowsingContextGroup represents the Unit of Related Browsing Contexts in
......@@ -47,16 +48,10 @@ class BrowsingContextGroup final : public nsWrapperCache {
// Force the given ContentParent to subscribe to our BrowsingContextGroup.
void EnsureSubscribed(ContentParent* aProcess);
// Methods interacting with cached contexts.
bool IsContextCached(BrowsingContext* aContext) const;
void CacheContext(BrowsingContext* aContext);
void CacheContexts(const BrowsingContext::Children& aContexts);
bool EvictCachedContext(BrowsingContext* aContext);
// Get a reference to the list of toplevel contexts in this
// BrowsingContextGroup.
BrowsingContext::Children& Toplevels() { return mToplevels; }
void GetToplevels(BrowsingContext::Children& aToplevels) {
nsTArray<RefPtr<BrowsingContext>>& Toplevels() { return mToplevels; }
void GetToplevels(nsTArray<RefPtr<BrowsingContext>>& aToplevels) {
aToplevels.AppendElements(mToplevels);
}
......@@ -67,26 +62,10 @@ class BrowsingContextGroup final : public nsWrapperCache {
BrowsingContextGroup();
static already_AddRefed<BrowsingContextGroup> Select(
BrowsingContext* aParent, BrowsingContext* aOpener) {
if (aParent) {
return do_AddRef(aParent->Group());
}
if (aOpener) {
return do_AddRef(aOpener->Group());
}
return MakeAndAddRef<BrowsingContextGroup>();
}
WindowContext* aParent, BrowsingContext* aOpener);
static already_AddRefed<BrowsingContextGroup> Select(uint64_t aParentId,
uint64_t aOpenerId) {
RefPtr<BrowsingContext> parent = BrowsingContext::Get(aParentId);
MOZ_RELEASE_ASSERT(parent || aParentId == 0);
RefPtr<BrowsingContext> opener = BrowsingContext::Get(aOpenerId);
MOZ_RELEASE_ASSERT(opener || aOpenerId == 0);
return Select(parent, opener);
}
uint64_t aOpenerId);
// For each 'ContentParent', except for 'aExcludedParent',
// associated with this group call 'aCallback'.
......@@ -148,7 +127,7 @@ class BrowsingContextGroup final : public nsWrapperCache {
nsTHashtable<nsRefPtrHashKey<BrowsingContext>> mContexts;
// The set of toplevel browsing contexts in the current BrowsingContextGroup.
BrowsingContext::Children mToplevels;
nsTArray<RefPtr<BrowsingContext>> mToplevels;
// DocGroups are thread-safe, and not able to be cycle collected,
// but we still keep strong pointers. When all Documents are removed
......@@ -158,9 +137,6 @@ class BrowsingContextGroup final : public nsWrapperCache {
ContentParents mSubscribers;
// Map of cached contexts that need to stay alive due to bfcache.
nsTHashtable<nsRefPtrHashKey<BrowsingContext>> mCachedContexts;
// A queue to store postMessage events during page load, the queue will be
// flushed once the page is loaded
RefPtr<mozilla::ThrottledEventQueue> mPostMessageEventQueue;
......
......@@ -33,14 +33,14 @@ extern mozilla::LazyLogModule gUserInteractionPRLog;
#define USER_ACTIVATION_LOG(msg, ...) \
MOZ_LOG(gUserInteractionPRLog, LogLevel::Debug, (msg, ##__VA_ARGS__))
CanonicalBrowsingContext::CanonicalBrowsingContext(BrowsingContext* aParent,
CanonicalBrowsingContext::CanonicalBrowsingContext(WindowContext* aParentWindow,
BrowsingContextGroup* aGroup,
uint64_t aBrowsingContextId,
uint64_t aOwnerProcessId,
uint64_t aEmbedderProcessId,
BrowsingContext::Type aType,
FieldTuple&& aFields)
: BrowsingContext(aParent, aGroup, aBrowsingContextId, aType,
: BrowsingContext(aParentWindow, aGroup, aBrowsingContextId, aType,
std::move(aFields)),
mProcessId(aOwnerProcessId),
mEmbedderProcessId(aEmbedderProcessId) {
......
......@@ -134,7 +134,7 @@ class CanonicalBrowsingContext final : public BrowsingContext {
void CanonicalDiscard();
using Type = BrowsingContext::Type;
CanonicalBrowsingContext(BrowsingContext* aParent,
CanonicalBrowsingContext(WindowContext* aParentWindow,
BrowsingContextGroup* aGroup,
uint64_t aBrowsingContextId,
uint64_t aOwnerProcessId,
......
......@@ -45,10 +45,43 @@ WindowGlobalParent* WindowContext::Canonical() {
return static_cast<WindowGlobalParent*>(this);
}
bool WindowContext::IsCached() const {
return mBrowsingContext->mCurrentWindowContext != this;
}
nsIGlobalObject* WindowContext::GetParentObject() const {
return xpc::NativeGlobal(xpc::PrivilegedJunkScope());
}
void WindowContext::AppendChildBrowsingContext(
BrowsingContext* aBrowsingContext) {
MOZ_DIAGNOSTIC_ASSERT(Group() == aBrowsingContext->Group(),
"Mismatched groups?");
MOZ_DIAGNOSTIC_ASSERT(!mChildren.Contains(aBrowsingContext));
mChildren.AppendElement(aBrowsingContext);
// If we're the current WindowContext in our BrowsingContext, make sure to
// clear any cached `children` value.
if (!IsCached()) {
BrowsingContext_Binding::ClearCachedChildrenValue(mBrowsingContext);
}
}
void WindowContext::RemoveChildBrowsingContext(
BrowsingContext* aBrowsingContext) {
MOZ_DIAGNOSTIC_ASSERT(Group() == aBrowsingContext->Group(),
"Mismatched groups?");
mChildren.RemoveElement(aBrowsingContext);
// If we're the current WindowContext in our BrowsingContext, make sure to
// clear any cached `children` value.
if (!IsCached()) {
BrowsingContext_Binding::ClearCachedChildrenValue(mBrowsingContext);
}
}
void WindowContext::SendCommitTransaction(ContentParent* aParent,
const BaseTransaction& aTxn,
uint64_t aEpoch) {
......@@ -131,9 +164,9 @@ void WindowContext::Discard() {
return;
}
mBrowsingContext->UnregisterWindowContext(this);
gWindowContexts->Remove(InnerWindowId());
mIsDiscarded = true;
gWindowContexts->Remove(InnerWindowId());
mBrowsingContext->UnregisterWindowContext(this);
}
WindowContext::WindowContext(BrowsingContext* aBrowsingContext,
......@@ -172,11 +205,13 @@ NS_IMPL_CYCLE_COLLECTION_UNLINK_BEGIN(WindowContext)
}
NS_IMPL_CYCLE_COLLECTION_UNLINK(mBrowsingContext)
NS_IMPL_CYCLE_COLLECTION_UNLINK(mChildren)
NS_IMPL_CYCLE_COLLECTION_UNLINK_PRESERVED_WRAPPER
NS_IMPL_CYCLE_COLLECTION_UNLINK_END
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_BEGIN(WindowContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mBrowsingContext)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE(mChildren)
NS_IMPL_CYCLE_COLLECTION_TRAVERSE_END
NS_IMPL_CYCLE_COLLECTION_TRACE_WRAPPERCACHE(WindowContext)
......
......@@ -7,6 +7,7 @@
#ifndef mozilla_dom_WindowContext_h
#define mozilla_dom_WindowContext_h
#include "mozilla/Span.h"
#include "mozilla/dom/MaybeDiscarded.h"
#include "mozilla/dom/SyncedContext.h"
#include "mozilla/net/NeckoChannelParams.h"
......@@ -16,6 +17,8 @@ namespace dom {
class WindowGlobalParent;
class WindowGlobalParent;
#define MOZ_EACH_WC_FIELD(FIELD) \
FIELD(OuterWindowId, uint64_t) \
FIELD(CookieJarSettings, Maybe<mozilla::net::CookieJarSettingsArgs>) \
......@@ -44,6 +47,10 @@ class WindowContext : public nsISupports, public nsWrapperCache {
uint64_t OuterWindowId() const { return GetOuterWindowId(); }
bool IsDiscarded() const { return mIsDiscarded; }
bool IsCached() const;
Span<RefPtr<BrowsingContext>> Children() { return mChildren; }
// Cast this object to it's parent-process canonical form.
WindowGlobalParent* Canonical();
......@@ -58,6 +65,12 @@ class WindowContext : public nsISupports, public nsWrapperCache {
uint64_t mBrowsingContextId;
FieldTuple mFields;
bool operator==(const IPCInitializer& aOther) const {
return mInnerWindowId == aOther.mInnerWindowId &&
mBrowsingContextId == aOther.mBrowsingContextId &&
mFields == aOther.mFields;
}
};
IPCInitializer GetIPCInitializer() {
return {mInnerWindowId, mBrowsingContext->Id(), mFields.Fields()};
......@@ -74,6 +87,11 @@ class WindowContext : public nsISupports, public nsWrapperCache {
void Init();
private:
friend class BrowsingContext;
void AppendChildBrowsingContext(BrowsingContext* aBrowsingContext);
void RemoveChildBrowsingContext(BrowsingContext* aBrowsingContext);
// Send a given `BaseTransaction` object to the correct remote.
void SendCommitTransaction(ContentParent* aParent,
const BaseTransaction& aTxn, uint64_t aEpoch);
......@@ -114,6 +132,12 @@ class WindowContext : public nsISupports, public nsWrapperCache {
uint64_t mInnerWindowId;
RefPtr<BrowsingContext> mBrowsingContext;
// --- NEVER CHANGE `mChildren` DIRECTLY! ---
// Changes to this list need to be synchronized to the list within our
// `mBrowsingContext`, and should only be performed through the
// `AppendChildBrowsingContext` and `RemoveChildBrowsingContext` methods.
nsTArray<RefPtr<BrowsingContext>> mChildren;
bool mIsDiscarded = false;
};
......
......@@ -7161,12 +7161,6 @@ nsresult nsDocShell::RestoreFromHistory() {
// Order the mContentViewer setup just like Embed does.
mContentViewer = nullptr;
if (!mWillChangeProcess) {
// Move the browsing context's children to the cache. If we're
// detaching them, we'll detach them from there.
mBrowsingContext->CacheChildren();
}
// Now that we're about to switch documents, forget all of our children.
// Note that we cached them as needed up in CaptureState above.
DestroyChildren();
......@@ -7283,7 +7277,6 @@ nsresult nsDocShell::RestoreFromHistory() {
// <head> is parsed.
document->NotifyPossibleTitleChange(false);
BrowsingContext::Children contexts(childShells.Count());
// Now we simulate appending child docshells for subframes.
for (i = 0; i < childShells.Count(); ++i) {
nsIDocShellTreeItem* childItem = childShells.ObjectAt(i);
......@@ -7320,8 +7313,6 @@ nsresult nsDocShell::RestoreFromHistory() {
// child inherits our mPrivateBrowsingId, which is what we want.
AddChild(childItem);
contexts.AppendElement(childShell->GetBrowsingContext());
childShell->SetAllowJavascript(allowJavascript);
childShell->SetAllowMetaRedirects(allowRedirects);
childShell->SetAllowSubframes(allowSubframes);
......@@ -7337,10 +7328,6 @@ nsresult nsDocShell::RestoreFromHistory() {
NS_ENSURE_SUCCESS(rv, rv);
}
if (!contexts.IsEmpty()) {
mBrowsingContext->RestoreChildren(std::move(contexts));
}
// Make sure to restore the window state after adding the child shells back