| 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 |