Skip to content

Commit

Permalink
Bug 1690747 - Should also check blur is allowed in BrowsingContext::B…
Browse files Browse the repository at this point in the history
…lur(); 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
  • Loading branch information
EdgarChen committed Feb 9, 2021
1 parent bd66042 commit 0916876
Show file tree
Hide file tree
Showing 15 changed files with 129 additions and 20 deletions.
17 changes: 14 additions & 3 deletions docshell/base/BrowsingContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down
4 changes: 3 additions & 1 deletion docshell/base/BrowsingContext.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);

Expand Down
4 changes: 2 additions & 2 deletions dom/base/nsGlobalWindowInner.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
2 changes: 1 addition & 1 deletion dom/base/nsGlobalWindowInner.h
Original file line number Diff line number Diff line change
Expand Up @@ -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(
Expand Down
6 changes: 2 additions & 4 deletions dom/base/nsGlobalWindowOuter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}

Expand Down
2 changes: 1 addition & 1 deletion dom/base/nsGlobalWindowOuter.h
Original file line number Diff line number Diff line change
Expand Up @@ -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();
Expand Down
32 changes: 32 additions & 0 deletions dom/base/test/file_focus_design_mode_inner.html
Original file line number Diff line number Diff line change
@@ -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>
3 changes: 3 additions & 0 deletions dom/base/test/mochitest.ini
Original file line number Diff line number Diff line change
Expand Up @@ -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]
Expand Down
62 changes: 62 additions & 0 deletions dom/base/test/test_focus_design_mode.html
Original file line number Diff line number Diff line change
@@ -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>
4 changes: 2 additions & 2 deletions dom/ipc/ContentChild.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"));
Expand All @@ -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();
}

Expand Down
2 changes: 1 addition & 1 deletion dom/ipc/ContentChild.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 2 additions & 2 deletions dom/ipc/ContentParent.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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();
}

Expand Down
2 changes: 1 addition & 1 deletion dom/ipc/ContentParent.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
3 changes: 2 additions & 1 deletion dom/ipc/PContent.ipdl
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 1 addition & 1 deletion dom/webidl/Window.webidl
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 0916876

Please sign in to comment.