Chromium Code Reviews| Index: content/browser/site_per_process_browsertest.cc |
| diff --git a/content/browser/site_per_process_browsertest.cc b/content/browser/site_per_process_browsertest.cc |
| index 542db3ac6b3c555bdfa342b6cdeadf4cc32ad9bd..17fc348668d919172dab088021f0af1180bf453c 100644 |
| --- a/content/browser/site_per_process_browsertest.cc |
| +++ b/content/browser/site_per_process_browsertest.cc |
| @@ -10200,4 +10200,106 @@ IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, |
| EXPECT_EQ(foo_url, web_contents()->GetMainFrame()->GetLastCommittedURL()); |
| } |
| +// Class to sniff incoming IPCs for FrameHostMsg_SetIsInert messages. |
| +class SetIsInertMessageFilter : public content::BrowserMessageFilter { |
| + public: |
| + SetIsInertMessageFilter() |
| + : content::BrowserMessageFilter(FrameMsgStart), |
| + message_loop_runner_(new content::MessageLoopRunner), |
| + msg_received_(false) {} |
| + |
| + bool OnMessageReceived(const IPC::Message& message) override { |
| + IPC_BEGIN_MESSAGE_MAP(SetIsInertMessageFilter, message) |
| + IPC_MESSAGE_HANDLER(FrameHostMsg_SetIsInert, OnSetIsInert) |
| + IPC_END_MESSAGE_MAP() |
| + return false; |
| + } |
| + |
| + bool is_inert() const { return is_inert_; } |
| + |
| + void Wait() { message_loop_runner_->Run(); } |
| + |
| + void Reset() { |
|
alexmos
2017/06/16 02:17:57
Is this needed? It doesn't appear to be used in t
kenrb
2017/06/19 19:26:22
Removed.
|
| + is_inert_ = false; |
| + message_loop_runner_ = new content::MessageLoopRunner; |
| + msg_received_ = false; |
| + } |
| + |
| + private: |
| + ~SetIsInertMessageFilter() override {} |
| + |
| + void OnSetIsInert(bool is_inert) { |
| + content::BrowserThread::PostTask( |
| + content::BrowserThread::UI, FROM_HERE, |
| + base::Bind(&SetIsInertMessageFilter::OnSetIsInertOnUI, this, is_inert)); |
| + } |
| + void OnSetIsInertOnUI(bool is_inert) { |
| + is_inert_ = is_inert; |
| + if (!msg_received_) { |
| + msg_received_ = true; |
| + message_loop_runner_->Quit(); |
| + } |
| + } |
| + scoped_refptr<content::MessageLoopRunner> message_loop_runner_; |
| + bool msg_received_; |
| + bool is_inert_; |
| + DISALLOW_COPY_AND_ASSIGN(SetIsInertMessageFilter); |
| +}; |
| + |
| +// Tests that when a frame contains a modal <dialog> element, out-of-process |
| +// iframe children cannot take focus, because they are inert. |
| +IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossProcessInertSubframe) { |
| + GURL main_url(embedded_test_server()->GetURL( |
| + "a.com", "/cross_site_iframe_factory.html?a(b)")); |
| + EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| + |
| + FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| + ->GetFrameTree() |
| + ->root(); |
| + ASSERT_EQ(1U, root->child_count()); |
| + |
| + FrameTreeNode* iframe_node = root->child_at(0); |
| + |
| + EXPECT_TRUE(ExecuteScript( |
| + iframe_node, |
| + "document.head.innerHTML = '';" |
| + "document.body.innerHTML = '<input id=\"text1\"> <input id=\"text2\">';" |
| + "text1.focus();")); |
| + |
| + scoped_refptr<SetIsInertMessageFilter> filter = new SetIsInertMessageFilter(); |
| + root->current_frame_host()->GetProcess()->AddFilter(filter.get()); |
|
alexmos
2017/06/16 02:17:57
Perhaps mention in a comment somewhere that the in
kenrb
2017/06/19 19:26:22
Done.
|
| + |
| + // Add a <dialog> to the root frame and call showModal on it. |
| + EXPECT_TRUE(ExecuteScript(root, |
| + "let dialog = " |
| + "document.body.appendChild(document.createElement('" |
| + "dialog'));" |
| + "dialog.innerHTML = 'Modal dialog <input>';" |
| + "dialog.showModal();")); |
| + filter->Wait(); |
| + EXPECT_TRUE(filter->is_inert()); |
| + |
| + // This yields the UI thread to ensure that the real SetIsInert message |
| + // handler runs, in order to guarantee that the update arrives at the |
| + // renderer process before the script below. |
| + { |
| + base::RunLoop loop; |
| + base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| + loop.QuitClosure()); |
| + loop.Run(); |
| + } |
| + |
| + std::string focused_element; |
| + |
| + // Attempt to change focus in the inert subframe. This should fail. |
| + // The setTimeout ensures that the inert bit can propagate before the |
| + // test JS code runs. |
| + EXPECT_TRUE(ExecuteScriptAndExtractString( |
| + iframe_node, |
| + "window.setTimeout(() => {text2.focus();" |
| + "domAutomationController.send(document.activeElement.id);}, 0)", |
| + &focused_element)); |
| + EXPECT_EQ("", focused_element); |
|
alexmos
2017/06/16 02:17:57
I was also curious about scenarios like the page d
kenrb
2017/06/19 19:26:22
The bit needs to be sent again after a swap from o
|
| +} |
| + |
| } // namespace content |