зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1677474 - Part 2: Refine AdjustWindowFocus IPC flow; r=hsivonen
When there is two-level nested iframe, like, a.com contains an iframe b.com, and b.com contains an iframe c.com, when script in c.com calls window.focus() to get the focus, we need to adjust the activeElement in a.com and b.com. Currently, it needs to bounce IPC twice to make a.com get updated. This patch tries to make a.com could be updated sooner, so when parent process recive the adjustWindowFocus IPC from process of c.com, it will notify process of b.com and a.com at the same time. Differential Revision: https://phabricator.services.mozilla.com/D105659
This commit is contained in:
Родитель
87bdcc2a5c
Коммит
10cc0a11f4
|
@ -1896,24 +1896,14 @@ mozilla::dom::BrowsingContext* nsFocusManager::GetCommonAncestor(
|
|||
return parent;
|
||||
}
|
||||
|
||||
void nsFocusManager::AdjustWindowFocus(BrowsingContext* aBrowsingContext,
|
||||
bool aCheckPermission, bool aIsVisible) {
|
||||
bool nsFocusManager::AdjustInProcessWindowFocus(
|
||||
BrowsingContext* aBrowsingContext, bool aCheckPermission, bool aIsVisible) {
|
||||
BrowsingContext* bc = aBrowsingContext;
|
||||
bool needToNotifyOtherProcess = false;
|
||||
while (bc) {
|
||||
// get the containing <iframe> or equivalent element so that it can be
|
||||
// focused below.
|
||||
nsCOMPtr<Element> frameElement = bc->GetEmbedderElement();
|
||||
|
||||
if (!frameElement && XRE_IsContentProcess()) {
|
||||
// The containing <iframe> isn't in this process and we are in a child
|
||||
// process, so continue the walk in another process.
|
||||
mozilla::dom::ContentChild* contentChild =
|
||||
mozilla::dom::ContentChild::GetSingleton();
|
||||
MOZ_ASSERT(contentChild);
|
||||
contentChild->SendAdjustWindowFocus(bc, aIsVisible);
|
||||
return;
|
||||
}
|
||||
|
||||
BrowsingContext* parent = bc->GetParent();
|
||||
if (!parent && XRE_IsParentProcess()) {
|
||||
CanonicalBrowsingContext* canonical = bc->Canonical();
|
||||
|
@ -1925,15 +1915,20 @@ void nsFocusManager::AdjustWindowFocus(BrowsingContext* aBrowsingContext,
|
|||
}
|
||||
bc = parent;
|
||||
if (!bc) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
if (!frameElement && XRE_IsContentProcess()) {
|
||||
needToNotifyOtherProcess = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowOuter> window = bc->GetDOMWindow();
|
||||
MOZ_ASSERT(window);
|
||||
// if the parent window is visible but the original window was not, then we
|
||||
// have likely moved up and out from a hidden tab to the browser window, or
|
||||
// a similar such arrangement. Stop adjusting the current nodes.
|
||||
if (IsWindowVisible(window) != aIsVisible) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
// When aCheckPermission is true, we should check whether the caller can
|
||||
|
@ -1941,11 +1936,25 @@ void nsFocusManager::AdjustWindowFocus(BrowsingContext* aBrowsingContext,
|
|||
// adjusting.
|
||||
if (aCheckPermission && !nsContentUtils::LegacyIsCallerNativeCode() &&
|
||||
!nsContentUtils::CanCallerAccess(window->GetCurrentInnerWindow())) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
window->SetFocusedElement(frameElement);
|
||||
}
|
||||
return needToNotifyOtherProcess;
|
||||
}
|
||||
|
||||
void nsFocusManager::AdjustWindowFocus(BrowsingContext* aBrowsingContext,
|
||||
bool aCheckPermission, bool aIsVisible) {
|
||||
if (AdjustInProcessWindowFocus(aBrowsingContext, aCheckPermission,
|
||||
aIsVisible)) {
|
||||
// Some ancestors of aBrowsingContext isn't in this process, so notify other
|
||||
// processes to adjust their focused element.
|
||||
mozilla::dom::ContentChild* contentChild =
|
||||
mozilla::dom::ContentChild::GetSingleton();
|
||||
MOZ_ASSERT(contentChild);
|
||||
contentChild->SendAdjustWindowFocus(aBrowsingContext, aIsVisible);
|
||||
}
|
||||
}
|
||||
|
||||
bool nsFocusManager::IsWindowVisible(nsPIDOMWindowOuter* aWindow) {
|
||||
|
|
|
@ -363,6 +363,9 @@ class nsFocusManager final : public nsIFocusManager,
|
|||
* start at the active top-level window and navigate down the currently
|
||||
* focused elements for each frame in the tree to get to aBrowsingContext.
|
||||
*/
|
||||
bool AdjustInProcessWindowFocus(
|
||||
mozilla::dom::BrowsingContext* aBrowsingContext, bool aCheckPermission,
|
||||
bool aIsVisible);
|
||||
void AdjustWindowFocus(mozilla::dom::BrowsingContext* aBrowsingContext,
|
||||
bool aCheckPermission, bool aIsVisible);
|
||||
|
||||
|
|
|
@ -3794,7 +3794,7 @@ mozilla::ipc::IPCResult ContentChild::RecvAdjustWindowFocus(
|
|||
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (fm) {
|
||||
fm->AdjustWindowFocus(aContext.get(), false, aIsVisible);
|
||||
fm->AdjustInProcessWindowFocus(aContext.get(), false, aIsVisible);
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
|
|
@ -6866,18 +6866,26 @@ mozilla::ipc::IPCResult ContentParent::RecvAdjustWindowFocus(
|
|||
("ParentIPC: Trying to send a message to dead or detached context"));
|
||||
return IPC_OK();
|
||||
}
|
||||
CanonicalBrowsingContext* context = aContext.get_canonical();
|
||||
BrowsingContext* parent = context->GetParent();
|
||||
if (!parent) {
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
CanonicalBrowsingContext* canonicalParent = parent->Canonical();
|
||||
nsDataHashtable<nsPtrHashKey<ContentParent>, bool> processes(2);
|
||||
processes.InsertOrUpdate(this, true);
|
||||
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
ContentParent* cp = cpm->GetContentProcessById(
|
||||
ContentParentId(canonicalParent->OwnerProcessId()));
|
||||
Unused << cp->SendAdjustWindowFocus(context, aIsVisible);
|
||||
CanonicalBrowsingContext* context = aContext.get_canonical();
|
||||
while (context) {
|
||||
BrowsingContext* parent = context->GetParent();
|
||||
if (!parent) {
|
||||
break;
|
||||
}
|
||||
|
||||
CanonicalBrowsingContext* canonicalParent = parent->Canonical();
|
||||
ContentParent* cp = cpm->GetContentProcessById(
|
||||
ContentParentId(canonicalParent->OwnerProcessId()));
|
||||
if (!processes.Get(cp)) {
|
||||
Unused << cp->SendAdjustWindowFocus(context, aIsVisible);
|
||||
processes.InsertOrUpdate(cp, true);
|
||||
}
|
||||
context = canonicalParent;
|
||||
}
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
|
Загрузка…
Ссылка в новой задаче