| 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 <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 17 matching lines...) Expand all Loading... |
| 28 #include "content/public/test/test_utils.h" | 28 #include "content/public/test/test_utils.h" |
| 29 #include "content/shell/browser/shell.h" | 29 #include "content/shell/browser/shell.h" |
| 30 #include "content/test/content_browser_test_utils_internal.h" | 30 #include "content/test/content_browser_test_utils_internal.h" |
| 31 #include "content/test/test_frame_navigation_observer.h" | 31 #include "content/test/test_frame_navigation_observer.h" |
| 32 #include "ipc/ipc_security_test_util.h" | 32 #include "ipc/ipc_security_test_util.h" |
| 33 #include "net/dns/mock_host_resolver.h" | 33 #include "net/dns/mock_host_resolver.h" |
| 34 #include "net/test/embedded_test_server/embedded_test_server.h" | 34 #include "net/test/embedded_test_server/embedded_test_server.h" |
| 35 | 35 |
| 36 namespace content { | 36 namespace content { |
| 37 | 37 |
| 38 namespace { |
| 39 |
| 40 // Helper function to send a postMessage and wait for a reply message. The |
| 41 // |post_message_script| is executed on the |sender_ftn| frame, and the sender |
| 42 // frame is expected to post |reply_status| from the DOMAutomationController |
| 43 // when it receives a reply. |
| 44 void PostMessageAndWaitForReply(FrameTreeNode* sender_ftn, |
| 45 const std::string& post_message_script, |
| 46 const std::string& reply_status) { |
| 47 bool success = false; |
| 48 EXPECT_TRUE(ExecuteScriptAndExtractBool( |
| 49 sender_ftn->current_frame_host(), |
| 50 "window.domAutomationController.send(" + post_message_script + ");", |
| 51 &success)); |
| 52 EXPECT_TRUE(success); |
| 53 |
| 54 content::DOMMessageQueue msg_queue; |
| 55 std::string status; |
| 56 while (msg_queue.WaitForMessage(&status)) { |
| 57 if (status == reply_status) |
| 58 break; |
| 59 } |
| 60 } |
| 61 |
| 62 } // anonymous namespace |
| 63 |
| 38 class RedirectNotificationObserver : public NotificationObserver { | 64 class RedirectNotificationObserver : public NotificationObserver { |
| 39 public: | 65 public: |
| 40 // Register to listen for notifications of the given type from either a | 66 // Register to listen for notifications of the given type from either a |
| 41 // specific source, or from all sources if |source| is | 67 // specific source, or from all sources if |source| is |
| 42 // NotificationService::AllSources(). | 68 // NotificationService::AllSources(). |
| 43 RedirectNotificationObserver(int notification_type, | 69 RedirectNotificationObserver(int notification_type, |
| 44 const NotificationSource& source); | 70 const NotificationSource& source); |
| 45 ~RedirectNotificationObserver() override; | 71 ~RedirectNotificationObserver() override; |
| 46 | 72 |
| 47 // Wait until the specified notification occurs. If the notification was | 73 // Wait until the specified notification occurs. If the notification was |
| (...skipping 784 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 832 RenderProcessHost* child_process = | 858 RenderProcessHost* child_process = |
| 833 root->child_at(0)->current_frame_host()->GetProcess(); | 859 root->child_at(0)->current_frame_host()->GetProcess(); |
| 834 RenderProcessHostWatcher crash_observer( | 860 RenderProcessHostWatcher crash_observer( |
| 835 child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); | 861 child_process, RenderProcessHostWatcher::WATCH_FOR_PROCESS_EXIT); |
| 836 child_process->Shutdown(0, false); | 862 child_process->Shutdown(0, false); |
| 837 crash_observer.Wait(); | 863 crash_observer.Wait(); |
| 838 | 864 |
| 839 // Navigate the second subframe to b.com to recreate the b.com process. | 865 // Navigate the second subframe to b.com to recreate the b.com process. |
| 840 GURL b_url = embedded_test_server()->GetURL("b.com", "/post_message.html"); | 866 GURL b_url = embedded_test_server()->GetURL("b.com", "/post_message.html"); |
| 841 NavigateFrameToURL(root->child_at(1), b_url); | 867 NavigateFrameToURL(root->child_at(1), b_url); |
| 868 // TODO(alexmos): This can be removed once TestFrameNavigationObserver is |
| 869 // fixed to use DidFinishLoad. |
| 842 EXPECT_TRUE( | 870 EXPECT_TRUE( |
| 843 WaitForRenderFrameReady(root->child_at(1)->current_frame_host())); | 871 WaitForRenderFrameReady(root->child_at(1)->current_frame_host())); |
| 844 EXPECT_TRUE(observer.last_navigation_succeeded()); | 872 EXPECT_TRUE(observer.last_navigation_succeeded()); |
| 845 EXPECT_EQ(b_url, observer.last_navigation_url()); | 873 EXPECT_EQ(b_url, observer.last_navigation_url()); |
| 846 EXPECT_TRUE(root->child_at(1)->current_frame_host()->IsRenderFrameLive()); | 874 EXPECT_TRUE(root->child_at(1)->current_frame_host()->IsRenderFrameLive()); |
| 847 | 875 |
| 848 EXPECT_EQ( | 876 EXPECT_EQ( |
| 849 " Site A ------------ proxies for B\n" | 877 " Site A ------------ proxies for B\n" |
| 850 " |--Site B ------- proxies for A\n" | 878 " |--Site B ------- proxies for A\n" |
| 851 " |--Site B ------- proxies for A\n" | 879 " |--Site B ------- proxies for A\n" |
| 852 " +--Site A ------- proxies for B\n" | 880 " +--Site A ------- proxies for B\n" |
| 853 "Where A = http://a.com/\n" | 881 "Where A = http://a.com/\n" |
| 854 " B = http://b.com/", | 882 " B = http://b.com/", |
| 855 DepictFrameTree(root)); | 883 DepictFrameTree(root)); |
| 856 | 884 |
| 857 // Check that third subframe's proxy is available in the b.com process by | 885 // Check that third subframe's proxy is available in the b.com process by |
| 858 // sending it a postMessage from second subframe. | 886 // sending it a postMessage from second subframe, and waiting for a reply. |
| 859 bool success = false; | 887 PostMessageAndWaitForReply(root->child_at(1), |
| 860 EXPECT_TRUE(ExecuteScriptAndExtractBool( | 888 "postToSibling('subframe-msg','frame3')", |
| 861 root->child_at(1)->current_frame_host(), | 889 "\"done-frame2\""); |
| 862 "window.domAutomationController.send(" | |
| 863 " postToSibling('subframe-msg','frame3'));", | |
| 864 &success)); | |
| 865 EXPECT_TRUE(success); | |
| 866 | |
| 867 // Wait to receive a reply from third subframe. Second subframe sends | |
| 868 // "done-frame2" from the DOMAutomationController when the reply arrives. | |
| 869 content::DOMMessageQueue msg_queue; | |
| 870 std::string status; | |
| 871 while (msg_queue.WaitForMessage(&status)) { | |
| 872 if (status == "\"done-frame2\"") | |
| 873 break; | |
| 874 } | |
| 875 } | 890 } |
| 876 | 891 |
| 877 // In A-embed-B-embed-C scenario, verify that killing process B clears proxies | 892 // In A-embed-B-embed-C scenario, verify that killing process B clears proxies |
| 878 // of C from the tree. | 893 // of C from the tree. |
| 879 // | 894 // |
| 880 // 1 A A | 895 // 1 A A |
| 881 // / \ / \ / \ . | 896 // / \ / \ / \ . |
| 882 // 2 3 -> B A -> Kill B -> B* A | 897 // 2 3 -> B A -> Kill B -> B* A |
| 883 // / / | 898 // / / |
| 884 // 4 C | 899 // 4 C |
| (...skipping 1207 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 GURL same_site_url(embedded_test_server()->GetURL("/post_message.html")); | 2107 GURL same_site_url(embedded_test_server()->GetURL("/post_message.html")); |
| 2093 EXPECT_EQ(same_site_url, root->child_at(0)->current_url()); | 2108 EXPECT_EQ(same_site_url, root->child_at(0)->current_url()); |
| 2094 GURL foo_url(embedded_test_server()->GetURL("foo.com", | 2109 GURL foo_url(embedded_test_server()->GetURL("foo.com", |
| 2095 "/post_message.html")); | 2110 "/post_message.html")); |
| 2096 EXPECT_EQ(foo_url, root->child_at(1)->current_url()); | 2111 EXPECT_EQ(foo_url, root->child_at(1)->current_url()); |
| 2097 EXPECT_NE(root->child_at(0)->current_frame_host()->GetSiteInstance(), | 2112 EXPECT_NE(root->child_at(0)->current_frame_host()->GetSiteInstance(), |
| 2098 root->child_at(1)->current_frame_host()->GetSiteInstance()); | 2113 root->child_at(1)->current_frame_host()->GetSiteInstance()); |
| 2099 | 2114 |
| 2100 // Send a message from first, same-site frame to second, cross-site frame. | 2115 // Send a message from first, same-site frame to second, cross-site frame. |
| 2101 // Expect the second frame to reply back to the first frame. | 2116 // Expect the second frame to reply back to the first frame. |
| 2102 // | 2117 PostMessageAndWaitForReply(root->child_at(0), |
| 2103 // TODO(alexmos): Also try sending from second to first frame. Currently, | 2118 "postToSibling('subframe-msg','subframe2')", |
| 2104 // this fails due to https://crbug.com/473518, which prevents | 2119 "\"done-subframe1\""); |
| 2105 // parent.frames[x] from working when "parent" is a remote frame. | |
| 2106 bool success = false; | |
| 2107 EXPECT_TRUE(ExecuteScriptAndExtractBool( | |
| 2108 root->child_at(0)->current_frame_host(), | |
| 2109 "window.domAutomationController.send(" | |
| 2110 " postToSibling('subframe-msg','subframe2'));", | |
| 2111 &success)); | |
| 2112 EXPECT_TRUE(success); | |
| 2113 | |
| 2114 // Wait for first frame to receive a reply from the second frame. It will | |
| 2115 // send "done-subframe1" from the DOMAutomationController when the reply | |
| 2116 // arrives. | |
| 2117 content::DOMMessageQueue msg_queue; | |
| 2118 std::string status; | |
| 2119 while (msg_queue.WaitForMessage(&status)) { | |
| 2120 if (status == "\"done-subframe1\"") | |
| 2121 break; | |
| 2122 } | |
| 2123 | 2120 |
| 2124 // Send a postMessage from second, cross-site frame to its parent. Expect | 2121 // Send a postMessage from second, cross-site frame to its parent. Expect |
| 2125 // parent to send a reply to the frame. | 2122 // parent to send a reply to the frame. |
| 2126 base::string16 expected_title(base::ASCIIToUTF16("subframe-msg")); | 2123 base::string16 expected_title(base::ASCIIToUTF16("subframe-msg")); |
| 2127 TitleWatcher title_watcher(shell()->web_contents(), expected_title); | 2124 TitleWatcher title_watcher(shell()->web_contents(), expected_title); |
| 2128 success = false; | 2125 PostMessageAndWaitForReply(root->child_at(1), "postToParent('subframe-msg')", |
| 2129 EXPECT_TRUE(ExecuteScriptAndExtractBool( | 2126 "\"done-subframe2\""); |
| 2130 root->child_at(1)->current_frame_host(), | |
| 2131 "window.domAutomationController.send(postToParent('subframe-msg'));", | |
| 2132 &success)); | |
| 2133 EXPECT_TRUE(success); | |
| 2134 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); | 2127 EXPECT_EQ(expected_title, title_watcher.WaitAndGetTitle()); |
| 2135 | 2128 |
| 2136 // Wait for second frame to receive a reply from the parent. The frame will | |
| 2137 // return "done-subframe2" from the DOMAutomationController when the reply | |
| 2138 // arrives. | |
| 2139 while (msg_queue.WaitForMessage(&status)) { | |
| 2140 if (status == "\"done-subframe2\"") | |
| 2141 break; | |
| 2142 } | |
| 2143 | |
| 2144 // Verify the total number of received messages for each subframe. First | 2129 // Verify the total number of received messages for each subframe. First |
| 2145 // frame should have one message (reply from second frame), and second frame | 2130 // frame should have one message (reply from second frame), and second frame |
| 2146 // should have two messages (message from first frame and reply from parent). | 2131 // should have two messages (message from first frame and reply from parent). |
| 2147 int subframe1_received_messages = 0; | 2132 int subframe1_received_messages = 0; |
| 2148 int subframe2_received_messages = 0; | 2133 int subframe2_received_messages = 0; |
| 2149 EXPECT_TRUE(ExecuteScriptAndExtractInt( | 2134 EXPECT_TRUE(ExecuteScriptAndExtractInt( |
| 2150 root->child_at(0)->current_frame_host(), | 2135 root->child_at(0)->current_frame_host(), |
| 2151 "window.domAutomationController.send(window.receivedMessages);", | 2136 "window.domAutomationController.send(window.receivedMessages);", |
| 2152 &subframe1_received_messages)); | 2137 &subframe1_received_messages)); |
| 2153 EXPECT_EQ(1, subframe1_received_messages); | 2138 EXPECT_EQ(1, subframe1_received_messages); |
| 2154 EXPECT_TRUE(ExecuteScriptAndExtractInt( | 2139 EXPECT_TRUE(ExecuteScriptAndExtractInt( |
| 2155 root->child_at(1)->current_frame_host(), | 2140 root->child_at(1)->current_frame_host(), |
| 2156 "window.domAutomationController.send(window.receivedMessages);", | 2141 "window.domAutomationController.send(window.receivedMessages);", |
| 2157 &subframe2_received_messages)); | 2142 &subframe2_received_messages)); |
| 2158 EXPECT_EQ(2, subframe2_received_messages); | 2143 EXPECT_EQ(2, subframe2_received_messages); |
| 2159 } | 2144 } |
| 2160 | 2145 |
| 2146 // Check that parent.frames[num] references correct sibling frames when the |
| 2147 // parent is remote. See https://crbug.com/478792. |
| 2148 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, IndexedFrameAccess) { |
| 2149 // Start on a page with three same-site subframes. |
| 2150 GURL main_url( |
| 2151 embedded_test_server()->GetURL("a.com", "/frame_tree/top.html")); |
| 2152 EXPECT_TRUE(NavigateToURL(shell(), main_url)); |
| 2153 |
| 2154 // It is safe to obtain the root frame tree node here, as it doesn't change. |
| 2155 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 2156 ->GetFrameTree() |
| 2157 ->root(); |
| 2158 ASSERT_EQ(3U, root->child_count()); |
| 2159 FrameTreeNode* child0 = root->child_at(0); |
| 2160 FrameTreeNode* child1 = root->child_at(1); |
| 2161 FrameTreeNode* child2 = root->child_at(2); |
| 2162 |
| 2163 // Send each of the frames to a different site. Each new renderer will first |
| 2164 // create proxies for the parent and two sibling subframes and then create |
| 2165 // and insert the new RenderFrame into the frame tree. |
| 2166 GURL b_url(embedded_test_server()->GetURL("b.com", "/post_message.html")); |
| 2167 GURL c_url(embedded_test_server()->GetURL("c.com", "/post_message.html")); |
| 2168 GURL d_url(embedded_test_server()->GetURL("d.com", "/post_message.html")); |
| 2169 NavigateFrameToURL(child0, b_url); |
| 2170 // TODO(alexmos): The calls to WaitForRenderFrameReady can be removed once |
| 2171 // TestFrameNavigationObserver is fixed to use DidFinishLoad. |
| 2172 EXPECT_TRUE(WaitForRenderFrameReady(child0->current_frame_host())); |
| 2173 NavigateFrameToURL(child1, c_url); |
| 2174 EXPECT_TRUE(WaitForRenderFrameReady(child1->current_frame_host())); |
| 2175 NavigateFrameToURL(child2, d_url); |
| 2176 EXPECT_TRUE(WaitForRenderFrameReady(child2->current_frame_host())); |
| 2177 |
| 2178 EXPECT_EQ( |
| 2179 " Site A ------------ proxies for B C D\n" |
| 2180 " |--Site B ------- proxies for A C D\n" |
| 2181 " |--Site C ------- proxies for A B D\n" |
| 2182 " +--Site D ------- proxies for A B C\n" |
| 2183 "Where A = http://a.com/\n" |
| 2184 " B = http://b.com/\n" |
| 2185 " C = http://c.com/\n" |
| 2186 " D = http://d.com/", |
| 2187 DepictFrameTree(root)); |
| 2188 |
| 2189 // Check that each subframe sees itself at correct index in parent.frames. |
| 2190 bool success = false; |
| 2191 EXPECT_TRUE(ExecuteScriptAndExtractBool( |
| 2192 child0->current_frame_host(), |
| 2193 "window.domAutomationController.send(window === parent.frames[0]);", |
| 2194 &success)); |
| 2195 EXPECT_TRUE(success); |
| 2196 |
| 2197 success = false; |
| 2198 EXPECT_TRUE(ExecuteScriptAndExtractBool( |
| 2199 child1->current_frame_host(), |
| 2200 "window.domAutomationController.send(window === parent.frames[1]);", |
| 2201 &success)); |
| 2202 EXPECT_TRUE(success); |
| 2203 |
| 2204 success = false; |
| 2205 EXPECT_TRUE(ExecuteScriptAndExtractBool( |
| 2206 child2->current_frame_host(), |
| 2207 "window.domAutomationController.send(window === parent.frames[2]);", |
| 2208 &success)); |
| 2209 EXPECT_TRUE(success); |
| 2210 |
| 2211 // Send a postMessage from B to parent.frames[1], which should go to C, and |
| 2212 // wait for reply. |
| 2213 PostMessageAndWaitForReply(child0, "postToSibling('subframe-msg', 1)", |
| 2214 "\"done-1-1-name\""); |
| 2215 |
| 2216 // Send a postMessage from C to parent.frames[2], which should go to D, and |
| 2217 // wait for reply. |
| 2218 PostMessageAndWaitForReply(child1, "postToSibling('subframe-msg', 2)", |
| 2219 "\"done-1-2-name\""); |
| 2220 |
| 2221 // Verify the total number of received messages for each subframe. |
| 2222 int child0_received_messages = 0; |
| 2223 EXPECT_TRUE(ExecuteScriptAndExtractInt( |
| 2224 child0->current_frame_host(), |
| 2225 "window.domAutomationController.send(window.receivedMessages);", |
| 2226 &child0_received_messages)); |
| 2227 EXPECT_EQ(1, child0_received_messages); |
| 2228 |
| 2229 int child1_received_messages = 0; |
| 2230 EXPECT_TRUE(ExecuteScriptAndExtractInt( |
| 2231 child1->current_frame_host(), |
| 2232 "window.domAutomationController.send(window.receivedMessages);", |
| 2233 &child1_received_messages)); |
| 2234 EXPECT_EQ(2, child1_received_messages); |
| 2235 |
| 2236 int child2_received_messages = 0; |
| 2237 EXPECT_TRUE(ExecuteScriptAndExtractInt( |
| 2238 child2->current_frame_host(), |
| 2239 "window.domAutomationController.send(window.receivedMessages);", |
| 2240 &child2_received_messages)); |
| 2241 EXPECT_EQ(1, child2_received_messages); |
| 2242 } |
| 2243 |
| 2161 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, RFPHDestruction) { | 2244 IN_PROC_BROWSER_TEST_F(SitePerProcessBrowserTest, RFPHDestruction) { |
| 2162 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); | 2245 GURL main_url(embedded_test_server()->GetURL("/site_per_process_main.html")); |
| 2163 NavigateToURL(shell(), main_url); | 2246 NavigateToURL(shell(), main_url); |
| 2164 | 2247 |
| 2165 // It is safe to obtain the root frame tree node here, as it doesn't change. | 2248 // It is safe to obtain the root frame tree node here, as it doesn't change. |
| 2166 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) | 2249 FrameTreeNode* root = static_cast<WebContentsImpl*>(shell()->web_contents()) |
| 2167 ->GetFrameTree() | 2250 ->GetFrameTree() |
| 2168 ->root(); | 2251 ->root(); |
| 2169 | 2252 |
| 2170 TestNavigationObserver observer(shell()->web_contents()); | 2253 TestNavigationObserver observer(shell()->web_contents()); |
| (...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2212 " |--Site A\n" | 2295 " |--Site A\n" |
| 2213 " +--Site A\n" | 2296 " +--Site A\n" |
| 2214 " |--Site A\n" | 2297 " |--Site A\n" |
| 2215 " +--Site A\n" | 2298 " +--Site A\n" |
| 2216 " +--Site A\n" | 2299 " +--Site A\n" |
| 2217 "Where A = http://127.0.0.1/", | 2300 "Where A = http://127.0.0.1/", |
| 2218 DepictFrameTree(root)); | 2301 DepictFrameTree(root)); |
| 2219 } | 2302 } |
| 2220 | 2303 |
| 2221 } // namespace content | 2304 } // namespace content |
| OLD | NEW |