Bug 1721306, hide the tooltip when deactivating a BrowserParent, r=peterv
authorOlli Pettay <Olli.Pettay@helsinki.fi>
Fri, 06 Aug 2021 19:33:04 +0000
changeset 588113 2cb9f52db17eabf59f8ca7d5e6aa261558473319
parent 588112 3c5a838521b1cf4616e3ea9f1b5b3ea8769e73dd
child 588114 e22e7584fbabfd0aeebc3c3468d62c6358355661
push id38682
push usersmolnar@mozilla.com
push dateSat, 07 Aug 2021 09:26:14 +0000
treeherdermozilla-central@7338d7d94091 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerspeterv
bugs1721306
milestone92.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 1721306, hide the tooltip when deactivating a BrowserParent, r=peterv Differential Revision: https://phabricator.services.mozilla.com/D121756
docshell/shistory/SessionHistoryEntry.cpp
dom/ipc/BrowserParent.cpp
dom/ipc/BrowserParent.h
dom/ipc/tests/browser.ini
dom/ipc/tests/browser_hide_tooltip.js
--- a/docshell/shistory/SessionHistoryEntry.cpp
+++ b/docshell/shistory/SessionHistoryEntry.cpp
@@ -14,16 +14,17 @@
 #include "nsSHEntryShared.h"
 #include "nsSHistory.h"
 #include "nsStructuredCloneContainer.h"
 #include "nsXULAppAPI.h"
 #include "mozilla/PresState.h"
 #include "mozilla/StaticPrefs_fission.h"
 #include "mozilla/Tuple.h"
 #include "mozilla/dom/BrowserParent.h"
+#include "mozilla/dom/CanonicalBrowsingContext.h"
 #include "mozilla/dom/ContentChild.h"
 #include "mozilla/dom/ContentParent.h"
 #include "mozilla/dom/CSPMessageUtils.h"
 #include "mozilla/dom/DOMTypes.h"
 #include "mozilla/dom/nsCSPContext.h"
 #include "mozilla/dom/PermissionMessageUtils.h"
 #include "mozilla/dom/ReferrerInfoUtils.h"
 #include "mozilla/ipc/IPDLParamTraits.h"
