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 10182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
10193 | 10193 |
10194 // Go back again. This should go to foo.com. | 10194 // Go back again. This should go to foo.com. |
10195 { | 10195 { |
10196 TestNavigationObserver back_observer(web_contents()); | 10196 TestNavigationObserver back_observer(web_contents()); |
10197 web_contents()->GetController().GoBack(); | 10197 web_contents()->GetController().GoBack(); |
10198 back_observer.Wait(); | 10198 back_observer.Wait(); |
10199 } | 10199 } |
10200 EXPECT_EQ(foo_url, web_contents()->GetMainFrame()->GetLastCommittedURL()); | 10200 EXPECT_EQ(foo_url, web_contents()->GetMainFrame()->GetLastCommittedURL()); |
10201 } | 10201 } |
10202 | 10202 |
10203 // Class to sniff incoming IPCs for FrameHostMsg_SetIsInert messages. | |
10204 class SetIsInertMessageFilter : public content::BrowserMessageFilter { | |
10205 public: | |
10206 SetIsInertMessageFilter() | |
10207 : content::BrowserMessageFilter(FrameMsgStart), | |
10208 message_loop_runner_(new content::MessageLoopRunner), | |
10209 msg_received_(false) {} | |
10210 | |
10211 bool OnMessageReceived(const IPC::Message& message) override { | |
10212 IPC_BEGIN_MESSAGE_MAP(SetIsInertMessageFilter, message) | |
10213 IPC_MESSAGE_HANDLER(FrameHostMsg_SetIsInert, OnSetIsInert) | |
10214 IPC_END_MESSAGE_MAP() | |
10215 return false; | |
10216 } | |
10217 | |
10218 bool is_inert() const { return is_inert_; } | |
10219 | |
10220 void Wait() { message_loop_runner_->Run(); } | |
10221 | |
10222 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.
| |
10223 is_inert_ = false; | |
10224 message_loop_runner_ = new content::MessageLoopRunner; | |
10225 msg_received_ = false; | |
10226 } | |
10227 | |
10228 private: | |
10229 ~SetIsInertMessageFilter() override {} | |
10230 | |
10231 void OnSetIsInert(bool is_inert) { | |
10232 content::BrowserThread::PostTask( | |
10233 content::BrowserThread::UI, FROM_HERE, | |
10234 base::Bind(&SetIsInertMessageFilter::OnSetIsInertOnUI, this, is_inert)); | |
10235 } | |
10236 void OnSetIsInertOnUI(bool is_inert) { | |
10237 is_inert_ = is_inert; | |
10238 if (!msg_received_) { | |
10239 msg_received_ = true; | |
10240 message_loop_runner_->Quit(); | |
10241 } | |
10242 } | |
10243 scoped_refptr<content::MessageLoopRunner> message_loop_runner_; | |
10244 bool msg_received_; | |
10245 bool is_inert_; | |
10246 DISALLOW_COPY_AND_ASSIGN(SetIsInertMessageFilter); | |
10247 }; | |
10248 | |
10249 // Tests that when a frame contains a modal <dialog> element, out-of-process | |
10250 // iframe children cannot take focus, because they are inert. | |
10251 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, CrossProcessInertSubframe) { | |
10252 GURL main_url(embedded_test_server()->GetURL( | |
10253 "a.com", "/cross_site_iframe_factory.html?a(b)")); | |
10254 EXPECT_TRUE(NavigateToURL(shell(), main_url)); | |
10255 | |
10256 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) | |
10257 ->GetFrameTree() | |
10258 ->root(); | |
10259 ASSERT_EQ(1U, root->child_count()); | |
10260 | |
10261 FrameTreeNode* iframe_node = root->child_at(0); | |
10262 | |
10263 EXPECT_TRUE(ExecuteScript( | |
10264 iframe_node, | |
10265 "document.head.innerHTML = '';" | |
10266 "document.body.innerHTML = '<input id=\"text1\"> <input id=\"text2\">';" | |
10267 "text1.focus();")); | |
10268 | |
10269 scoped_refptr<SetIsInertMessageFilter> filter = new SetIsInertMessageFilter(); | |
10270 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.
| |
10271 | |
10272 // Add a <dialog> to the root frame and call showModal on it. | |
10273 EXPECT_TRUE(ExecuteScript(root, | |
10274 "let dialog = " | |
10275 "document.body.appendChild(document.createElement('" | |
10276 "dialog'));" | |
10277 "dialog.innerHTML = 'Modal dialog <input>';" | |
10278 "dialog.showModal();")); | |
10279 filter->Wait(); | |
10280 EXPECT_TRUE(filter->is_inert()); | |
10281 | |
10282 // This yields the UI thread to ensure that the real SetIsInert message | |
10283 // handler runs, in order to guarantee that the update arrives at the | |
10284 // renderer process before the script below. | |
10285 { | |
10286 base::RunLoop loop; | |
10287 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, | |
10288 loop.QuitClosure()); | |
10289 loop.Run(); | |
10290 } | |
10291 | |
10292 std::string focused_element; | |
10293 | |
10294 // Attempt to change focus in the inert subframe. This should fail. | |
10295 // The setTimeout ensures that the inert bit can propagate before the | |
10296 // test JS code runs. | |
10297 EXPECT_TRUE(ExecuteScriptAndExtractString( | |
10298 iframe_node, | |
10299 "window.setTimeout(() => {text2.focus();" | |
10300 "domAutomationController.send(document.activeElement.id);}, 0)", | |
10301 &focused_element)); | |
10302 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
| |
10303 } | |
10304 | |
10203 } // namespace content | 10305 } // namespace content |
OLD | NEW |