Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(237)

Side by Side Diff: content/browser/renderer_host/render_view_host_manager_browsertest.cc

Issue 10827078: Support frame tree propagation between renderers in the same browsing instance. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Moved away from hardcoded strings and no static cast needed for tests. Created 8 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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/string_constants.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"
(...skipping 460 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 481
480 // 2) Fail to post a message from the foo window to the opener if the target 482 // 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 483 // origin is wrong. We won't see an error, but we can check for the right
482 // number of received messages below. 484 // number of received messages below.
483 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( 485 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool(
484 foo_contents->GetRenderViewHost(), L"", 486 foo_contents->GetRenderViewHost(), L"",
485 L"window.domAutomationController.send(postToOpener('msg'," 487 L"window.domAutomationController.send(postToOpener('msg',"
486 L"'http://google.com'));", 488 L"'http://google.com'));",
487 &success)); 489 &success));
488 EXPECT_TRUE(success); 490 EXPECT_TRUE(success);
491 ASSERT_FALSE(opener_manager->GetSwappedOutRenderViewHost(orig_site_instance));
489 492
490 // 3) Post a message from the foo window to the opener. The opener will 493 // 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. 494 // reply, causing the foo window to update its own title.
492 WindowedNotificationObserver title_observer( 495 WindowedNotificationObserver title_observer(
493 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED, 496 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
494 Source<WebContents>(foo_contents)); 497 Source<WebContents>(foo_contents));
495 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool( 498 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool(
496 foo_contents->GetRenderViewHost(), L"", 499 foo_contents->GetRenderViewHost(), L"",
497 L"window.domAutomationController.send(postToOpener('msg','*'));", 500 L"window.domAutomationController.send(postToOpener('msg','*'));",
498 &success)); 501 &success));
499 EXPECT_TRUE(success); 502 EXPECT_TRUE(success);
503 ASSERT_FALSE(opener_manager->GetSwappedOutRenderViewHost(orig_site_instance));
500 title_observer.Wait(); 504 title_observer.Wait();
501 505
502 // We should have received only 1 message in the opener and "foo" tabs, 506 // We should have received only 1 message in the opener and "foo" tabs,
503 // and updated the title. 507 // and updated the title.
504 int opener_received_messages = 0; 508 int opener_received_messages = 0;
505 EXPECT_TRUE(ExecuteJavaScriptAndExtractInt( 509 EXPECT_TRUE(ExecuteJavaScriptAndExtractInt(
506 opener_contents->GetRenderViewHost(), L"", 510 opener_contents->GetRenderViewHost(), L"",
507 L"window.domAutomationController.send(window.receivedMessages);", 511 L"window.domAutomationController.send(window.receivedMessages);",
508 &opener_received_messages)); 512 &opener_received_messages));
509 int foo_received_messages = 0; 513 int foo_received_messages = 0;
(...skipping 14 matching lines...) Expand all
524 new_contents->GetRenderViewHost(), L"", 528 new_contents->GetRenderViewHost(), L"",
525 L"window.domAutomationController.send(postToFoo('msg2'));", 529 L"window.domAutomationController.send(postToFoo('msg2'));",
526 &success)); 530 &success));
527 EXPECT_TRUE(success); 531 EXPECT_TRUE(success);
528 title_observer2.Wait(); 532 title_observer2.Wait();
529 EXPECT_EQ(ASCIIToUTF16("msg2"), foo_contents->GetTitle()); 533 EXPECT_EQ(ASCIIToUTF16("msg2"), foo_contents->GetTitle());
530 534
531 // This postMessage should have created a swapped out RVH for the new 535 // This postMessage should have created a swapped out RVH for the new
532 // SiteInstance in the target=_blank window. 536 // SiteInstance in the target=_blank window.
533 EXPECT_TRUE(new_manager->GetSwappedOutRenderViewHost(foo_site_instance)); 537 EXPECT_TRUE(new_manager->GetSwappedOutRenderViewHost(foo_site_instance));
538
539 NavigateToURL(new_shell, https_server.GetURL("files/post_message2.html"));
540
541 // 5) Now verify that posting a message from the foo window to a subframe of
542 // the opener window works fine. The opener subframe will reply, causing the
543 // foo window to update its own title.
544 WindowedNotificationObserver title_observer3(
545 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
546 Source<WebContents>(new_shell->web_contents()));
547 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool(
548 foo_contents->GetRenderViewHost(), L"",
549 L"window.domAutomationController.send(postToOpenerFrame('msg3','*'));",
550 &success));
551 EXPECT_TRUE(success);
552 title_observer3.Wait();
553 EXPECT_EQ(ASCIIToUTF16("msg3"), new_shell->web_contents()->GetTitle());
554
555 // 5) Lastly, verify that the _blank window can post a message to subframe
556 // of the foo window. The subframe of foo will set the foo window title and
557 // will reply, setting the _blank window title.
558 WindowedNotificationObserver title_observer4(
559 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
560 Source<WebContents>(new_shell2->web_contents()));
561 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool(
562 new_contents->GetRenderViewHost(), L"",
563 L"window.domAutomationController.send(postToFooFrame('msg4'));",
564 &success));
565 EXPECT_TRUE(success);
566 title_observer4.Wait();
567 EXPECT_EQ(ASCIIToUTF16("msg4"), new_shell2->web_contents()->GetTitle());
534 } 568 }
535 569
536 // Test for crbug.com/116192. Navigations to a window's opener should 570 // Test for crbug.com/116192. Navigations to a window's opener should
537 // still work after a process swap. 571 // still work after a process swap.
538 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, 572 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest,
539 AllowTargetedNavigationsInOpenerAfterSwap) { 573 AllowTargetedNavigationsInOpenerAfterSwap) {
540 // Start two servers with different sites. 574 // Start two servers with different sites.
541 ASSERT_TRUE(test_server()->Start()); 575 ASSERT_TRUE(test_server()->Start());
542 net::TestServer https_server( 576 net::TestServer https_server(
543 net::TestServer::TYPE_HTTPS, 577 net::TestServer::TYPE_HTTPS,
(...skipping 488 matching lines...) Expand 10 before | Expand all | Expand 10 after
1032 rvh_observers.AddObserverToRVH(shell()->web_contents()->GetRenderViewHost()); 1066 rvh_observers.AddObserverToRVH(shell()->web_contents()->GetRenderViewHost());
1033 1067
1034 // This used to leak a render view host. 1068 // This used to leak a render view host.
1035 shell()->Close(); 1069 shell()->Close();
1036 1070
1037 RunAllPendingInMessageLoop(); // Needed on ChromeOS. 1071 RunAllPendingInMessageLoop(); // Needed on ChromeOS.
1038 1072
1039 EXPECT_EQ(0U, rvh_observers.GetNumObservers()); 1073 EXPECT_EQ(0U, rvh_observers.GetNumObservers());
1040 } 1074 }
1041 1075
1076 namespace {
awong 2012/08/21 19:27:28 Anonymous namespaces should go at the top of the f
nasko 2012/08/21 22:24:13 Done.
1077
1078 bool CompareTrees(base::DictionaryValue* first, base::DictionaryValue* second) {
1079 string16 name1;
1080 string16 name2;
1081 if (!first->GetString(content::kFrameTreeNodeNameKey, &name1) ||
1082 !second->GetString(content::kFrameTreeNodeNameKey, &name2))
1083 return false;
1084 if (name1 != name2)
1085 return false;
1086
1087 int id1 = 0;
1088 int id2 = 0;
1089 if (!first->GetInteger(content::kFrameTreeNodeIdKey, &id1) ||
1090 !second->GetInteger(content::kFrameTreeNodeIdKey, &id2))
1091 return false;
1092 if (id1 != id2)
1093 return false;
1094
1095 ListValue* subtree1 = NULL;
1096 ListValue* subtree2 = NULL;
1097 bool result1 = first->GetList(content::kFrameTreeNodeSubtreeKey, &subtree1);
1098 bool result2 = second->GetList(content::kFrameTreeNodeSubtreeKey, &subtree2);
1099 if (!result1 && !result2)
1100 return true;
1101 if (!result1 || !result2)
1102 return false;
1103
1104 if (subtree1->GetSize() != subtree2->GetSize())
1105 return false;
1106
1107 base::DictionaryValue* child1 = NULL;
1108 base::DictionaryValue* child2 = NULL;
1109 for (size_t i = 0; i < subtree1->GetSize(); ++i) {
1110 if (!subtree1->GetDictionary(i, &child1) ||
1111 !subtree2->GetDictionary(i, &child2))
1112 return false;
1113 if (!CompareTrees(child1, child2))
1114 return false;
1115 }
1116
1117 return true;
1118 }
1119
1120 base::DictionaryValue* GetTree(RenderViewHostImpl* rvh) {
1121 std::string frame_tree = rvh->frame_tree();
1122 EXPECT_FALSE(frame_tree.empty());
awong 2012/08/21 19:27:28 Failing any of these EXPECTs feels like it should
1123 base::Value* v = base::JSONReader::Read(frame_tree);
1124 base::DictionaryValue* tree = NULL;
1125 EXPECT_TRUE(v->IsType(base::Value::TYPE_DICTIONARY));
1126 EXPECT_TRUE(v->GetAsDictionary(&tree));
1127 return tree;
1128 }
1129
1130 } // namespace
1131
1132 // Test for correct propagation of frames hierarchy across processes in the
1133 // same browsing context.
awong 2012/08/21 19:27:28 Can we add a few brief sentences describing the ba
nasko 2012/08/21 22:24:13 Done.
1134 IN_PROC_BROWSER_TEST_F(RenderViewHostManagerTest, FrameTreeUpdates) {
1135 // Start two servers to allow using different sites.
1136 EXPECT_TRUE(test_server()->Start());
1137 net::TestServer https_server(
1138 net::TestServer::TYPE_HTTPS,
1139 net::TestServer::kLocalhost,
1140 FilePath(FILE_PATH_LITERAL("content/test/data")));
1141 EXPECT_TRUE(https_server.Start());
1142
1143 GURL frame_tree_url(test_server()->GetURL("files/frame_tree/top.html"));
1144
1145 // Replace the 127.0.0.1 with localhost, which will give us a different
1146 // site instance.
1147 GURL::Replacements replacements;
1148 std::string new_host("localhost");
1149 replacements.SetHostStr(new_host);
1150 GURL remote_frame = test_server()->GetURL(
1151 "files/frame_tree/1-1.html").ReplaceComponents(replacements);
1152
1153 bool success = false;
1154 base::DictionaryValue* frames = NULL;
1155 base::ListValue* subtree = NULL;
1156
1157 NavigateToURL(shell(), test_server()->GetURL("files/simple_page.html"));
1158 WebContents* opener_contents = shell()->web_contents();
1159 RenderViewHostManager* opener_rvhm = static_cast<WebContentsImpl*>(
1160 opener_contents)->GetRenderManagerForTesting();
1161 frames = GetTree(opener_rvhm->current_host());
1162 EXPECT_FALSE(frames->GetList(content::kFrameTreeNodeSubtreeKey, &subtree));
1163
1164 NavigateToURL(shell(), frame_tree_url);
1165 frames = GetTree(opener_rvhm->current_host());
1166 EXPECT_TRUE(frames->GetList(content::kFrameTreeNodeSubtreeKey, &subtree));
1167 EXPECT_TRUE(subtree->GetSize() == 3);
1168
1169 scoped_refptr<SiteInstance> orig_site_instance(
1170 opener_contents->GetSiteInstance());
1171 EXPECT_TRUE(orig_site_instance != NULL);
1172
1173 ShellAddedObserver shell_observer1;
1174 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool(
1175 opener_contents->GetRenderViewHost(), L"",
1176 L"window.domAutomationController.send(openWindow('1-3.html'));",
1177 &success));
1178 EXPECT_TRUE(success);
1179
1180 Shell* shell1 = shell_observer1.GetShell();
1181 WebContents* contents1 = shell1->web_contents();
1182 WaitForLoadStop(contents1);
1183 RenderViewHostManager* rvhm1 = static_cast<WebContentsImpl*>(
1184 contents1)->GetRenderManagerForTesting();
1185 EXPECT_EQ("/files/frame_tree/1-3.html", contents1->GetURL().path());
1186
1187 NavigateToURL(shell1, https_server.GetURL("files/title1.html"));
1188 EXPECT_EQ("/files/title1.html", contents1->GetURL().path());
1189 scoped_refptr<SiteInstance> site_instance1(
1190 contents1->GetSiteInstance());
1191 EXPECT_NE(orig_site_instance, site_instance1);
1192
1193 ShellAddedObserver shell_observer2;
1194 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool(
1195 opener_contents->GetRenderViewHost(), L"",
1196 L"window.domAutomationController.send(openWindow('../title2.html'));",
1197 &success));
1198 EXPECT_TRUE(success);
1199
1200 Shell* shell2 = shell_observer2.GetShell();
1201 WebContents* contents2 = shell2->web_contents();
1202 WaitForLoadStop(contents2);
1203 EXPECT_EQ("/files/title2.html", contents2->GetURL().path());
1204
1205 NavigateToURL(shell2, remote_frame);
1206 EXPECT_EQ("/files/frame_tree/1-1.html", contents2->GetURL().path());
1207 scoped_refptr<SiteInstance> site_instance2(
1208 contents2->GetSiteInstance());
1209 EXPECT_NE(orig_site_instance, site_instance2);
1210 EXPECT_NE(site_instance1, site_instance2);
1211
1212 RenderViewHostManager* rvhm2 = static_cast<WebContentsImpl*>(
1213 contents2)->GetRenderManagerForTesting();
1214
1215 EXPECT_TRUE(CompareTrees(
1216 GetTree(opener_rvhm->current_host()),
1217 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(
1218 rvhm1->current_host()->GetSiteInstance()))));
1219 EXPECT_TRUE(CompareTrees(
1220 GetTree(opener_rvhm->current_host()),
1221 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(
1222 rvhm2->current_host()->GetSiteInstance()))));
1223
1224 EXPECT_TRUE(CompareTrees(
1225 GetTree(rvhm1->current_host()),
1226 GetTree(rvhm1->GetSwappedOutRenderViewHost(
1227 opener_rvhm->current_host()->GetSiteInstance()))));
1228 EXPECT_TRUE(CompareTrees(
1229 GetTree(rvhm2->current_host()),
1230 GetTree(rvhm2->GetSwappedOutRenderViewHost(
1231 opener_rvhm->current_host()->GetSiteInstance()))));
1232
1233 EXPECT_FALSE(CompareTrees(
1234 GetTree(opener_rvhm->current_host()), GetTree(rvhm1->current_host())));
1235 EXPECT_FALSE(CompareTrees(
1236 GetTree(opener_rvhm->current_host()), GetTree(rvhm2->current_host())));
1237
1238 // Reload the original page, which will cause subframe ids to change. This
1239 // will ensure that the ids are properly replicated across reload.
1240 NavigateToURL(shell(), frame_tree_url);
1241
1242 EXPECT_TRUE(CompareTrees(
1243 GetTree(opener_rvhm->current_host()),
1244 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(
1245 rvhm1->current_host()->GetSiteInstance()))));
1246 EXPECT_TRUE(CompareTrees(
1247 GetTree(opener_rvhm->current_host()),
1248 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(
1249 rvhm2->current_host()->GetSiteInstance()))));
1250
1251 EXPECT_FALSE(CompareTrees(
1252 GetTree(opener_rvhm->current_host()), GetTree(rvhm1->current_host())));
1253 EXPECT_FALSE(CompareTrees(
1254 GetTree(opener_rvhm->current_host()), GetTree(rvhm2->current_host())));
1255
1256 // Now let's ensure that using JS to add/remove frames results in proper
1257 // updates.
1258 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool(
1259 opener_contents->GetRenderViewHost(), L"",
1260 L"window.domAutomationController.send(removeFrame());",
1261 &success));
1262 EXPECT_TRUE(success);
1263 frames = GetTree(opener_rvhm->current_host());
1264 EXPECT_TRUE(frames->GetList(content::kFrameTreeNodeSubtreeKey, &subtree));
1265 EXPECT_TRUE(subtree->GetSize() == 2);
1266
1267 WindowedNotificationObserver title_observer(
1268 NOTIFICATION_WEB_CONTENTS_TITLE_UPDATED,
1269 Source<WebContents>(opener_contents));
1270 EXPECT_TRUE(ExecuteJavaScriptAndExtractBool(
1271 opener_contents->GetRenderViewHost(), L"",
1272 L"window.domAutomationController.send(addFrame());",
1273 &success));
1274 EXPECT_TRUE(success);
1275 title_observer.Wait();
1276
1277 frames = GetTree(opener_rvhm->current_host());
1278 EXPECT_TRUE(frames->GetList(content::kFrameTreeNodeSubtreeKey, &subtree));
1279 EXPECT_TRUE(subtree->GetSize() == 3);
1280
1281 EXPECT_TRUE(CompareTrees(
1282 GetTree(opener_rvhm->current_host()),
1283 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(
1284 rvhm1->current_host()->GetSiteInstance()))));
1285 EXPECT_TRUE(CompareTrees(
1286 GetTree(opener_rvhm->current_host()),
1287 GetTree(opener_rvhm->GetSwappedOutRenderViewHost(
1288 rvhm2->current_host()->GetSiteInstance()))));
1289 }
1290
1042 } // namespace content 1291 } // namespace content
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698