mirror of
https://github.com/mozilla/gecko-dev.git
synced 2025-01-09 21:33:43 +00:00
Bug 1659383
- Check if focus() is allowed even when Window_Binding::focus() delegates to BrowsingContext::Focus(). r=nika
Differential Revision: https://phabricator.services.mozilla.com/D100005
This commit is contained in:
parent
652e43b038
commit
0e936b95f1
@ -1957,15 +1957,148 @@ void BrowsingContext::Close(CallerType aCallerType, ErrorResult& aError) {
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Examine the current document state to see if we're in a way that is
|
||||
* typically abused by web designers. The window.open code uses this
|
||||
* routine to determine whether to allow the new window.
|
||||
* Returns a value from the PopupControlState enum.
|
||||
*/
|
||||
PopupBlocker::PopupControlState BrowsingContext::RevisePopupAbuseLevel(
|
||||
PopupBlocker::PopupControlState aControl) {
|
||||
if (!IsContent()) {
|
||||
return PopupBlocker::openAllowed;
|
||||
}
|
||||
|
||||
PopupBlocker::PopupControlState abuse = aControl;
|
||||
switch (abuse) {
|
||||
case PopupBlocker::openControlled:
|
||||
case PopupBlocker::openBlocked:
|
||||
case PopupBlocker::openOverridden:
|
||||
if (IsPopupAllowed()) {
|
||||
abuse = PopupBlocker::PopupControlState(abuse - 1);
|
||||
}
|
||||
break;
|
||||
case PopupBlocker::openAbused:
|
||||
if (IsPopupAllowed()) {
|
||||
// Skip PopupBlocker::openBlocked
|
||||
abuse = PopupBlocker::openControlled;
|
||||
}
|
||||
break;
|
||||
case PopupBlocker::openAllowed:
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Strange PopupControlState!");
|
||||
}
|
||||
|
||||
// limit the number of simultaneously open popups
|
||||
if (abuse == PopupBlocker::openAbused || abuse == PopupBlocker::openBlocked ||
|
||||
abuse == PopupBlocker::openControlled) {
|
||||
int32_t popupMax = StaticPrefs::dom_popup_maximum();
|
||||
if (popupMax >= 0 &&
|
||||
PopupBlocker::GetOpenPopupSpamCount() >= (uint32_t)popupMax) {
|
||||
abuse = PopupBlocker::openOverridden;
|
||||
}
|
||||
}
|
||||
|
||||
// If we're currently in-process, attempt to consume transient user gesture
|
||||
// activations.
|
||||
if (RefPtr<Document> doc = GetExtantDocument()) {
|
||||
// HACK: Some pages using bogus library + UA sniffing call window.open()
|
||||
// from a blank iframe, only on Firefox, see bug 1685056.
|
||||
//
|
||||
// This is a hack-around to preserve behavior in that particular and
|
||||
// specific case, by consuming activation on the parent document, so we
|
||||
// don't care about the InProcessParent bits not being fission-safe or what
|
||||
// not.
|
||||
auto ConsumeTransientUserActivationForMultiplePopupBlocking =
|
||||
[&]() -> bool {
|
||||
if (doc->ConsumeTransientUserGestureActivation()) {
|
||||
return true;
|
||||
}
|
||||
if (!doc->IsInitialDocument()) {
|
||||
return false;
|
||||
}
|
||||
Document* parentDoc = doc->GetInProcessParentDocument();
|
||||
if (!parentDoc ||
|
||||
!parentDoc->NodePrincipal()->Equals(doc->NodePrincipal())) {
|
||||
return false;
|
||||
}
|
||||
return parentDoc->ConsumeTransientUserGestureActivation();
|
||||
};
|
||||
|
||||
// If this popup is allowed, let's block any other for this event, forcing
|
||||
// PopupBlocker::openBlocked state.
|
||||
if ((abuse == PopupBlocker::openAllowed ||
|
||||
abuse == PopupBlocker::openControlled) &&
|
||||
StaticPrefs::dom_block_multiple_popups() && !IsPopupAllowed() &&
|
||||
!ConsumeTransientUserActivationForMultiplePopupBlocking()) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns,
|
||||
doc, nsContentUtils::eDOM_PROPERTIES,
|
||||
"MultiplePopupsBlockedNoUserActivation");
|
||||
abuse = PopupBlocker::openBlocked;
|
||||
}
|
||||
}
|
||||
|
||||
return abuse;
|
||||
}
|
||||
|
||||
std::tuple<bool, bool> BrowsingContext::CanFocusCheck(CallerType aCallerType) {
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (!fm) {
|
||||
return {false, false};
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> caller = do_QueryInterface(GetEntryGlobal());
|
||||
BrowsingContext* callerBC = caller ? caller->GetBrowsingContext() : nullptr;
|
||||
RefPtr<BrowsingContext> openerBC = GetOpener();
|
||||
MOZ_DIAGNOSTIC_ASSERT(!openerBC || openerBC->Group() == Group());
|
||||
|
||||
// Enforce dom.disable_window_flip (for non-chrome), but still allow the
|
||||
// window which opened us to raise us at times when popups are allowed
|
||||
// (bugs 355482 and 369306).
|
||||
bool canFocus = aCallerType == CallerType::System ||
|
||||
!Preferences::GetBool("dom.disable_window_flip", true);
|
||||
if (!canFocus && openerBC == callerBC) {
|
||||
canFocus = (RevisePopupAbuseLevel(PopupBlocker::GetPopupControlState()) <
|
||||
PopupBlocker::openBlocked);
|
||||
}
|
||||
|
||||
bool isActive = false;
|
||||
if (XRE_IsParentProcess()) {
|
||||
RefPtr<CanonicalBrowsingContext> chromeTop =
|
||||
Canonical()->TopCrossChromeBoundary();
|
||||
nsCOMPtr<nsPIDOMWindowOuter> activeWindow = fm->GetActiveWindow();
|
||||
isActive = (activeWindow == chromeTop->GetDOMWindow());
|
||||
} else {
|
||||
isActive = (fm->GetActiveBrowsingContext() == Top());
|
||||
}
|
||||
|
||||
return {canFocus, isActive};
|
||||
}
|
||||
|
||||
void BrowsingContext::Focus(CallerType aCallerType, ErrorResult& aError) {
|
||||
// These checks need to happen before the RequestFrameFocus call, which
|
||||
// is why they are done in an untrusted process. If we wanted to enforce
|
||||
// these in the parent, we'd need to do the checks there _also_.
|
||||
// These should be kept in sync with nsGlobalWindowOuter::FocusOuter.
|
||||
|
||||
auto [canFocus, isActive] = CanFocusCheck(aCallerType);
|
||||
|
||||
if (!(canFocus || isActive)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Permission check passed
|
||||
|
||||
if (mEmbedderElement) {
|
||||
// Make the activeElement in this process update synchronously.
|
||||
nsContentUtils::RequestFrameFocus(*mEmbedderElement, true, aCallerType);
|
||||
}
|
||||
uint64_t actionId = nsFocusManager::GenerateFocusActionId();
|
||||
if (ContentChild* cc = ContentChild::GetSingleton()) {
|
||||
cc->SendWindowFocus(this, aCallerType);
|
||||
cc->SendWindowFocus(this, aCallerType, actionId);
|
||||
} else if (ContentParent* cp = Canonical()->GetContentParent()) {
|
||||
Unused << cp->SendWindowFocus(this, aCallerType);
|
||||
Unused << cp->SendWindowFocus(this, aCallerType, actionId);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
#ifndef mozilla_dom_BrowsingContext_h
|
||||
#define mozilla_dom_BrowsingContext_h
|
||||
|
||||
#include <tuple>
|
||||
#include "GVAutoplayRequestUtils.h"
|
||||
#include "mozilla/ErrorResult.h"
|
||||
#include "mozilla/HalScreenConfiguration.h"
|
||||
@ -18,6 +19,7 @@
|
||||
#include "mozilla/dom/BindingDeclarations.h"
|
||||
#include "mozilla/dom/LocationBase.h"
|
||||
#include "mozilla/dom/MaybeDiscarded.h"
|
||||
#include "mozilla/dom/PopupBlocker.h"
|
||||
#include "mozilla/dom/UserActivation.h"
|
||||
#include "mozilla/dom/BrowsingContextBinding.h"
|
||||
#include "mozilla/dom/ScreenOrientationBinding.h"
|
||||
@ -776,6 +778,12 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
|
||||
|
||||
mozilla::dom::DisplayMode DisplayMode() { return Top()->GetDisplayMode(); }
|
||||
|
||||
// Returns canFocus, isActive
|
||||
std::tuple<bool, bool> CanFocusCheck(CallerType aCallerType);
|
||||
|
||||
PopupBlocker::PopupControlState RevisePopupAbuseLevel(
|
||||
PopupBlocker::PopupControlState aControl);
|
||||
|
||||
protected:
|
||||
virtual ~BrowsingContext();
|
||||
BrowsingContext(WindowContext* aParentWindow, BrowsingContextGroup* aGroup,
|
||||
|
@ -3723,7 +3723,9 @@ void nsGlobalWindowInner::Prompt(const nsAString& aMessage,
|
||||
}
|
||||
|
||||
void nsGlobalWindowInner::Focus(CallerType aCallerType, ErrorResult& aError) {
|
||||
FORWARD_TO_OUTER_OR_THROW(FocusOuter, (aCallerType), aError, );
|
||||
FORWARD_TO_OUTER_OR_THROW(
|
||||
FocusOuter, (aCallerType, nsFocusManager::GenerateFocusActionId()),
|
||||
aError, );
|
||||
}
|
||||
|
||||
nsresult nsGlobalWindowInner::Focus(CallerType aCallerType) {
|
||||
|
@ -5053,47 +5053,14 @@ void nsGlobalWindowOuter::PromptOuter(const nsAString& aMessage,
|
||||
}
|
||||
}
|
||||
|
||||
void nsGlobalWindowOuter::FocusOuter(CallerType aCallerType) {
|
||||
void nsGlobalWindowOuter::FocusOuter(CallerType aCallerType,
|
||||
uint64_t aActionId) {
|
||||
nsFocusManager* fm = nsFocusManager::GetFocusManager();
|
||||
if (!fm) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> baseWin = do_QueryInterface(mDocShell);
|
||||
if (!baseWin) {
|
||||
return;
|
||||
}
|
||||
|
||||
nsCOMPtr<nsPIDOMWindowInner> caller = do_QueryInterface(GetEntryGlobal());
|
||||
nsPIDOMWindowOuter* callerOuter = caller ? caller->GetOuterWindow() : nullptr;
|
||||
BrowsingContext* callerBC =
|
||||
callerOuter ? callerOuter->GetBrowsingContext() : nullptr;
|
||||
RefPtr<BrowsingContext> openerBC = GetOpenerBrowsingContext();
|
||||
|
||||
// Enforce dom.disable_window_flip (for non-chrome), but still allow the
|
||||
// window which opened us to raise us at times when popups are allowed
|
||||
// (bugs 355482 and 369306).
|
||||
bool canFocus = CanSetProperty("dom.disable_window_flip") ||
|
||||
(openerBC == callerBC &&
|
||||
RevisePopupAbuseLevel(PopupBlocker::GetPopupControlState()) <
|
||||
PopupBlocker::openBlocked);
|
||||
|
||||
bool isActive = false;
|
||||
if (XRE_IsParentProcess()) {
|
||||
nsCOMPtr<nsPIDOMWindowOuter> activeWindow = fm->GetActiveWindow();
|
||||
|
||||
nsCOMPtr<nsIDocShellTreeItem> rootItem;
|
||||
mDocShell->GetInProcessRootTreeItem(getter_AddRefs(rootItem));
|
||||
nsCOMPtr<nsPIDOMWindowOuter> rootWin =
|
||||
rootItem ? rootItem->GetWindow() : nullptr;
|
||||
isActive = (rootWin == activeWindow);
|
||||
} else {
|
||||
BrowsingContext* activeBrowsingContext = fm->GetActiveBrowsingContext();
|
||||
BrowsingContext* bc = GetBrowsingContext();
|
||||
if (bc) {
|
||||
isActive = (activeBrowsingContext == bc->Top());
|
||||
}
|
||||
}
|
||||
auto [canFocus, isActive] = GetBrowsingContext()->CanFocusCheck(aCallerType);
|
||||
|
||||
nsCOMPtr<nsIBaseWindow> treeOwnerAsWin = GetTreeOwnerWindow();
|
||||
if (treeOwnerAsWin && (canFocus || isActive)) {
|
||||
@ -5124,11 +5091,10 @@ void nsGlobalWindowOuter::FocusOuter(CallerType aCallerType) {
|
||||
parent = bc->Canonical()->GetParentCrossChromeBoundary();
|
||||
}
|
||||
}
|
||||
uint64_t actionId = nsFocusManager::GenerateFocusActionId();
|
||||
if (parent) {
|
||||
if (!parent->IsInProcess()) {
|
||||
if (isActive) {
|
||||
fm->WindowRaised(this, actionId);
|
||||
fm->WindowRaised(this, aActionId);
|
||||
// XXX we still need to notify framer about the focus moves to OOP
|
||||
// iframe to generate corresponding blur event for bug 1677474.
|
||||
} else {
|
||||
@ -5153,7 +5119,7 @@ void nsGlobalWindowOuter::FocusOuter(CallerType aCallerType) {
|
||||
// if there is no parent, this must be a toplevel window, so raise the
|
||||
// window if canFocus is true. If this is a child process, the raise
|
||||
// window request will get forwarded to the parent by the puppet widget.
|
||||
fm->RaiseWindow(this, aCallerType, actionId);
|
||||
fm->RaiseWindow(this, aCallerType, aActionId);
|
||||
}
|
||||
}
|
||||
|
||||
@ -5700,91 +5666,6 @@ bool nsGlobalWindowOuter::CanSetProperty(const char* aPrefName) {
|
||||
return !Preferences::GetBool(aPrefName, true);
|
||||
}
|
||||
|
||||
bool nsGlobalWindowOuter::IsPopupAllowed() {
|
||||
return mBrowsingContext->IsPopupAllowed();
|
||||
}
|
||||
|
||||
/*
|
||||
* Examine the current document state to see if we're in a way that is
|
||||
* typically abused by web designers. The window.open code uses this
|
||||
* routine to determine whether to allow the new window.
|
||||
* Returns a value from the PopupControlState enum.
|
||||
*/
|
||||
PopupBlocker::PopupControlState nsGlobalWindowOuter::RevisePopupAbuseLevel(
|
||||
PopupBlocker::PopupControlState aControl) {
|
||||
NS_ASSERTION(mDocShell, "Must have docshell");
|
||||
|
||||
if (mDocShell->ItemType() != nsIDocShellTreeItem::typeContent) {
|
||||
return PopupBlocker::openAllowed;
|
||||
}
|
||||
|
||||
PopupBlocker::PopupControlState abuse = aControl;
|
||||
switch (abuse) {
|
||||
case PopupBlocker::openControlled:
|
||||
case PopupBlocker::openBlocked:
|
||||
case PopupBlocker::openOverridden:
|
||||
if (IsPopupAllowed()) {
|
||||
abuse = PopupBlocker::PopupControlState(abuse - 1);
|
||||
}
|
||||
break;
|
||||
case PopupBlocker::openAbused:
|
||||
if (IsPopupAllowed()) {
|
||||
// Skip PopupBlocker::openBlocked
|
||||
abuse = PopupBlocker::openControlled;
|
||||
}
|
||||
break;
|
||||
case PopupBlocker::openAllowed:
|
||||
break;
|
||||
default:
|
||||
NS_WARNING("Strange PopupControlState!");
|
||||
}
|
||||
|
||||
// limit the number of simultaneously open popups
|
||||
if (abuse == PopupBlocker::openAbused || abuse == PopupBlocker::openBlocked ||
|
||||
abuse == PopupBlocker::openControlled) {
|
||||
int32_t popupMax = StaticPrefs::dom_popup_maximum();
|
||||
if (popupMax >= 0 &&
|
||||
PopupBlocker::GetOpenPopupSpamCount() >= (uint32_t)popupMax) {
|
||||
abuse = PopupBlocker::openOverridden;
|
||||
}
|
||||
}
|
||||
|
||||
// HACK: Some pages using bogus library + UA sniffing call window.open() from
|
||||
// a blank iframe, only on Firefox, see bug 1685056.
|
||||
//
|
||||
// This is a hack-around to preserve behavior in that particular and specific
|
||||
// case, by consuming activation on the parent document, so we don't care
|
||||
// about the InProcessParent bits not being fission-safe or what not.
|
||||
auto ConsumeTransientUserActivationForMultiplePopupBlocking = [&]() -> bool {
|
||||
if (mDoc->ConsumeTransientUserGestureActivation()) {
|
||||
return true;
|
||||
}
|
||||
if (!mDoc->IsInitialDocument()) {
|
||||
return false;
|
||||
}
|
||||
Document* parentDoc = mDoc->GetInProcessParentDocument();
|
||||
if (!parentDoc ||
|
||||
!parentDoc->NodePrincipal()->Equals(mDoc->NodePrincipal())) {
|
||||
return false;
|
||||
}
|
||||
return parentDoc->ConsumeTransientUserGestureActivation();
|
||||
};
|
||||
|
||||
// If this popup is allowed, let's block any other for this event, forcing
|
||||
// PopupBlocker::openBlocked state.
|
||||
if ((abuse == PopupBlocker::openAllowed ||
|
||||
abuse == PopupBlocker::openControlled) &&
|
||||
StaticPrefs::dom_block_multiple_popups() && !IsPopupAllowed() &&
|
||||
!ConsumeTransientUserActivationForMultiplePopupBlocking()) {
|
||||
nsContentUtils::ReportToConsole(nsIScriptError::warningFlag, "DOM"_ns, mDoc,
|
||||
nsContentUtils::eDOM_PROPERTIES,
|
||||
"MultiplePopupsBlockedNoUserActivation");
|
||||
abuse = PopupBlocker::openBlocked;
|
||||
}
|
||||
|
||||
return abuse;
|
||||
}
|
||||
|
||||
/* If a window open is blocked, fire the appropriate DOM events. */
|
||||
void nsGlobalWindowOuter::FireAbuseEvents(
|
||||
const nsAString& aPopupURL, const nsAString& aPopupWindowName,
|
||||
@ -7114,7 +6995,7 @@ nsresult nsGlobalWindowOuter::OpenInternal(
|
||||
PopupBlocker::PopupControlState abuseLevel =
|
||||
PopupBlocker::GetPopupControlState();
|
||||
if (checkForPopup) {
|
||||
abuseLevel = RevisePopupAbuseLevel(abuseLevel);
|
||||
abuseLevel = mBrowsingContext->RevisePopupAbuseLevel(abuseLevel);
|
||||
if (abuseLevel >= PopupBlocker::openBlocked) {
|
||||
if (!aCalledNoScript) {
|
||||
// If script in some other window is doing a window.open on us and
|
||||
|
@ -532,7 +532,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
|
||||
bool GetClosedOuter();
|
||||
bool Closed() override;
|
||||
void StopOuter(mozilla::ErrorResult& aError);
|
||||
void FocusOuter(mozilla::dom::CallerType aCallerType);
|
||||
void FocusOuter(mozilla::dom::CallerType aCallerType, uint64_t aActionId);
|
||||
nsresult Focus(mozilla::dom::CallerType aCallerType) override;
|
||||
void BlurOuter();
|
||||
mozilla::dom::WindowProxyHolder GetFramesOuter();
|
||||
@ -1061,9 +1061,6 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
|
||||
virtual mozilla::AbstractThread* AbstractMainThreadFor(
|
||||
mozilla::TaskCategory aCategory) override;
|
||||
|
||||
private:
|
||||
bool IsPopupAllowed();
|
||||
|
||||
protected:
|
||||
bool mFullscreen : 1;
|
||||
bool mFullscreenMode : 1;
|
||||
|
@ -3721,7 +3721,8 @@ mozilla::ipc::IPCResult ContentChild::RecvWindowClose(
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(
|
||||
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType) {
|
||||
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
|
||||
uint64_t aActionId) {
|
||||
if (aContext.IsNullOrDiscarded()) {
|
||||
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
|
||||
("ChildIPC: Trying to send a message to dead or detached context"));
|
||||
@ -3735,7 +3736,7 @@ mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(
|
||||
("ChildIPC: Trying to send a message to a context without a window"));
|
||||
return IPC_OK();
|
||||
}
|
||||
nsGlobalWindowOuter::Cast(window)->FocusOuter(aCallerType);
|
||||
nsGlobalWindowOuter::Cast(window)->FocusOuter(aCallerType, aActionId);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -714,7 +714,8 @@ class ContentChild final : public PContentChild,
|
||||
mozilla::ipc::IPCResult RecvWindowClose(
|
||||
const MaybeDiscarded<BrowsingContext>& aContext, bool aTrustedCaller);
|
||||
mozilla::ipc::IPCResult RecvWindowFocus(
|
||||
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType);
|
||||
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
|
||||
uint64_t aActionId);
|
||||
mozilla::ipc::IPCResult RecvWindowBlur(
|
||||
const MaybeDiscarded<BrowsingContext>& aContext);
|
||||
mozilla::ipc::IPCResult RecvRaiseWindow(
|
||||
|
@ -6736,7 +6736,8 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowClose(
|
||||
}
|
||||
|
||||
mozilla::ipc::IPCResult ContentParent::RecvWindowFocus(
|
||||
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType) {
|
||||
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
|
||||
uint64_t aActionId) {
|
||||
if (aContext.IsNullOrDiscarded()) {
|
||||
MOZ_LOG(
|
||||
BrowsingContext::GetLog(), LogLevel::Debug,
|
||||
@ -6748,7 +6749,7 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowFocus(
|
||||
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
|
||||
ContentParent* cp =
|
||||
cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId()));
|
||||
Unused << cp->SendWindowFocus(context, aCallerType);
|
||||
Unused << cp->SendWindowFocus(context, aCallerType, aActionId);
|
||||
return IPC_OK();
|
||||
}
|
||||
|
||||
|
@ -675,7 +675,8 @@ class ContentParent final
|
||||
mozilla::ipc::IPCResult RecvWindowClose(
|
||||
const MaybeDiscarded<BrowsingContext>& aContext, bool aTrustedCaller);
|
||||
mozilla::ipc::IPCResult RecvWindowFocus(
|
||||
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType);
|
||||
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
|
||||
uint64_t aActionId);
|
||||
mozilla::ipc::IPCResult RecvWindowBlur(
|
||||
const MaybeDiscarded<BrowsingContext>& aContext);
|
||||
mozilla::ipc::IPCResult RecvRaiseWindow(
|
||||
|
@ -1801,7 +1801,7 @@ both:
|
||||
async WindowClose(MaybeDiscardedBrowsingContext aContext,
|
||||
bool aTrustedCaller);
|
||||
async WindowFocus(MaybeDiscardedBrowsingContext aContext,
|
||||
CallerType aCallerType);
|
||||
CallerType aCallerType, uint64_t aActionId);
|
||||
async WindowBlur(MaybeDiscardedBrowsingContext aContext);
|
||||
async RaiseWindow(MaybeDiscardedBrowsingContext aContext, CallerType aCallerType, uint64_t aActionId);
|
||||
async ClearFocus(MaybeDiscardedBrowsingContext aContext);
|
||||
|
@ -0,0 +1,3 @@
|
||||
[iframe-focuses-parent-different-site.html]
|
||||
disabled:
|
||||
if (os == "android"): https://bugzilla.mozilla.org/show_bug.cgi?id=1687280
|
@ -0,0 +1,3 @@
|
||||
[iframe-focuses-parent-same-site.html]
|
||||
disabled:
|
||||
if (os == "android"): https://bugzilla.mozilla.org/show_bug.cgi?id=1687280
|
@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>iframe focuses parent</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script>
|
||||
setup({explicit_done:true});
|
||||
var w = null;
|
||||
window.onload = function() {
|
||||
window.onmessage = function(e) {
|
||||
test(function() {
|
||||
assert_equals(e.data, "PASS", 'Check result');
|
||||
}, "Check result");
|
||||
w.close();
|
||||
w = null;
|
||||
done();
|
||||
};
|
||||
w = window.open("support/iframe-focuses-parent-different-site-outer.sub.html");
|
||||
}
|
||||
</script>
|
@ -0,0 +1,20 @@
|
||||
<!doctype html>
|
||||
<meta charset=utf-8>
|
||||
<title>iframe focuses parent</title>
|
||||
<script src=/resources/testharness.js></script>
|
||||
<script src=/resources/testharnessreport.js></script>
|
||||
<script>
|
||||
setup({explicit_done:true});
|
||||
var w = null;
|
||||
window.onload = function() {
|
||||
window.onmessage = function(e) {
|
||||
test(function() {
|
||||
assert_equals(e.data, "PASS", 'Check result');
|
||||
}, "Check result");
|
||||
w.close();
|
||||
w = null;
|
||||
done();
|
||||
};
|
||||
w = window.open("support/iframe-focuses-parent-same-site-outer.html");
|
||||
}
|
||||
</script>
|
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>iframe focuses parent different site inner</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.onmessage = function() {
|
||||
parent.focus();
|
||||
setTimeout(function() {
|
||||
parent.postMessage("finished", "*");
|
||||
}, 500);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>iframe focuses parent different site other</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
opener.postMessage("ready", "*");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>iframe focuses parent different site outer</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="http://{{hosts[alt][www]}}:{{ports[http][0]}}/focus/support/iframe-focuses-parent-different-site-inner.html"></iframe>
|
||||
<script>
|
||||
var w = null;
|
||||
var focusDisallowed = false;
|
||||
var failed = false;
|
||||
window.onmessage = function(e) {
|
||||
if (failed) {
|
||||
return;
|
||||
}
|
||||
if (e.data == "ready") {
|
||||
focusDisallowed = true;
|
||||
document.getElementsByTagName("iframe")[0].contentWindow.postMessage("focus", "*");
|
||||
return;
|
||||
}
|
||||
focusDisallowed = false;
|
||||
if (w) {
|
||||
w.close();
|
||||
w = null;
|
||||
}
|
||||
opener.postMessage(failed ? "FAIL" : "PASS", "*");
|
||||
}
|
||||
window.onload = function() {
|
||||
w = window.open("iframe-focuses-parent-different-site-other.html");
|
||||
}
|
||||
document.body.onfocus = function() {
|
||||
if (focusDisallowed) {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,17 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>iframe focuses parent same site inner</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.onmessage = function() {
|
||||
parent.focus();
|
||||
setTimeout(function() {
|
||||
parent.postMessage("finished", "*");
|
||||
}, 500);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,14 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>iframe focuses parent same site other</title>
|
||||
</head>
|
||||
<body>
|
||||
<script>
|
||||
window.onload = function() {
|
||||
opener.postMessage("ready", "*");
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -0,0 +1,39 @@
|
||||
<!DOCTYPE html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<title>iframe focuses parent same site outer</title>
|
||||
</head>
|
||||
<body>
|
||||
<iframe src="iframe-focuses-parent-same-site-inner.html"></iframe>
|
||||
<script>
|
||||
var w = null;
|
||||
var focusDisallowed = false;
|
||||
var failed = false;
|
||||
window.onmessage = function(e) {
|
||||
if (failed) {
|
||||
return;
|
||||
}
|
||||
if (e.data == "ready") {
|
||||
focusDisallowed = true;
|
||||
document.getElementsByTagName("iframe")[0].contentWindow.postMessage("focus", "*");
|
||||
return;
|
||||
}
|
||||
focusDisallowed = false;
|
||||
if (w) {
|
||||
w.close();
|
||||
w = null;
|
||||
}
|
||||
opener.postMessage(failed ? "FAIL" : "PASS", "*");
|
||||
}
|
||||
window.onload = function() {
|
||||
w = window.open("iframe-focuses-parent-same-site-other.html");
|
||||
}
|
||||
document.body.onfocus = function() {
|
||||
if (focusDisallowed) {
|
||||
failed = true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -218,6 +218,8 @@ SET TIMEOUT: focus/support/iframe-focus-with-different-site-intermediate-frame-o
|
||||
SET TIMEOUT: focus/support/iframe-focus-with-different-site-intermediate-frame-middle.sub.html
|
||||
SET TIMEOUT: focus/support/iframe-contentwindow-focus-with-different-site-intermediate-frame-outer.sub.html
|
||||
SET TIMEOUT: focus/support/iframe-contentwindow-focus-with-different-site-intermediate-frame-middle.sub.html
|
||||
SET TIMEOUT: focus/support/iframe-focuses-parent-different-site-inner.html
|
||||
SET TIMEOUT: focus/support/iframe-focuses-parent-same-site-inner.html
|
||||
|
||||
# generate_tests implementation and sample usage
|
||||
GENERATE_TESTS: resources/test/tests/functional/generate-callback.html
|
||||
|
Loading…
Reference in New Issue
Block a user