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 "base/file_util.h" | 5 #include "base/file_util.h" |
| 6 #include "base/json/json_reader.h" |
6 #include "base/memory/ref_counted.h" | 7 #include "base/memory/ref_counted.h" |
7 #include "base/path_service.h" | 8 #include "base/path_service.h" |
8 #include "base/utf_string_conversions.h" | 9 #include "base/utf_string_conversions.h" |
| 10 #include "content/common/content_constants_internal.h" |
9 #include "content/browser/renderer_host/render_view_host_impl.h" | 11 #include "content/browser/renderer_host/render_view_host_impl.h" |
10 #include "content/browser/site_instance_impl.h" | 12 #include "content/browser/site_instance_impl.h" |
11 #include "content/browser/web_contents/web_contents_impl.h" | 13 #include "content/browser/web_contents/web_contents_impl.h" |
12 #include "content/public/browser/navigation_controller.h" | 14 #include "content/public/browser/navigation_controller.h" |
13 #include "content/public/browser/navigation_entry.h" | 15 #include "content/public/browser/navigation_entry.h" |
14 #include "content/public/browser/notification_details.h" | 16 #include "content/public/browser/notification_details.h" |
15 #include "content/public/browser/notification_observer.h" | 17 #include "content/public/browser/notification_observer.h" |
16 #include "content/public/browser/notification_registrar.h" | 18 #include "content/public/browser/notification_registrar.h" |
17 #include "content/public/browser/notification_types.h" | 19 #include "content/public/browser/notification_types.h" |
18 #include "content/public/browser/render_process_host.h" | 20 #include "content/public/browser/render_process_host.h" |
19 #include "content/public/browser/render_view_host_observer.h" | 21 #include "content/public/browser/render_view_host_observer.h" |
20 #include "content/public/browser/web_contents.h" | 22 #include "content/public/browser/web_contents.h" |
21 #include "content/public/common/url_constants.h" | 23 #include "content/public/common/url_constants.h" |
22 #include "content/public/test/browser_test_utils.h" | 24 #include "content/public/test/browser_test_utils.h" |
23 #include "content/public/test/test_utils.h" | 25 #include "content/public/test/test_utils.h" |
24 #include "content/shell/shell.h" | 26 #include "content/shell/shell.h" |
25 #include "content/test/content_browser_test.h" | 27 #include "content/test/content_browser_test.h" |
26 #include "content/test/content_browser_test_utils.h" | 28 #include "content/test/content_browser_test_utils.h" |
27 #include "net/base/net_util.h" | 29 #include "net/base/net_util.h" |
28 #include "net/test/test_server.h" | 30 #include "net/test/test_server.h" |
29 | 31 |
| 32 namespace { |
| 33 |
| 34 bool CompareTrees(base::DictionaryValue* first, base::DictionaryValue* second) { |
| 35 string16 name1; |
| 36 string16 name2; |
| 37 if (!first->GetString(content::kFrameTreeNodeNameKey, &name1) || |
| 38 !second->GetString(content::kFrameTreeNodeNameKey, &name2)) |
| 39 return false; |
| 40 if (name1 != name2) |
| 41 return false; |
| 42 |
| 43 int id1 = 0; |
| 44 int id2 = 0; |
| 45 if (!first->GetInteger(content::kFrameTreeNodeIdKey, &id1) || |
| 46 !second->GetInteger(content::kFrameTreeNodeIdKey, &id2)) { |
| 47 return false; |
| 48 } |
| 49 if (id1 != id2) |
| 50 return false; |
| 51 |
| 52 ListValue* subtree1 = NULL; |
| 53 ListValue* subtree2 = NULL; |
| 54 bool result1 = first->GetList(content::kFrameTreeNodeSubtreeKey, &subtree1); |
| 55 bool result2 = second->GetList(content::kFrameTreeNodeSubtreeKey, &subtree2); |
| 56 if (!result1 && !result2) |
| 57 return true; |
| 58 if (!result1 || !result2) |
| 59 return false; |
| 60 |
| 61 if (subtree1->GetSize() != subtree2->GetSize()) |
| 62 return false; |
| 63 |
| 64 base::DictionaryValue* child1 = NULL; |
| 65 base::DictionaryValue* child2 = NULL; |
| 66 for (size_t i = 0; i < subtree1->GetSize(); ++i) { |
| 67 if (!subtree1->GetDictionary(i, &child1) || |
| 68 !subtree2->GetDictionary(i, &child2)) { |
| 69 return false; |
| 70 } |
| 71 if (!CompareTrees(child1, child2)) |
| 72 return false; |
| 73 } |
| 74 |
| 75 return true; |
| 76 } |
| 77 |
| 78 base::DictionaryValue* GetTree(content::RenderViewHostImpl* rvh) { |
| 79 std::string frame_tree = rvh->frame_tree(); |
| 80 EXPECT_FALSE(frame_tree.empty()); |
| 81 base::Value* v = base::JSONReader::Read(frame_tree); |
| 82 base::DictionaryValue* tree = NULL; |
| 83 EXPECT_TRUE(v->IsType(base::Value::TYPE_DICTIONARY)); |
| 84 EXPECT_TRUE(v->GetAsDictionary(&tree)); |
| 85 return tree; |
| 86 } |
| 87 |
| 88 } // namespace |
| 89 |
30 namespace content { | 90 namespace content { |
31 | 91 |
32 class RenderViewHostManagerTest : public ContentBrowserTest { | 92 class RenderViewHostManagerTest : public ContentBrowserTest { |
33 public: | 93 public: |
34 RenderViewHostManagerTest() {} | 94 RenderViewHostManagerTest() {} |
35 | 95 |
36 static bool GetFilePathWithHostAndPortReplacement( | 96 static bool GetFilePathWithHostAndPortReplacement( |
37 const std::string& original_file_path, | 97 const std::string& original_file_path, |
38 const net::HostPortPair& host_port_pair, | 98 const net::HostPortPair& host_port_pair, |
39 std::string* replacement_path) { | 99 std::string* replacement_path) { |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
395 close_observer.Wait(); | 455 close_observer.Wait(); |
396 } | 456 } |
397 | 457 |
398 // Test for crbug.com/99202. PostMessage calls should still work after | 458 // Test for crbug.com/99202. PostMessage calls should still work after |
399 // navigating the source and target windows to different sites. | 459 // navigating the source and target windows to different sites. |
400 // Specifically: | 460 // Specifically: |
401 // 1) Create 3 windows (opener, "foo", and _blank) and send "foo" cross-process. | 461 // 1) Create 3 windows (opener, "foo", and _blank) and send "foo" cross-process. |
402 // 2) Fail to post a message from "foo" to opener with the wrong target origin. | 462 // 2) Fail to post a message from "foo" to opener with the wrong target origin. |
403 // 3) Post a message from "foo" to opener, which replies back to "foo". | 463 // 3) Post a message from "foo" to opener, which replies back to "foo". |
404 // 4) Post a message from _blank to "foo". | 464 // 4) Post a message from _blank to "foo". |
| 465 // 5) Post a message from "foo" to a subframe of opener, which replies back. |
| 466 // 6) Post a message from _blank to a subframe of "foo". |
405 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, | 467 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, |
406 SupportCrossProcessPostMessage) { | 468 SupportCrossProcessPostMessage) { |
407 // Start two servers with different sites. | 469 // Start two servers with different sites. |
408 ASSERT_TRUE(test_server()->Start()); | 470 ASSERT_TRUE(test_server()->Start()); |
409 net::TestServer https_server( | 471 net::TestServer https_server( |
410 net::TestServer::TYPE_HTTPS, | 472 net::TestServer::TYPE_HTTPS, |
411 net::TestServer::kLocalhost, | 473 net::TestServer::kLocalhost, |
412 FilePath(FILE_PATH_LITERAL("content/test/data"))); | 474 FilePath(FILE_PATH_LITERAL("content/test/data"))); |
413 ASSERT_TRUE(https_server.Start()); | 475 ASSERT_TRUE(https_server.Start()); |
414 | 476 |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
479 | 541 |
480 // 2) Fail to post a message from the foo window to the opener if the target | 542 // 2) Fail to post a message from the foo window to the opener if the target |
481 // origin is wrong. We won't see an error, but we can check for the right | 543 // origin is wrong. We won't see an error, but we can check for the right |
482 // number of received messages below. | 544 // number of received messages below. |
483 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( | 545 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( |
484 foo_contents->GetRenderViewHost(), L"", | 546 foo_contents->GetRenderViewHost(), L"", |
485 L"window.domAutomationController.send(postToOpener('msg'," | 547 L"window.domAutomationController.send(postToOpener('msg'," |
486 L"'http://google.com'));", | 548 L"'http://google.com'));", |
487 &success)); | 549 &success)); |
488 EXPECT_TRUE(success); | 550 EXPECT_TRUE(success); |
| 551 ASSERT_FALSE(opener_manager->GetSwappedOutRenderViewHost(orig_site_instance)); |
489 | 552 |
490 // 3) Post a message from the foo window to the opener. The opener will | 553 // 3) Post a message from the foo window to the opener. The opener will |
491 // reply, causing the foo window to update its own title. | 554 // reply, causing the foo window to update its own title. |
492 WindowedNotificationObserver title_observer( | 555 WindowedNotificationObserver title_observer( |
493 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, | 556 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, |
494 Source<WebContents>(foo_contents)); | 557 Source<WebContents>(foo_contents)); |
495 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( | 558 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( |
496 foo_contents->GetRenderViewHost(), L"", | 559 foo_contents->GetRenderViewHost(), L"", |
497 L"window.domAutomationController.send(postToOpener('msg','*'));", | 560 L"window.domAutomationController.send(postToOpener('msg','*'));", |
498 &success)); | 561 &success)); |
499 EXPECT_TRUE(success); | 562 EXPECT_TRUE(success); |
| 563 ASSERT_FALSE(opener_manager->GetSwappedOutRenderViewHost(orig_site_instance)); |
500 title_observer.Wait(); | 564 title_observer.Wait(); |
501 | 565 |
502 // We should have received only 1 message in the opener and "foo" tabs, | 566 // We should have received only 1 message in the opener and "foo" tabs, |
503 // and updated the title. | 567 // and updated the title. |
504 int opener_received_messages = 0; | 568 int opener_received_messages = 0; |
505 EXPECT_TRUE(ExecuteJavaScriptAndExtractInt( | 569 EXPECT_TRUE(ExecuteJavaScriptAndExtractInt( |
506 opener_contents->GetRenderViewHost(), L"", | 570 opener_contents->GetRenderViewHost(), L"", |
507 L"window.domAutomationController.send(window.receivedMessages);", | 571 L"window.domAutomationController.send(window.receivedMessages);", |
508 &opener_received_messages)); | 572 &opener_received_messages)); |
509 int foo_received_messages = 0; | 573 int foo_received_messages = 0; |
(...skipping 14 matching lines...) Expand all Loading... |
524 new_contents->GetRenderViewHost(), L"", | 588 new_contents->GetRenderViewHost(), L"", |
525 L"window.domAutomationController.send(postToFoo('msg2'));", | 589 L"window.domAutomationController.send(postToFoo('msg2'));", |
526 &success)); | 590 &success)); |
527 EXPECT_TRUE(success); | 591 EXPECT_TRUE(success); |
528 title_observer2.Wait(); | 592 title_observer2.Wait(); |
529 EXPECT_EQ(ASCIIToUTF16("msg2"), foo_contents->GetTitle()); | 593 EXPECT_EQ(ASCIIToUTF16("msg2"), foo_contents->GetTitle()); |
530 | 594 |
531 // This postMessage should have created a swapped out RVH for the new | 595 // This postMessage should have created a swapped out RVH for the new |
532 // SiteInstance in the target=_blank window. | 596 // SiteInstance in the target=_blank window. |
533 EXPECT_TRUE(new_manager->GetSwappedOutRenderViewHost(foo_site_instance)); | 597 EXPECT_TRUE(new_manager->GetSwappedOutRenderViewHost(foo_site_instance)); |
| 598 |
| 599 NavigateToURL(new_shell, https_server.GetURL("files/post_message2.html")); |
| 600 |
| 601 // 5) Now verify that posting a message from the foo window to a subframe of |
| 602 // the opener window works fine. The opener subframe will reply, causing the |
| 603 // foo window to update its own title. |
| 604 WindowedNotificationObserver title_observer3( |
| 605 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, |
| 606 Source<WebContents>(new_shell->web_contents())); |
| 607 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( |
| 608 foo_contents->GetRenderViewHost(), L"", |
| 609 L"window.domAutomationController.send(postToOpenerFrame('msg3','*'));", |
| 610 &success)); |
| 611 EXPECT_TRUE(success); |
| 612 title_observer3.Wait(); |
| 613 EXPECT_EQ(ASCIIToUTF16("msg3"), new_shell->web_contents()->GetTitle()); |
| 614 |
| 615 // 6) Lastly, verify that the _blank window can post a message to a subframe |
| 616 // of the foo window. The subframe of foo will set the foo window title and |
| 617 // will reply, setting the _blank window title. |
| 618 WindowedNotificationObserver title_observer4( |
| 619 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, |
| 620 Source<WebContents>(new_shell2->web_contents())); |
| 621 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( |
| 622 new_contents->GetRenderViewHost(), L"", |
| 623 L"window.domAutomationController.send(postToFooFrame('msg4'));", |
| 624 &success)); |
| 625 EXPECT_TRUE(success); |
| 626 title_observer4.Wait(); |
| 627 EXPECT_EQ(ASCIIToUTF16("msg4"), new_shell2->web_contents()->GetTitle()); |
534 } | 628 } |
535 | 629 |
536 // Test for crbug.com/116192. Navigations to a window's opener should | 630 // Test for crbug.com/116192. Navigations to a window's opener should |
537 // still work after a process swap. | 631 // still work after a process swap. |
538 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, | 632 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, |
539 AllowTargetedNavigationsInOpenerAfterSwap) { | 633 AllowTargetedNavigationsInOpenerAfterSwap) { |
540 // Start two servers with different sites. | 634 // Start two servers with different sites. |
541 ASSERT_TRUE(test_server()->Start()); | 635 ASSERT_TRUE(test_server()->Start()); |
542 net::TestServer https_server( | 636 net::TestServer https_server( |
543 net::TestServer::TYPE_HTTPS, | 637 net::TestServer::TYPE_HTTPS, |
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1032 rvh_observers.AddObserverToRVH(shell()->web_contents()->GetRenderViewHost()); | 1126 rvh_observers.AddObserverToRVH(shell()->web_contents()->GetRenderViewHost()); |
1033 | 1127 |
1034 // This used to leak a render view host. | 1128 // This used to leak a render view host. |
1035 shell()->Close(); | 1129 shell()->Close(); |
1036 | 1130 |
1037 RunAllPendingInMessageLoop(); // Needed on ChromeOS. | 1131 RunAllPendingInMessageLoop(); // Needed on ChromeOS. |
1038 | 1132 |
1039 EXPECT_EQ(0U, rvh_observers.GetNumObservers()); | 1133 EXPECT_EQ(0U, rvh_observers.GetNumObservers()); |
1040 } | 1134 } |
1041 | 1135 |
| 1136 // Test for correct propagation of the frame hierarchy across processes in the |
| 1137 // same BrowsingInstance. The test starts by navigating to a page that has |
| 1138 // multiple nested frames. It then opens two windows and navigates each one |
| 1139 // to a separate site, so at the end we have 3 SiteInstances. The opened |
| 1140 // windows have swapped out RenderViews corresponding to the opener, so those |
| 1141 // swapped out views must have a matching frame hierarchy. The test checks |
| 1142 // that frame hierarchies are kept in sync through navigations, reloading, and |
| 1143 // JavaScript manipulation of the frame tree. |
| 1144 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, FrameTreeUpdates) { |
| 1145 // Start two servers to allow using different sites. |
| 1146 EXPECT_TRUE(test_server()->Start()); |
| 1147 net::TestServer https_server( |
| 1148 net::TestServer::TYPE_HTTPS, |
| 1149 net::TestServer::kLocalhost, |
| 1150 FilePath(FILE_PATH_LITERAL("content/test/data"))); |
| 1151 EXPECT_TRUE(https_server.Start()); |
| 1152 |
| 1153 GURL frame_tree_url(test_server()->GetURL("files/frame_tree/top.html")); |
| 1154 |
| 1155 // Replace the 127.0.0.1 with localhost, which will give us a different |
| 1156 // site instance. |
| 1157 GURL::Replacements replacements; |
| 1158 std::string new_host("localhost"); |
| 1159 replacements.SetHostStr(new_host); |
| 1160 GURL remote_frame = test_server()->GetURL( |
| 1161 "files/frame_tree/1-1.html").ReplaceComponents(replacements); |
| 1162 |
| 1163 bool success = false; |
| 1164 base::DictionaryValue* frames = NULL; |
| 1165 base::ListValue* subtree = NULL; |
| 1166 |
| 1167 // First navigate to a page with no frames and ensure the frame tree has no |
| 1168 // subtrees. |
| 1169 NavigateToURL(shell(), test_server()->GetURL("files/simple_page.html")); |
| 1170 WebContents* opener_contents = shell()->web_contents(); |
| 1171 RenderViewHostManager* opener_rvhm = static_cast<WebContentsImpl*>( |
| 1172 opener_contents)->GetRenderManagerForTesting(); |
| 1173 frames = GetTree(opener_rvhm->current_host()); |
| 1174 EXPECT_FALSE(frames->GetList(content::kFrameTreeNodeSubtreeKey, &subtree)); |
| 1175 |
| 1176 NavigateToURL(shell(), frame_tree_url); |
| 1177 frames = GetTree(opener_rvhm->current_host()); |
| 1178 EXPECT_TRUE(frames->GetList(content::kFrameTreeNodeSubtreeKey, &subtree)); |
| 1179 EXPECT_TRUE(subtree->GetSize() == 3); |
| 1180 |
| 1181 scoped_refptr<SiteInstance> orig_site_instance( |
| 1182 opener_contents->GetSiteInstance()); |
| 1183 EXPECT_TRUE(orig_site_instance != NULL); |
| 1184 |
| 1185 ShellAddedObserver shell_observer1; |
| 1186 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( |
| 1187 opener_contents->GetRenderViewHost(), L"", |
| 1188 L"window.domAutomationController.send(openWindow('1-3.html'));", |
| 1189 &success)); |
| 1190 EXPECT_TRUE(success); |
| 1191 |
| 1192 Shell* shell1 = shell_observer1.GetShell(); |
| 1193 WebContents* contents1 = shell1->web_contents(); |
| 1194 WaitForLoadStop(contents1); |
| 1195 RenderViewHostManager* rvhm1 = static_cast<WebContentsImpl*>( |
| 1196 contents1)->GetRenderManagerForTesting(); |
| 1197 EXPECT_EQ("/files/frame_tree/1-3.html", contents1->GetURL().path()); |
| 1198 |
| 1199 // Now navigate the new window to a different SiteInstance. |
| 1200 NavigateToURL(shell1, https_server.GetURL("files/title1.html")); |
| 1201 EXPECT_EQ("/files/title1.html", contents1->GetURL().path()); |
| 1202 scoped_refptr<SiteInstance> site_instance1( |
| 1203 contents1->GetSiteInstance()); |
| 1204 EXPECT_NE(orig_site_instance, site_instance1); |
| 1205 |
| 1206 ShellAddedObserver shell_observer2; |
| 1207 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( |
| 1208 opener_contents->GetRenderViewHost(), L"", |
| 1209 L"window.domAutomationController.send(openWindow('../title2.html'));", |
| 1210 &success)); |
| 1211 EXPECT_TRUE(success); |
| 1212 |
| 1213 Shell* shell2 = shell_observer2.GetShell(); |
| 1214 WebContents* contents2 = shell2->web_contents(); |
| 1215 WaitForLoadStop(contents2); |
| 1216 EXPECT_EQ("/files/title2.html", contents2->GetURL().path()); |
| 1217 |
| 1218 // Navigate the second new window to a different SiteInstance as well. |
| 1219 NavigateToURL(shell2, remote_frame); |
| 1220 EXPECT_EQ("/files/frame_tree/1-1.html", contents2->GetURL().path()); |
| 1221 scoped_refptr<SiteInstance> site_instance2( |
| 1222 contents2->GetSiteInstance()); |
| 1223 EXPECT_NE(orig_site_instance, site_instance2); |
| 1224 EXPECT_NE(site_instance1, site_instance2); |
| 1225 |
| 1226 RenderViewHostManager* rvhm2 = static_cast<WebContentsImpl*>( |
| 1227 contents2)->GetRenderManagerForTesting(); |
| 1228 |
| 1229 EXPECT_TRUE(CompareTrees( |
| 1230 GetTree(opener_rvhm->current_host()), |
| 1231 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance1)))); |
| 1232 EXPECT_TRUE(CompareTrees( |
| 1233 GetTree(opener_rvhm->current_host()), |
| 1234 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance2)))); |
| 1235 |
| 1236 EXPECT_TRUE(CompareTrees( |
| 1237 GetTree(rvhm1->current_host()), |
| 1238 GetTree(rvhm1->GetSwappedOutRenderViewHost(orig_site_instance)))); |
| 1239 EXPECT_TRUE(CompareTrees( |
| 1240 GetTree(rvhm2->current_host()), |
| 1241 GetTree(rvhm2->GetSwappedOutRenderViewHost(orig_site_instance)))); |
| 1242 |
| 1243 // Verify that the frame trees from different windows aren't equal. |
| 1244 EXPECT_FALSE(CompareTrees( |
| 1245 GetTree(opener_rvhm->current_host()), GetTree(rvhm1->current_host()))); |
| 1246 EXPECT_FALSE(CompareTrees( |
| 1247 GetTree(opener_rvhm->current_host()), GetTree(rvhm2->current_host()))); |
| 1248 |
| 1249 // Reload the original page, which will cause subframe ids to change. This |
| 1250 // will ensure that the ids are properly replicated across reload. |
| 1251 NavigateToURL(shell(), frame_tree_url); |
| 1252 |
| 1253 EXPECT_TRUE(CompareTrees( |
| 1254 GetTree(opener_rvhm->current_host()), |
| 1255 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance1)))); |
| 1256 EXPECT_TRUE(CompareTrees( |
| 1257 GetTree(opener_rvhm->current_host()), |
| 1258 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance2)))); |
| 1259 |
| 1260 EXPECT_FALSE(CompareTrees( |
| 1261 GetTree(opener_rvhm->current_host()), GetTree(rvhm1->current_host()))); |
| 1262 EXPECT_FALSE(CompareTrees( |
| 1263 GetTree(opener_rvhm->current_host()), GetTree(rvhm2->current_host()))); |
| 1264 |
| 1265 // Now let's ensure that using JS to add/remove frames results in proper |
| 1266 // updates. |
| 1267 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( |
| 1268 opener_contents->GetRenderViewHost(), L"", |
| 1269 L"window.domAutomationController.send(removeFrame());", |
| 1270 &success)); |
| 1271 EXPECT_TRUE(success); |
| 1272 frames = GetTree(opener_rvhm->current_host()); |
| 1273 EXPECT_TRUE(frames->GetList(content::kFrameTreeNodeSubtreeKey, &subtree)); |
| 1274 EXPECT_EQ(subtree->GetSize(), 2U); |
| 1275 |
| 1276 // Create a load observer for the iframe that will be created by the |
| 1277 // JavaScript code we will execute. |
| 1278 WindowedNotificationObserver load_observer( |
| 1279 NOTIFICATION_LOAD_STOP, |
| 1280 content::Source<NavigationController>( |
| 1281 &opener_contents->GetController())); |
| 1282 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( |
| 1283 opener_contents->GetRenderViewHost(), L"", |
| 1284 L"window.domAutomationController.send(addFrame());", |
| 1285 &success)); |
| 1286 EXPECT_TRUE(success); |
| 1287 load_observer.Wait(); |
| 1288 |
| 1289 frames = GetTree(opener_rvhm->current_host()); |
| 1290 EXPECT_TRUE(frames->GetList(content::kFrameTreeNodeSubtreeKey, &subtree)); |
| 1291 EXPECT_EQ(subtree->GetSize(), 3U); |
| 1292 |
| 1293 EXPECT_TRUE(CompareTrees( |
| 1294 GetTree(opener_rvhm->current_host()), |
| 1295 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance1)))); |
| 1296 EXPECT_TRUE(CompareTrees( |
| 1297 GetTree(opener_rvhm->current_host()), |
| 1298 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(site_instance2)))); |
| 1299 } |
| 1300 |
1042 } // namespace content | 1301 } // namespace content |
OLD | NEW |