Bug 1690747 - Should also check blur is allowed in BrowsingContext::Blur(); r=hsivonen

When binding delegates blur() to BrowsingContext::Blur, the remote side skips
the check given that there is no js on the stack, but we should not skip the
check. This only affects design-mode which allows the focus moving to the root
element.

Differential Revision: https://phabricator.services.mozilla.com/D104008
This commit is contained in:
Edgar Chen 2021-02-09 14:56:56 +00:00
Родитель bd660428af
Коммит 0916876268
15 изменённых файлов: 129 добавлений и 20 удалений

Просмотреть файл

@ -2148,11 +2148,22 @@ void BrowsingContext::Focus(CallerType aCallerType, ErrorResult& aError) {
}
}
void BrowsingContext::Blur(ErrorResult& aError) {
bool BrowsingContext::CanBlurCheck(CallerType aCallerType) {
// If dom.disable_window_flip == true, then content should not be allowed
// to do blur (this would allow popunders, bug 369306)
return aCallerType == CallerType::System ||
!Preferences::GetBool("dom.disable_window_flip", true);
}
void BrowsingContext::Blur(CallerType aCallerType, ErrorResult& aError) {
if (!CanBlurCheck(aCallerType)) {
return;
}
if (ContentChild* cc = ContentChild::GetSingleton()) {
cc->SendWindowBlur(this);
cc->SendWindowBlur(this, aCallerType);
} else if (ContentParent* cp = Canonical()->GetContentParent()) {
Unused << cp->SendWindowBlur(this);
Unused << cp->SendWindowBlur(this, aCallerType);
}
}

Просмотреть файл

@ -610,7 +610,7 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
void Close(CallerType aCallerType, ErrorResult& aError);
bool GetClosed(ErrorResult&) { return GetClosed(); }
void Focus(CallerType aCallerType, ErrorResult& aError);
void Blur(ErrorResult& aError);
void Blur(CallerType aCallerType, ErrorResult& aError);
WindowProxyHolder GetFrames(ErrorResult& aError);
int32_t Length() const { return Children().Length(); }
Nullable<WindowProxyHolder> GetTop(ErrorResult& aError);
@ -784,6 +784,8 @@ class BrowsingContext : public nsILoadContext, public nsWrapperCache {
// Returns canFocus, isActive
std::tuple<bool, bool> CanFocusCheck(CallerType aCallerType);
bool CanBlurCheck(CallerType aCallerType);
PopupBlocker::PopupControlState RevisePopupAbuseLevel(
PopupBlocker::PopupControlState aControl);

Просмотреть файл

@ -3736,8 +3736,8 @@ nsresult nsGlobalWindowInner::Focus(CallerType aCallerType) {
return rv.StealNSResult();
}
void nsGlobalWindowInner::Blur(ErrorResult& aError) {
FORWARD_TO_OUTER_OR_THROW(BlurOuter, (), aError, );
void nsGlobalWindowInner::Blur(CallerType aCallerType, ErrorResult& aError) {
FORWARD_TO_OUTER_OR_THROW(BlurOuter, (aCallerType), aError, );
}
void nsGlobalWindowInner::Stop(ErrorResult& aError) {

Просмотреть файл

@ -608,7 +608,7 @@ class nsGlobalWindowInner final : public mozilla::dom::EventTarget,
void Focus(mozilla::dom::CallerType aCallerType,
mozilla::ErrorResult& aError);
nsresult Focus(mozilla::dom::CallerType aCallerType) override;
void Blur(mozilla::ErrorResult& aError);
void Blur(mozilla::dom::CallerType aCallerType, mozilla::ErrorResult& aError);
mozilla::dom::WindowProxyHolder GetFrames(mozilla::ErrorResult& aError);
uint32_t Length();
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetTop(

Просмотреть файл

@ -5117,10 +5117,8 @@ nsresult nsGlobalWindowOuter::Focus(CallerType aCallerType) {
FORWARD_TO_INNER(Focus, (aCallerType), NS_ERROR_UNEXPECTED);
}
void nsGlobalWindowOuter::BlurOuter() {
// If dom.disable_window_flip == true, then content should not be allowed
// to call this function (this would allow popunders, bug 369306)
if (!CanSetProperty("dom.disable_window_flip")) {
void nsGlobalWindowOuter::BlurOuter(CallerType aCallerType) {
if (!GetBrowsingContext()->CanBlurCheck(aCallerType)) {
return;
}

Просмотреть файл

@ -535,7 +535,7 @@ class nsGlobalWindowOuter final : public mozilla::dom::EventTarget,
void FocusOuter(mozilla::dom::CallerType aCallerType, bool aFromOtherProcess,
uint64_t aActionId);
nsresult Focus(mozilla::dom::CallerType aCallerType) override;
void BlurOuter();
void BlurOuter(mozilla::dom::CallerType aCallerType);
mozilla::dom::WindowProxyHolder GetFramesOuter();
uint32_t Length();
mozilla::dom::Nullable<mozilla::dom::WindowProxyHolder> GetTopOuter();

Просмотреть файл

@ -0,0 +1,32 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>activeElement design-mode inner document</title>
</head>
<body>
<h1>Inner</h1>
<script>
let innerlog = "innerlog:";
document.designmode = "on";
window.onmessage = function(e) {
if (e.data == "focus") {
document.documentElement.focus();
} else if (e.data == "getlog") {
innerlog += "activeElement:" + document.activeElement.tagName + ",";
parent.postMessage(innerlog, "*");
}
};
window.onfocus = function() {
innerlog += "windowfocus,";
};
window.onblur = function() {
innerlog += "windowblur,";
};
</script>
</body>
</html>

Просмотреть файл

@ -657,6 +657,9 @@ skip-if = toolkit == 'android' && !is_fennec # Bug 1525959
[test_focus_scrollable_input.html]
[test_focus_scrollable_fieldset.html]
[test_focus_scroll_padding_tab.html]
[test_focus_design_mode.html]
support-files =
file_focus_design_mode_inner.html
[test_getAttribute_after_createAttribute.html]
[test_getElementById.html]
[test_getTranslationNodes.html]

Просмотреть файл

@ -0,0 +1,62 @@
<!DOCTYPE HTML>
<html>
<!--
https://bugzilla.mozilla.org/show_bug.cgi?id=1690747
-->
<head>
<title>Test for Bug 1690747</title>
<script src="/tests/SimpleTest/SimpleTest.js"></script>
<script src="/tests/SimpleTest/EventUtils.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css"/>
</head>
<body>
<a target="_blank" href="https://bugzilla.mozilla.org/show_bug.cgi?id=1690747">Mozilla Bug 1690747</a>
<p id="display"></p>
<div id='content'>
</div>
<pre id="test">
<iframe src="https://example.org/tests/dom/base/test/file_focus_design_mode_inner.html"></iframe>
<script type="application/javascript">
/** Test for Bug 1690747 **/
let iframe = document.querySelector("iframe");
function waitForEvent(target, event, checkFn) {
return new Promise(resolve => {
target.addEventListener(event, e => {
if (checkFn && !checkFn(e)) {
return;
}
resolve();
}, { once: true });
});
}
async function getLog() {
let log = "";
SimpleTest.executeSoon(function() {
iframe.contentWindow.postMessage("getlog", "*");
});
await waitForEvent(window, "message", (e) => {
log = e.data;
return true;
});
return log;
}
add_task(async function init() {
await SpecialPowers.pushPrefEnv({ set: [["dom.disable_window_flip", true]] });
});
add_task(async function activeElementAfterBluring() {
iframe.contentWindow.postMessage("focus", "*");
is(await getLog(), "innerlog:windowfocus,activeElement:HTML,", "check activeElement");
iframe.contentWindow.blur();
is(await getLog(), "innerlog:windowfocus,activeElement:HTML,activeElement:HTML,", "check activeElement after bluring");
});
</script>
</pre>
</body>
</html>

Просмотреть файл

@ -3734,7 +3734,7 @@ mozilla::ipc::IPCResult ContentChild::RecvWindowFocus(
}
mozilla::ipc::IPCResult ContentChild::RecvWindowBlur(
const MaybeDiscarded<BrowsingContext>& aContext) {
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType) {
if (aContext.IsNullOrDiscarded()) {
MOZ_LOG(BrowsingContext::GetLog(), LogLevel::Debug,
("ChildIPC: Trying to send a message to dead or detached context"));
@ -3748,7 +3748,7 @@ mozilla::ipc::IPCResult ContentChild::RecvWindowBlur(
("ChildIPC: Trying to send a message to a context without a window"));
return IPC_OK();
}
nsGlobalWindowOuter::Cast(window)->BlurOuter();
nsGlobalWindowOuter::Cast(window)->BlurOuter(aCallerType);
return IPC_OK();
}

Просмотреть файл

@ -712,7 +712,7 @@ class ContentChild final : public PContentChild,
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
uint64_t aActionId);
mozilla::ipc::IPCResult RecvWindowBlur(
const MaybeDiscarded<BrowsingContext>& aContext);
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType);
mozilla::ipc::IPCResult RecvRaiseWindow(
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
uint64_t aActionId);

Просмотреть файл

@ -6817,7 +6817,7 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowFocus(
}
mozilla::ipc::IPCResult ContentParent::RecvWindowBlur(
const MaybeDiscarded<BrowsingContext>& aContext) {
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType) {
if (aContext.IsNullOrDiscarded()) {
MOZ_LOG(
BrowsingContext::GetLog(), LogLevel::Debug,
@ -6829,7 +6829,7 @@ mozilla::ipc::IPCResult ContentParent::RecvWindowBlur(
ContentProcessManager* cpm = ContentProcessManager::GetSingleton();
ContentParent* cp =
cpm->GetContentProcessById(ContentParentId(context->OwnerProcessId()));
Unused << cp->SendWindowBlur(context);
Unused << cp->SendWindowBlur(context, aCallerType);
return IPC_OK();
}

Просмотреть файл

@ -679,7 +679,7 @@ class ContentParent final
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
uint64_t aActionId);
mozilla::ipc::IPCResult RecvWindowBlur(
const MaybeDiscarded<BrowsingContext>& aContext);
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType);
mozilla::ipc::IPCResult RecvRaiseWindow(
const MaybeDiscarded<BrowsingContext>& aContext, CallerType aCallerType,
uint64_t aActionId);

Просмотреть файл

@ -1799,7 +1799,8 @@ both:
bool aTrustedCaller);
async WindowFocus(MaybeDiscardedBrowsingContext aContext,
CallerType aCallerType, uint64_t aActionId);
async WindowBlur(MaybeDiscardedBrowsingContext aContext);
async WindowBlur(MaybeDiscardedBrowsingContext aContext,
CallerType aCallerType);
async RaiseWindow(MaybeDiscardedBrowsingContext aContext, CallerType aCallerType, uint64_t aActionId);
async ClearFocus(MaybeDiscardedBrowsingContext aContext);
async SetFocusedBrowsingContext(MaybeDiscardedBrowsingContext aContext);

Просмотреть файл

@ -226,7 +226,7 @@ typedef OfflineResourceList ApplicationCache;
[Throws, CrossOriginReadable] readonly attribute boolean closed;
[Throws] void stop();
[Throws, CrossOriginCallable, NeedsCallerType] void focus();
[Throws, CrossOriginCallable] void blur();
[Throws, CrossOriginCallable, NeedsCallerType] void blur();
[Replaceable, Pref="dom.window.event.enabled"] readonly attribute any event;
// other browsing contexts