OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "content/browser/site_per_process_browsertest.h" | 5 #include "content/browser/site_per_process_browsertest.h" |
6 | 6 |
7 #include <stddef.h> | 7 #include <stddef.h> |
8 #include <stdint.h> | 8 #include <stdint.h> |
9 | 9 |
10 #include <algorithm> | 10 #include <algorithm> |
(...skipping 10179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
10190 | 10190 |
10191 // Go back again. This should go to foo.com. | 10191 // Go back again. This should go to foo.com. |
10192 { | 10192 { |
10193 TestNavigationObserver back_observer(web_contents()); | 10193 TestNavigationObserver back_observer(web_contents()); |
10194 web_contents()->GetController().GoBack(); | 10194 web_contents()->GetController().GoBack(); |
10195 back_observer.Wait(); | 10195 back_observer.Wait(); |
10196 } | 10196 } |
10197 EXPECT_EQ(foo_url, web_contents()->GetMainFrame()->GetLastCommittedURL()); | 10197 EXPECT_EQ(foo_url, web_contents()->GetMainFrame()->GetLastCommittedURL()); |
10198 } | 10198 } |
10199 | 10199 |
| 10200 // Class to sniff incoming IPCs for FrameHostMsg_SetIsInert messages. |
| 10201 class SetIsInertMessageFilter : public content::BrowserMessageFilter { |
| 10202 public: |
| 10203 SetIsInertMessageFilter() |
| 10204 : content::BrowserMessageFilter(FrameMsgStart), |
| 10205 message_loop_runner_(new content::MessageLoopRunner), |
| 10206 msg_received_(false) {} |
| 10207 |
| 10208 bool OnMessageReceived(const IPC::Message& message) override { |
| 10209 IPC_BEGIN_MESSAGE_MAP(SetIsInertMessageFilter, message) |
| 10210 IPC_MESSAGE_HANDLER(FrameHostMsg_SetIsInert, OnSetIsInert) |
| 10211 IPC_END_MESSAGE_MAP() |
| 10212 return false; |
| 10213 } |
| 10214 |
| 10215 bool is_inert() const { return is_inert_; } |
| 10216 |
| 10217 void Wait() { message_loop_runner_->Run(); } |
| 10218 |
| 10219 private: |
| 10220 ~SetIsInertMessageFilter() override {} |
| 10221 |
| 10222 void OnSetIsInert(bool is_inert) { |
| 10223 content::BrowserThread::PostTask( |
| 10224 content::BrowserThread::UI, FROM_HERE, |
| 10225 base::Bind(&SetIsInertMessageFilter::OnSetIsInertOnUI, this, is_inert)); |
| 10226 } |
| 10227 void OnSetIsInertOnUI(bool is_inert) { |
| 10228 is_inert_ = is_inert; |
| 10229 if (!msg_received_) { |
| 10230 msg_received_ = true; |
| 10231 message_loop_runner_->Quit(); |
| 10232 } |
| 10233 } |
| 10234 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; |
| 10235 bool msg_received_; |
| 10236 bool is_inert_; |
| 10237 DISALLOW_COPY_AND_ASSIGN(SetIsInertMessageFilter); |
| 10238 }; |
| 10239 |
| 10240 // Tests that when a frame contains a modal <dialog> element, out-of-process |
| 10241 // iframe children cannot take focus, because they are inert. |
| 10242 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossProcessInertSubframe) { |
| 10243 // This uses a(b,b) instead of a(b) to preserve the b.com process even when |
| 10244 // the first subframe is navigated away from it. |
| 10245 GURL main_url(embedded_test_server()->GetURL( |
| 10246 "a.com", "/cross_site_iframe_factory.html?a(b,b)")); |
| 10247 EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| 10248 |
| 10249 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 10250 ->GetFrameTree() |
| 10251 ->root(); |
| 10252 ASSERT_EQ(2U, root->child_count()); |
| 10253 |
| 10254 FrameTreeNode* iframe_node = root->child_at(0); |
| 10255 |
| 10256 EXPECT_TRUE(ExecuteScript( |
| 10257 iframe_node, |
| 10258 "document.head.innerHTML = '';" |
| 10259 "document.body.innerHTML = '<input id=\"text1\"> <input id=\"text2\">';" |
| 10260 "text1.focus();")); |
| 10261 |
| 10262 // Add a filter to the parent frame's process to monitor for inert bit |
| 10263 // updates. These are sent through the proxy for b.com child frame. |
| 10264 scoped_refptr<SetIsInertMessageFilter> filter = new SetIsInertMessageFilter(); |
| 10265 root->current_frame_host()->GetProcess()->AddFilter(filter.get()); |
| 10266 |
| 10267 // Add a <dialog> to the root frame and call showModal on it. |
| 10268 EXPECT_TRUE(ExecuteScript(root, |
| 10269 "let dialog = " |
| 10270 "document.body.appendChild(document.createElement('" |
| 10271 "dialog'));" |
| 10272 "dialog.innerHTML = 'Modal dialog <input>';" |
| 10273 "dialog.showModal();")); |
| 10274 filter->Wait(); |
| 10275 EXPECT_TRUE(filter->is_inert()); |
| 10276 |
| 10277 // This yields the UI thread to ensure that the real SetIsInert message |
| 10278 // handler runs, in order to guarantee that the update arrives at the |
| 10279 // renderer process before the script below. |
| 10280 { |
| 10281 base::RunLoop loop; |
| 10282 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, |
| 10283 loop.QuitClosure()); |
| 10284 loop.Run(); |
| 10285 } |
| 10286 |
| 10287 std::string focused_element; |
| 10288 |
| 10289 // Attempt to change focus in the inert subframe. This should fail. |
| 10290 // The setTimeout ensures that the inert bit can propagate before the |
| 10291 // test JS code runs. |
| 10292 EXPECT_TRUE(ExecuteScriptAndExtractString( |
| 10293 iframe_node, |
| 10294 "window.setTimeout(() => {text2.focus();" |
| 10295 "domAutomationController.send(document.activeElement.id);}, 0)", |
| 10296 &focused_element)); |
| 10297 EXPECT_EQ("", focused_element); |
| 10298 |
| 10299 // Navigate the child frame to another site, so that it moves into a new |
| 10300 // process. |
| 10301 GURL site_url(embedded_test_server()->GetURL("c.com", "/title1.html")); |
| 10302 NavigateFrameToURL(iframe_node, site_url); |
| 10303 |
| 10304 EXPECT_TRUE(ExecuteScript( |
| 10305 iframe_node, |
| 10306 "document.head.innerHTML = '';" |
| 10307 "document.body.innerHTML = '<input id=\"text1\"> <input id=\"text2\">';" |
| 10308 "text1.focus();")); |
| 10309 |
| 10310 // Verify that inertness was preserved across the navigation. |
| 10311 EXPECT_TRUE(ExecuteScriptAndExtractString( |
| 10312 iframe_node, |
| 10313 "text2.focus();" |
| 10314 "domAutomationController.send(document.activeElement.id);", |
| 10315 &focused_element)); |
| 10316 EXPECT_EQ("", focused_element); |
| 10317 |
| 10318 // Navigate the subframe back into its parent process to verify that the |
| 10319 // new local frame remains inert. |
| 10320 GURL same_site_url(embedded_test_server()->GetURL("a.com", "/title1.html")); |
| 10321 NavigateFrameToURL(iframe_node, same_site_url); |
| 10322 |
| 10323 EXPECT_TRUE(ExecuteScript( |
| 10324 iframe_node, |
| 10325 "document.head.innerHTML = '';" |
| 10326 "document.body.innerHTML = '<input id=\"text1\"> <input id=\"text2\">';" |
| 10327 "text1.focus();")); |
| 10328 |
| 10329 // Verify that inertness was preserved across the navigation. |
| 10330 EXPECT_TRUE(ExecuteScriptAndExtractString( |
| 10331 iframe_node, |
| 10332 "text2.focus();" |
| 10333 "domAutomationController.send(document.activeElement.id);", |
| 10334 &focused_element)); |
| 10335 EXPECT_EQ("", focused_element); |
| 10336 } |
| 10337 |
10200 } // namespace content | 10338 } // namespace content |
OLD | NEW |