Bug 1646567 - fix nsDocShell::HasUnloadedParent to work for OOP frames. r?nika draft
authorSteven MacLeod <steven@smacleod.ca>
Wed, 29 Jul 2020 15:56:52 -0400
changeset 3099953 d652efa5fd2ca09436238f1b8ce0107ab61c5c03
parent 3096819 e130c4bccd3d8308ab25108c9d3707d8155f3425
child 3099954 4c92e449c05c00f6c59c6e1b26fb32df79333af0
push id577695
push usersmacleod@mozilla.com
push dateFri, 31 Jul 2020 19:56:28 +0000
treeherdertry@4c92e449c05c [default view] [failures only]
reviewersnika
bugs1646567
milestone81.0a1
Bug 1646567 - fix nsDocShell::HasUnloadedParent to work for OOP frames. r?nika With fission enabled, walking the docshell tree to find unloaded parents would stop at the first OOP parent. Instead we now walk the `BrowsingContext`/`WindowContext` tree. To still check parents which are OOP, we take advantage of the fact that a parent `WindowContext` will no longer be the current `WindowContext` if the parent was unloaded. For in process docshell's we additionally check the docshell directly. Differential Revision: https://phabricator.services.mozilla.com/D85328
docshell/base/nsDocShell.cpp
docshell/base/nsIDocShell.idl
--- a/docshell/base/nsDocShell.cpp
+++ b/docshell/base/nsDocShell.cpp
@@ -12489,24 +12489,30 @@ nsDocShell::GetAsyncPanZoomEnabled(bool*
 
   // If we don't have a presShell, fall back to the default platform value of
   // whether or not APZ is enabled.
   *aOut = gfxPlatform::AsyncPanZoomEnabled();
   return NS_OK;
 }
 
 bool nsDocShell::HasUnloadedParent() {
-  RefPtr<nsDocShell> parent = GetInProcessParentDocshell();
-  while (parent) {
-    bool inUnload = false;
-    parent->GetIsInUnload(&inUnload);
-    if (inUnload) {
+  for (WindowContext* wc = GetBrowsingContext()->GetParentWindowContext(); wc;
+       wc = wc->GetParentWindowContext()) {
+    if (wc->IsCached() || wc->IsDiscarded() ||
+        wc->GetBrowsingContext()->IsDiscarded()) {
+      // If a parent is OOP and the parent WindowContext is no
+      // longer current, we can assume the parent was unloaded.
       return true;
     }
-    parent = parent->GetInProcessParentDocshell();
+
+    if (wc->GetBrowsingContext()->IsInProcess() &&
+        (!wc->GetBrowsingContext()->GetDocShell() ||
+         wc->GetBrowsingContext()->GetDocShell()->GetIsInUnload())) {
+      return true;
+    }
   }
   return false;
 }
 
 /* static */
 bool nsDocShell::ShouldUpdateGlobalHistory(uint32_t aLoadType) {
   return !(aLoadType == LOAD_BYPASS_HISTORY || aLoadType == LOAD_ERROR_PAGE ||
            aLoadType & LOAD_CMD_HISTORY);
--- a/docshell/base/nsIDocShell.idl
+++ b/docshell/base/nsIDocShell.idl
@@ -455,17 +455,17 @@ interface nsIDocShell : nsIDocShellTreeI
    * dynamically added docShells.
    */
   [notxpcom,nostdcall] attribute long childOffset;
 
   /**
    * Find out whether the docshell is currently in the middle of a page
    * transition. This is set just before the pagehide/unload events fire.
    */
-  readonly attribute boolean isInUnload;
+  [infallible] readonly attribute boolean isInUnload;
 
   /**
    * Disconnects this docshell's editor from its window, and stores the
    * editor data in the open document's session history entry.  This
    * should be called only during page transitions.
    */
   [noscript, notxpcom] void DetachEditorFromWindow();