@@ -1371,18 +1372,22 @@ SHEntrySharedParentState* SessionHistory
 }
 
 void SessionHistoryEntry::SetFrameLoader(nsFrameLoader* aFrameLoader) {
   MOZ_DIAGNOSTIC_ASSERT(!aFrameLoader || !SharedInfo()->mFrameLoader);
   // If the pref is disabled, we still allow evicting the existing entries.
   MOZ_RELEASE_ASSERT(!aFrameLoader || mozilla::BFCacheInParent());
   SharedInfo()->SetFrameLoader(aFrameLoader);
   if (aFrameLoader) {
-    if (BrowserParent* bp = aFrameLoader->GetBrowserParent()) {
-      bp->Deactivated();
+    if (BrowsingContext* bc = aFrameLoader->GetMaybePendingBrowsingContext()) {
+      bc->PreOrderWalk([&](BrowsingContext* aContext) {
+        if (BrowserParent* bp = aContext->Canonical()->GetBrowserParent()) {
+          bp->Deactivated();
+        }
+      });
     }
 
     // When a new frameloader is stored, try to evict some older
     // frameloaders. Non-SHIP session history has a similar call in
     // nsDocumentViewer::Show.
     nsCOMPtr<nsISHistory> shistory;
     GetShistory(getter_AddRefs(shistory));
     if (shistory) {
--- a/dom/ipc/BrowserParent.cpp
+++ b/dom/ipc/BrowserParent.cpp
@@ -230,17 +230,18 @@ BrowserParent::BrowserParent(ContentPare
       mIsDestroyed(false),
       mRemoteTargetSetsCursor(false),
       mIsPreservingLayers(false),
       mRenderLayers(true),
       mHasLayers(false),
       mHasPresented(false),
       mIsReadyToHandleInputEvents(false),
       mIsMouseEnterIntoWidgetEventSuppressed(false),
-      mLockedNativePointer(false) {
+      mLockedNativePointer(false),
+      mShowingTooltip(false) {
   MOZ_ASSERT(aManager);
   // When the input event queue is disabled, we don't need to handle the case
   // that some input events are dispatched before PBrowserConstructor.
   mIsReadyToHandleInputEvents = !ContentParent::IsInputEventQueueSupported();
 
   // If we're in a BC tree that is active with respect to the priority manager,
   // ensure that this new BrowserParent is marked as active. This ensures that
   // the process will be prioritized in a cross-site iframe navigation in an
@@ -592,16 +593,20 @@ void BrowserParent::RemoveWindowListener
     if (eventTarget) {
       eventTarget->RemoveEventListener(u"MozUpdateWindowPos"_ns, this, false);
       eventTarget->RemoveEventListener(u"fullscreenchange"_ns, this, false);
     }
   }
 }
 
 void BrowserParent::Deactivated() {
+  if (mShowingTooltip) {
+    // Reuse the normal tooltip hiding method.
+    mozilla::Unused << RecvHideTooltip();
+  }
   UnlockNativePointer();
   UnsetTopLevelWebFocus(this);
   UnsetLastMouseRemoteTarget(this);
   PointerLockManager::ReleaseLockedRemoteTarget(this);
   PointerEventHandler::ReleasePointerCaptureRemoteTarget(this);
   PresShell::ReleaseCapturingRemoteTarget(this);
   ProcessPriorityManager::ActivityChanged(this, /* aIsActive = */ false);
 }
@@ -2291,21 +2296,26 @@ mozilla::ipc::IPCResult BrowserParent::R
   // nsFrameLoaderOwner, which implies we're a XULFrameElement. We can then
   // safely pass Element into JS.
   RefPtr<nsFrameLoaderOwner> flo = do_QueryObject(mFrameElement);
   if (!flo) return IPC_OK();
 
   nsCOMPtr<Element> el = do_QueryInterface(flo);
   if (!el) return IPC_OK();
 
-  xulBrowserWindow->ShowTooltip(aX, aY, aTooltip, aDirection, el);
+  if (NS_SUCCEEDED(
+          xulBrowserWindow->ShowTooltip(aX, aY, aTooltip, aDirection, el))) {
+    mShowingTooltip = true;
+  }
   return IPC_OK();
 }
 
 mozilla::ipc::IPCResult BrowserParent::RecvHideTooltip() {
+  mShowingTooltip = false;
+
   nsCOMPtr<nsIXULBrowserWindow> xulBrowserWindow = GetXULBrowserWindow();
   if (!xulBrowserWindow) {
     return IPC_OK();
   }
 
   xulBrowserWindow->HideTooltip();
   return IPC_OK();
 }
--- a/dom/ipc/BrowserParent.h
+++ b/dom/ipc/BrowserParent.h
@@ -968,16 +968,19 @@ class BrowserParent final : public PBrow
   // True if we suppress the eMouseEnterIntoWidget event due to the
   // BrowserChild was not ready to handle it. We will resend it when the next
   // time we fire a mouse event and the BrowserChild is ready.
   bool mIsMouseEnterIntoWidgetEventSuppressed : 1;
 
   // True after RecvLockNativePointer has been called and until
   // UnlockNativePointer has been called.
   bool mLockedNativePointer : 1;
+
+  // True between ShowTooltip and HideTooltip messages.
+  bool mShowingTooltip : 1;
 };
 
 struct MOZ_STACK_CLASS BrowserParent::AutoUseNewTab final {
  public:
   explicit AutoUseNewTab(BrowserParent* aNewTab) : mNewTab(aNewTab) {
     MOZ_ASSERT(!aNewTab->mCreatingWindow);
     aNewTab->mCreatingWindow = true;
   }
--- a/dom/ipc/tests/browser.ini
+++ b/dom/ipc/tests/browser.ini
@@ -15,16 +15,17 @@ support-files =
   ../../tests/browser/file_coop_coep.html
   ../../tests/browser/file_coop_coep.html^headers^
 [browser_crash_oopiframe.js]
 skip-if =
   !fission
   !crashreporter
   verify
 [browser_domainPolicy.js]
+[browser_hide_tooltip.js]
 [browser_memory_distribution_telemetry.js]
 skip-if = true
   !e10s # This is an e10s only probe, but the test is currently broken. See Bug 1449991
 [browser_cancel_content_js.js]
 skip-if = !e10s
 [browser_bug1646088.js]
 support-files = file_dummy.html
 skip-if = !e10s
new file mode 100644
--- /dev/null
+++ b/dom/ipc/tests/browser_hide_tooltip.js
@@ -0,0 +1,38 @@
+/* Any copyright is dedicated to the Public Domain.
+   http://creativecommons.org/publicdomain/zero/1.0/ */
+
+"use strict";
+
+add_task(async function test_hiding_tooltip() {
+  let page1 = "data:text/html,<html title='title'><body>page 1<body></html>";
+  let page2 = "data:text/html,<html><body>page 2</body></html>";
+
+  let tab = await BrowserTestUtils.openNewForegroundTab({
+    gBrowser,
+    opening: page1,
+  });
+
+  let popup = new Promise(function(resolve) {
+    window.addEventListener("popupshown", resolve, { once: true });
+  });
+  // Fire a mousemove to trigger the tooltip.
+  EventUtils.synthesizeMouseAtCenter(gBrowser.selectedBrowser, {
+    type: "mousemove",
+  });
+  await popup;
+
+  let hiding = new Promise(function(resolve) {
+    window.addEventListener("popuphiding", resolve, { once: true });
+  });
+  let loaded = BrowserTestUtils.browserLoaded(
+    gBrowser.selectedBrowser,
+    false,
+    page2
+  );
+  BrowserTestUtils.loadURI(gBrowser, page2);
+  await loaded;
+  await hiding;
+
+  ok(true, "Should have hidden the tooltip");
+  BrowserTestUtils.removeTab(tab);
+});