Bug 1550637 - hide tooltip when the docshell navigate, don't show tooltips if the docshell is no longer active, r=nika,dao

Differential Revision: https://phabricator.services.mozilla.com/D35503

--HG--
extra : moz-landing-system : lando
This commit is contained in:
Gijs Kruitbosch 2019-07-16 07:48:23 +00:00
parent fc05893051
commit 5ae6f00741
4 changed files with 49 additions and 23 deletions

View File

@ -5557,26 +5557,6 @@ var XULBrowserWindow = {
onLocationChange(aWebProgress, aRequest, aLocationURI, aFlags, aIsSimulated) {
var location = aLocationURI ? aLocationURI.spec : "";
let pageTooltip = document.getElementById("aHTMLTooltip");
let tooltipNode = pageTooltip.triggerNode;
if (tooltipNode) {
// Optimise for the common case
if (aWebProgress.isTopLevel) {
pageTooltip.hidePopup();
} else {
for (
let tooltipWindow = tooltipNode.ownerGlobal;
tooltipWindow != tooltipWindow.parent;
tooltipWindow = tooltipWindow.parent
) {
if (tooltipWindow == aWebProgress.DOMWindow) {
pageTooltip.hidePopup();
break;
}
}
}
}
this.hideOverLinkImmediately = true;
this.setOverLink("", null);
this.hideOverLinkImmediately = false;
@ -5800,6 +5780,13 @@ var XULBrowserWindow = {
CombinedStopReload.onTabSwitch();
// Docshell should normally take care of hiding the tooltip, but we need to do it
// ourselves for tabswitches.
this.hideTooltip();
// Also hide tooltips for content loaded in the parent process:
document.getElementById("aHTMLTooltip").hidePopup();
var nsIWebProgressListener = Ci.nsIWebProgressListener;
var loadingDone = aStateFlags & nsIWebProgressListener.STATE_STOP;
// use a pseudo-object instead of a (potentially nonexistent) channel for getting

View File

@ -683,6 +683,11 @@ NS_IMETHODIMP
nsDocShellTreeOwner::OnLocationChange(nsIWebProgress* aWebProgress,
nsIRequest* aRequest, nsIURI* aURI,
uint32_t aFlags) {
if (mChromeTooltipListener && aWebProgress &&
!(aFlags & nsIWebProgressListener::LOCATION_CHANGE_SAME_DOCUMENT) &&
mChromeTooltipListener->WebProgressShowedTooltip(aWebProgress)) {
mChromeTooltipListener->HideTooltip();
}
return NS_OK;
}
@ -1186,6 +1191,7 @@ ChromeTooltipListener::HideTooltip() {
mTooltipTimer = nullptr;
// release tooltip target
mPossibleTooltipNode = nullptr;
mLastDocshell = nullptr;
}
// if we're showing the tip, tell the chrome to hide it
@ -1203,6 +1209,30 @@ ChromeTooltipListener::HideTooltip() {
return rv;
}
bool ChromeTooltipListener::WebProgressShowedTooltip(
nsIWebProgress* aWebProgress) {
nsCOMPtr<nsIDocShell> docshell = do_QueryInterface(aWebProgress);
nsCOMPtr<nsIDocShell> lastUsed = do_QueryReferent(mLastDocshell);
while (lastUsed) {
if (lastUsed == docshell) {
return true;
}
// We can't use the docshell hierarchy here, because when the parent
// docshell is navigated, the child docshell is disconnected (ie its
// references to the parent are nulled out) despite it still being
// alive here. So we use the document hierarchy instead:
Document* document = lastUsed->GetDocument();
if (document) {
document = document->GetParentDocument();
}
if (!document) {
break;
}
lastUsed = document->GetDocShell();
}
return false;
}
// A timer callback, fired when the mouse has hovered inside of a frame for the
// appropriate amount of time. Getting to this point means that we should show
// the tooltip, but only after we determine there is an appropriate TITLE
@ -1244,7 +1274,7 @@ void ChromeTooltipListener::sTooltipCallback(nsITimer* aTimer,
}
}
if (!widget) {
if (!widget || !docShell || !docShell->GetIsActive()) {
// release tooltip target if there is one, NO MATTER WHAT
self->mPossibleTooltipNode = nullptr;
return;
@ -1275,6 +1305,10 @@ void ChromeTooltipListener::sTooltipCallback(nsITimer* aTimer,
self->mMouseScreenY - screenDot.y / scaleFactor,
tooltipText, directionText);
self->mLastShownTooltipText = std::move(tooltipText);
if (self->mPossibleTooltipNode->OwnerDoc()) {
self->mLastDocshell = do_GetWeakReference(
self->mPossibleTooltipNode->OwnerDoc()->GetDocShell());
}
}
}

View File

@ -131,6 +131,10 @@ class ChromeTooltipListener final : public nsIDOMEventListener {
NS_IMETHOD AddChromeListeners();
NS_IMETHOD RemoveChromeListeners();
NS_IMETHOD HideTooltip();
bool WebProgressShowedTooltip(nsIWebProgress* aWebProgress);
private:
// various delays for tooltips
enum {
@ -144,7 +148,6 @@ class ChromeTooltipListener final : public nsIDOMEventListener {
NS_IMETHOD ShowTooltip(int32_t aInXCoords, int32_t aInYCoords,
const nsAString& aInTipText,
const nsAString& aDirText);
NS_IMETHOD HideTooltip();
nsITooltipTextProvider* GetTooltipTextProvider();
nsWebBrowser* mWebBrowser;
@ -177,6 +180,8 @@ class ChromeTooltipListener final : public nsIDOMEventListener {
// The string of text that we last displayed.
nsString mLastShownTooltipText;
nsWeakPtr mLastDocshell;
// The node hovered over that fired the timer. This may turn into the node
// that triggered the tooltip, but only if the timer ever gets around to
// firing. This is a strong reference, because the tooltip content can be

View File

@ -589,7 +589,7 @@ interface nsIDocShell : nsIDocShellTreeItem
* visible, and thus is not a good candidate for certain optimizations
* like image frame discarding. Docshells are active unless told otherwise.
*/
attribute boolean isActive;
[infallible] attribute boolean isActive;
/**
* The ID of the docshell in the session history.