Commit d18c5197 authored by Avi Drissman's avatar Avi Drissman Committed by Commit Bot

Security drop fullscreen for any nested WebContents level.

This relands 3dcaec6e with a fix to the test.

BUG=873080
TEST=as in bug

Change-Id: Ie68b197fc6b92447e9633f233354a68fefcf20c7
Reviewed-on: https://chromium-review.googlesource.com/1175925Reviewed-by: default avatarSidney San Martín <sdy@chromium.org>
Commit-Queue: Avi Drissman <avi@chromium.org>
Cr-Commit-Position: refs/heads/master@{#583335}
parent adc38f78
...@@ -2695,8 +2695,7 @@ void WebContentsImpl::CreateNewWindow( ...@@ -2695,8 +2695,7 @@ void WebContentsImpl::CreateNewWindow(
// Any new WebContents opened while this WebContents is in fullscreen can be // Any new WebContents opened while this WebContents is in fullscreen can be
// used to confuse the user, so drop fullscreen. // used to confuse the user, so drop fullscreen.
if (IsFullscreenForCurrentTab()) ForSecurityDropFullscreen();
ExitFullscreen(true);
if (params.opener_suppressed) { if (params.opener_suppressed) {
// When the opener is suppressed, the original renderer cannot access the // When the opener is suppressed, the original renderer cannot access the
...@@ -4366,8 +4365,7 @@ void WebContentsImpl::ViewSource(RenderFrameHostImpl* frame) { ...@@ -4366,8 +4365,7 @@ void WebContentsImpl::ViewSource(RenderFrameHostImpl* frame) {
// Any new WebContents opened while this WebContents is in fullscreen can be // Any new WebContents opened while this WebContents is in fullscreen can be
// used to confuse the user, so drop fullscreen. // used to confuse the user, so drop fullscreen.
if (IsFullscreenForCurrentTab()) ForSecurityDropFullscreen();
ExitFullscreen(true);
// We intentionally don't share the SiteInstance with the original frame so // We intentionally don't share the SiteInstance with the original frame so
// that view source has a consistent process model and always ends up in a new // that view source has a consistent process model and always ends up in a new
...@@ -5084,8 +5082,7 @@ void WebContentsImpl::RunJavaScriptDialog(RenderFrameHost* render_frame_host, ...@@ -5084,8 +5082,7 @@ void WebContentsImpl::RunJavaScriptDialog(RenderFrameHost* render_frame_host,
// Running a dialog causes an exit to webpage-initiated fullscreen. // Running a dialog causes an exit to webpage-initiated fullscreen.
// http://crbug.com/728276 // http://crbug.com/728276
if (IsFullscreenForCurrentTab()) ForSecurityDropFullscreen();
ExitFullscreen(true);
auto callback = auto callback =
base::BindOnce(&WebContentsImpl::OnDialogClosed, base::Unretained(this), base::BindOnce(&WebContentsImpl::OnDialogClosed, base::Unretained(this),
...@@ -5154,8 +5151,7 @@ void WebContentsImpl::RunBeforeUnloadConfirm( ...@@ -5154,8 +5151,7 @@ void WebContentsImpl::RunBeforeUnloadConfirm(
// Running a dialog causes an exit to webpage-initiated fullscreen. // Running a dialog causes an exit to webpage-initiated fullscreen.
// http://crbug.com/728276 // http://crbug.com/728276
if (IsFullscreenForCurrentTab()) ForSecurityDropFullscreen();
ExitFullscreen(true);
RenderFrameHostImpl* rfhi = RenderFrameHostImpl* rfhi =
static_cast<RenderFrameHostImpl*>(render_frame_host); static_cast<RenderFrameHostImpl*>(render_frame_host);
...@@ -5737,6 +5733,15 @@ void WebContentsImpl::EnsureOpenerProxiesExist(RenderFrameHost* source_rfh) { ...@@ -5737,6 +5733,15 @@ void WebContentsImpl::EnsureOpenerProxiesExist(RenderFrameHost* source_rfh) {
} }
} }
void WebContentsImpl::ForSecurityDropFullscreen() {
WebContentsImpl* web_contents = this;
while (web_contents) {
if (web_contents->IsFullscreenForCurrentTab())
web_contents->ExitFullscreen(true);
web_contents = web_contents->GetOuterWebContents();
}
}
void WebContentsImpl::SetAsFocusedWebContentsIfNecessary() { void WebContentsImpl::SetAsFocusedWebContentsIfNecessary() {
// Only change focus if we are not currently focused. // Only change focus if we are not currently focused.
WebContentsImpl* old_contents = GetFocusedWebContents(); WebContentsImpl* old_contents = GetFocusedWebContents();
...@@ -5804,8 +5809,7 @@ void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node, ...@@ -5804,8 +5809,7 @@ void WebContentsImpl::SetFocusedFrame(FrameTreeNode* node,
void WebContentsImpl::DidCallFocus() { void WebContentsImpl::DidCallFocus() {
// Any explicit focusing of another window while this WebContents is in // Any explicit focusing of another window while this WebContents is in
// fullscreen can be used to confuse the user, so drop fullscreen. // fullscreen can be used to confuse the user, so drop fullscreen.
if (IsFullscreenForCurrentTab()) ForSecurityDropFullscreen();
ExitFullscreen(true);
} }
RenderFrameHost* WebContentsImpl::GetFocusedFrameIncludingInnerWebContents() { RenderFrameHost* WebContentsImpl::GetFocusedFrameIncludingInnerWebContents() {
......
...@@ -923,6 +923,11 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, ...@@ -923,6 +923,11 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
// |IsFullscreen| must return |true| when this method is called. // |IsFullscreen| must return |true| when this method is called.
bool IsPictureInPictureAllowedForFullscreenVideo() const; bool IsPictureInPictureAllowedForFullscreenVideo() const;
// The WebContents is trying to take some action that would cause user
// confusion if taken while in fullscreen. If this WebContents or any outer
// WebContents is in fullscreen, drop it.
void ForSecurityDropFullscreen();
// When inner or outer WebContents are present, become the focused // When inner or outer WebContents are present, become the focused
// WebContentsImpl. This will activate this content's main frame RenderWidget // WebContentsImpl. This will activate this content's main frame RenderWidget
// and indirectly all its subframe widgets. GetFocusedRenderWidgetHost will // and indirectly all its subframe widgets. GetFocusedRenderWidgetHost will
...@@ -1013,6 +1018,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents, ...@@ -1013,6 +1018,8 @@ class CONTENT_EXPORT WebContentsImpl : public WebContents,
JavaScriptDialogsInMainAndSubframes); JavaScriptDialogsInMainAndSubframes);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest, FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
DialogsFromJavaScriptEndFullscreen); DialogsFromJavaScriptEndFullscreen);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
DialogsFromJavaScriptEndFullscreenEvenInInnerWC);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest, FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
PopupsFromJavaScriptEndFullscreen); PopupsFromJavaScriptEndFullscreen);
FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest, FRIEND_TEST_ALL_PREFIXES(WebContentsImplBrowserTest,
......
...@@ -1558,8 +1558,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager, ...@@ -1558,8 +1558,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
void ExitFullscreenModeForTab(WebContents*) override { void ExitFullscreenModeForTab(WebContents*) override {
is_fullscreen_ = false; is_fullscreen_ = false;
if (waiting_for_ == kFullscreenExit) if (waiting_for_ == kFullscreenExit) {
waiting_for_ = kNothing;
run_loop_->Quit(); run_loop_->Quit();
}
} }
bool IsFullscreenForTabOrPending( bool IsFullscreenForTabOrPending(
...@@ -1575,8 +1577,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager, ...@@ -1575,8 +1577,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
bool* was_blocked) override { bool* was_blocked) override {
popup_ = std::move(new_contents); popup_ = std::move(new_contents);
if (waiting_for_ == kNewContents) if (waiting_for_ == kNewContents) {
waiting_for_ = kNothing;
run_loop_->Quit(); run_loop_->Quit();
}
} }
// JavaScriptDialogManager // JavaScriptDialogManager
...@@ -1591,8 +1595,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager, ...@@ -1591,8 +1595,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
last_message_ = base::UTF16ToUTF8(message_text); last_message_ = base::UTF16ToUTF8(message_text);
*did_suppress_message = true; *did_suppress_message = true;
if (waiting_for_ == kDialog) if (waiting_for_ == kDialog) {
waiting_for_ = kNothing;
run_loop_->Quit(); run_loop_->Quit();
}
} }
void RunBeforeUnloadDialog(WebContents* web_contents, void RunBeforeUnloadDialog(WebContents* web_contents,
...@@ -1601,8 +1607,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager, ...@@ -1601,8 +1607,10 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
DialogClosedCallback callback) override { DialogClosedCallback callback) override {
std::move(callback).Run(true, base::string16()); std::move(callback).Run(true, base::string16());
if (waiting_for_ == kDialog) if (waiting_for_ == kDialog) {
waiting_for_ = kNothing;
run_loop_->Quit(); run_loop_->Quit();
}
} }
bool HandleJavaScriptDialog(WebContents* web_contents, bool HandleJavaScriptDialog(WebContents* web_contents,
...@@ -1615,7 +1623,12 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager, ...@@ -1615,7 +1623,12 @@ class TestWCDelegateForDialogsAndFullscreen : public JavaScriptDialogManager,
bool reset_state) override {} bool reset_state) override {}
private: private:
enum { kDialog, kNewContents, kFullscreenExit } waiting_for_; enum {
kNothing,
kDialog,
kNewContents,
kFullscreenExit
} waiting_for_ = kNothing;
std::string last_message_; std::string last_message_;
...@@ -2132,6 +2145,51 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, ...@@ -2132,6 +2145,51 @@ IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
wc->SetJavaScriptDialogManagerForTesting(nullptr); wc->SetJavaScriptDialogManagerForTesting(nullptr);
} }
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
DialogsFromJavaScriptEndFullscreenEvenInInnerWC) {
WebContentsImpl* top_contents =
static_cast<WebContentsImpl*>(shell()->web_contents());
TestWCDelegateForDialogsAndFullscreen top_test_delegate;
top_contents->SetDelegate(&top_test_delegate);
GURL url("about:blank");
EXPECT_TRUE(NavigateToURL(shell(), url));
FrameTreeNode* root = top_contents->GetFrameTree()->root();
ASSERT_EQ(0U, root->child_count());
std::string script =
"var iframe = document.createElement('iframe');"
"document.body.appendChild(iframe);";
EXPECT_TRUE(content::ExecuteScript(root->current_frame_host(), script));
EXPECT_TRUE(WaitForLoadStop(shell()->web_contents()));
ASSERT_EQ(1U, root->child_count());
RenderFrameHost* frame = root->child_at(0)->current_frame_host();
ASSERT_NE(nullptr, frame);
WebContentsImpl* inner_contents =
static_cast<WebContentsImpl*>(CreateAndAttachInnerContents(frame));
TestWCDelegateForDialogsAndFullscreen inner_test_delegate;
inner_contents->SetDelegate(&inner_test_delegate);
// A dialog from the inner WebContents should make the outer contents lose
// fullscreen.
top_contents->EnterFullscreenMode(url, blink::WebFullscreenOptions());
EXPECT_TRUE(top_contents->IsFullscreenForCurrentTab());
script = "alert('hi')";
inner_test_delegate.WillWaitForDialog();
EXPECT_TRUE(content::ExecuteScript(inner_contents, script));
inner_test_delegate.Wait();
EXPECT_FALSE(top_contents->IsFullscreenForCurrentTab());
inner_contents->SetDelegate(nullptr);
inner_contents->SetJavaScriptDialogManagerForTesting(nullptr);
top_contents->SetDelegate(nullptr);
top_contents->SetJavaScriptDialogManagerForTesting(nullptr);
}
IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest, IN_PROC_BROWSER_TEST_F(WebContentsImplBrowserTest,
PopupsFromJavaScriptEndFullscreen) { PopupsFromJavaScriptEndFullscreen) {
WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents()); WebContentsImpl* wc = static_cast<WebContentsImpl*>(shell()->web_contents());
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment