OLD | NEW |
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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/bind.h" | 5 #include "base/bind.h" |
6 #include "base/command_line.h" | 6 #include "base/command_line.h" |
7 #include "base/run_loop.h" | 7 #include "base/run_loop.h" |
8 #include "build/build_config.h" | 8 #include "build/build_config.h" |
9 #include "content/browser/renderer_host/render_process_host_impl.h" | 9 #include "content/browser/renderer_host/render_process_host_impl.h" |
10 #include "content/common/child_process_messages.h" | 10 #include "content/common/child_process_messages.h" |
11 #include "content/public/browser/render_frame_host.h" | 11 #include "content/public/browser/render_frame_host.h" |
12 #include "content/public/browser/render_process_host.h" | 12 #include "content/public/browser/render_process_host.h" |
13 #include "content/public/browser/render_process_host_observer.h" | 13 #include "content/public/browser/render_process_host_observer.h" |
14 #include "content/public/browser/web_contents.h" | 14 #include "content/public/browser/web_contents.h" |
15 #include "content/public/common/url_constants.h" | 15 #include "content/public/common/url_constants.h" |
16 #include "content/public/test/content_browser_test.h" | 16 #include "content/public/test/content_browser_test.h" |
17 #include "content/public/test/content_browser_test_utils.h" | 17 #include "content/public/test/content_browser_test_utils.h" |
18 #include "content/public/test/test_service.mojom.h" | 18 #include "content/public/test/test_service.mojom.h" |
19 #include "content/shell/browser/shell.h" | 19 #include "content/shell/browser/shell.h" |
| 20 #include "content/shell/browser/shell_browser_context.h" |
| 21 #include "content/shell/browser/shell_browser_main_parts.h" |
| 22 #include "content/shell/browser/shell_content_browser_client.h" |
| 23 #include "content/test/test_content_browser_client.h" |
20 #include "media/base/bind_to_current_loop.h" | 24 #include "media/base/bind_to_current_loop.h" |
21 #include "media/base/media_switches.h" | 25 #include "media/base/media_switches.h" |
22 #include "media/base/test_data_util.h" | 26 #include "media/base/test_data_util.h" |
23 #include "media/mojo/features.h" | 27 #include "media/mojo/features.h" |
24 #include "net/test/embedded_test_server/embedded_test_server.h" | 28 #include "net/test/embedded_test_server/embedded_test_server.h" |
25 | 29 |
26 #if defined(OS_WIN) | 30 #if defined(OS_WIN) |
27 #include "base/win/windows_version.h" | 31 #include "base/win/windows_version.h" |
28 #endif | 32 #endif |
29 | 33 |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
66 } | 70 } |
67 void RenderProcessHostDestroyed(RenderProcessHost* host) override { | 71 void RenderProcessHostDestroyed(RenderProcessHost* host) override { |
68 ++host_destructions_; | 72 ++host_destructions_; |
69 } | 73 } |
70 | 74 |
71 int process_exits_; | 75 int process_exits_; |
72 int host_destructions_; | 76 int host_destructions_; |
73 base::Closure process_exit_callback_; | 77 base::Closure process_exit_callback_; |
74 }; | 78 }; |
75 | 79 |
| 80 // A mock ContentBrowserClient that only considers a spare renderer to be a |
| 81 // suitable host. |
| 82 class SpareRendererContentBrowserClient : public TestContentBrowserClient { |
| 83 public: |
| 84 bool IsSuitableHost(RenderProcessHost* process_host, |
| 85 const GURL& site_url) override { |
| 86 if (RenderProcessHostImpl::GetSpareRenderProcessHostForTesting()) { |
| 87 return process_host == |
| 88 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting(); |
| 89 } |
| 90 return true; |
| 91 } |
| 92 }; |
| 93 |
| 94 // A mock ContentBrowserClient that only considers a non-spare renderer to be a |
| 95 // suitable host, but otherwise tries to reuse processes. |
| 96 class NonSpareRendererContentBrowserClient : public TestContentBrowserClient { |
| 97 public: |
| 98 bool IsSuitableHost(RenderProcessHost* process_host, |
| 99 const GURL& site_url) override { |
| 100 return RenderProcessHostImpl::GetSpareRenderProcessHostForTesting() != |
| 101 process_host; |
| 102 } |
| 103 |
| 104 bool ShouldTryToUseExistingProcessHost(BrowserContext* context, |
| 105 const GURL& url) override { |
| 106 return true; |
| 107 } |
| 108 }; |
| 109 |
76 // Sometimes the renderer process's ShutdownRequest (corresponding to the | 110 // Sometimes the renderer process's ShutdownRequest (corresponding to the |
77 // ViewMsg_WasSwappedOut from a previous navigation) doesn't arrive until after | 111 // ViewMsg_WasSwappedOut from a previous navigation) doesn't arrive until after |
78 // the browser process decides to re-use the renderer for a new purpose. This | 112 // the browser process decides to re-use the renderer for a new purpose. This |
79 // test makes sure the browser doesn't let the renderer die in that case. See | 113 // test makes sure the browser doesn't let the renderer die in that case. See |
80 // http://crbug.com/87176. | 114 // http://crbug.com/87176. |
81 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, | 115 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, |
82 ShutdownRequestFromActiveTabIgnored) { | 116 ShutdownRequestFromActiveTabIgnored) { |
83 ASSERT_TRUE(embedded_test_server()->Start()); | 117 ASSERT_TRUE(embedded_test_server()->Start()); |
84 | 118 |
85 GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); | 119 GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); |
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
123 GURL::Replacements replace_host; | 157 GURL::Replacements replace_host; |
124 replace_host.SetHostStr("localhost"); | 158 replace_host.SetHostStr("localhost"); |
125 GURL another_url = embedded_test_server()->GetURL("/simple_page.html"); | 159 GURL another_url = embedded_test_server()->GetURL("/simple_page.html"); |
126 another_url = another_url.ReplaceComponents(replace_host); | 160 another_url = another_url.ReplaceComponents(replace_host); |
127 NavigateToURL(CreateBrowser(), another_url); | 161 NavigateToURL(CreateBrowser(), another_url); |
128 | 162 |
129 // Expect that we got another process (the guest renderer was not reused). | 163 // Expect that we got another process (the guest renderer was not reused). |
130 EXPECT_EQ(2, RenderProcessHostCount()); | 164 EXPECT_EQ(2, RenderProcessHostCount()); |
131 } | 165 } |
132 | 166 |
| 167 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRenderProcessHostTaken) { |
| 168 ASSERT_TRUE(embedded_test_server()->Start()); |
| 169 |
| 170 RenderProcessHost::WarmupSpareRenderProcessHost( |
| 171 ShellContentBrowserClient::Get()->browser_context()); |
| 172 RenderProcessHost* spare_renderer = |
| 173 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting(); |
| 174 EXPECT_NE(nullptr, spare_renderer); |
| 175 |
| 176 GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); |
| 177 Shell* window = CreateBrowser(); |
| 178 NavigateToURL(window, test_url); |
| 179 |
| 180 EXPECT_EQ(spare_renderer, |
| 181 window->web_contents()->GetMainFrame()->GetProcess()); |
| 182 |
| 183 // The spare render process host should no longer be available. |
| 184 EXPECT_EQ(nullptr, |
| 185 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting()); |
| 186 } |
| 187 |
| 188 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRenderProcessHostNotTaken) { |
| 189 ASSERT_TRUE(embedded_test_server()->Start()); |
| 190 |
| 191 RenderProcessHost::WarmupSpareRenderProcessHost( |
| 192 ShellContentBrowserClient::Get()->off_the_record_browser_context()); |
| 193 RenderProcessHost* spare_renderer = |
| 194 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting(); |
| 195 GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); |
| 196 Shell* window = CreateBrowser(); |
| 197 NavigateToURL(window, test_url); |
| 198 |
| 199 // There should have been another process created for the navigation. |
| 200 EXPECT_NE(spare_renderer, |
| 201 window->web_contents()->GetMainFrame()->GetProcess()); |
| 202 |
| 203 // The spare RenderProcessHost should have been cleaned up. Note this |
| 204 // behavior is identical to what would have happened if the RenderProcessHost |
| 205 // were taken. |
| 206 EXPECT_EQ(nullptr, |
| 207 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting()); |
| 208 } |
| 209 |
| 210 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRenderProcessHostKilled) { |
| 211 RenderProcessHost::WarmupSpareRenderProcessHost( |
| 212 ShellContentBrowserClient::Get()->browser_context()); |
| 213 |
| 214 RenderProcessHost* spare_renderer = |
| 215 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting(); |
| 216 mojom::TestServicePtr service; |
| 217 ASSERT_NE(nullptr, spare_renderer); |
| 218 BindInterface(spare_renderer, &service); |
| 219 |
| 220 base::RunLoop run_loop; |
| 221 set_process_exit_callback(run_loop.QuitClosure()); |
| 222 spare_renderer->AddObserver(this); // For process_exit_callback. |
| 223 |
| 224 // Should reply with a bad message and cause process death. |
| 225 service->DoSomething(base::Bind(&base::DoNothing)); |
| 226 run_loop.Run(); |
| 227 |
| 228 // The spare RenderProcessHost should disappear when its process dies. |
| 229 EXPECT_EQ(nullptr, |
| 230 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting()); |
| 231 } |
| 232 |
| 233 // Test that the spare renderer works correctly when the limit on the maximum |
| 234 // number of processes is small. |
| 235 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, |
| 236 SpareRendererSurpressedMaxProcesses) { |
| 237 ASSERT_TRUE(embedded_test_server()->Start()); |
| 238 |
| 239 SpareRendererContentBrowserClient browser_client; |
| 240 ContentBrowserClient* old_client = |
| 241 SetBrowserClientForTesting(&browser_client); |
| 242 |
| 243 RenderProcessHost::SetMaxRendererProcessCount(1); |
| 244 |
| 245 // A process is created with shell startup, so with a maximum of one renderer |
| 246 // process the spare RPH should not be created. |
| 247 RenderProcessHost::WarmupSpareRenderProcessHost( |
| 248 ShellContentBrowserClient::Get()->browser_context()); |
| 249 EXPECT_EQ(nullptr, |
| 250 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting()); |
| 251 |
| 252 // A spare RPH should be created with a max of 2 renderer processes. |
| 253 RenderProcessHost::SetMaxRendererProcessCount(2); |
| 254 RenderProcessHost::WarmupSpareRenderProcessHost( |
| 255 ShellContentBrowserClient::Get()->browser_context()); |
| 256 RenderProcessHost* spare_renderer = |
| 257 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting(); |
| 258 EXPECT_NE(nullptr, spare_renderer); |
| 259 |
| 260 // Thanks to the injected SpareRendererContentBrowserClient and the limit on |
| 261 // processes, the spare RPH will always be used via GetExistingProcessHost() |
| 262 // rather than picked up via MaybeTakeSpareRenderProcessHost(). |
| 263 GURL test_url = embedded_test_server()->GetURL("/simple_page.html"); |
| 264 Shell* new_window = CreateBrowser(); |
| 265 NavigateToURL(new_window, test_url); |
| 266 // The spare RPH should have been dropped during CreateBrowser() and given to |
| 267 // the new window. |
| 268 EXPECT_EQ(nullptr, |
| 269 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting()); |
| 270 EXPECT_EQ(spare_renderer, |
| 271 new_window->web_contents()->GetMainFrame()->GetProcess()); |
| 272 |
| 273 // Revert to the default process limit and original ContentBrowserClient. |
| 274 RenderProcessHost::SetMaxRendererProcessCount(0); |
| 275 SetBrowserClientForTesting(old_client); |
| 276 } |
| 277 |
| 278 // Check that the spare renderer is dropped if an existing process is reused. |
| 279 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRendererOnProcessReuse) { |
| 280 ASSERT_TRUE(embedded_test_server()->Start()); |
| 281 |
| 282 NonSpareRendererContentBrowserClient browser_client; |
| 283 ContentBrowserClient* old_client = |
| 284 SetBrowserClientForTesting(&browser_client); |
| 285 |
| 286 RenderProcessHost::WarmupSpareRenderProcessHost( |
| 287 ShellContentBrowserClient::Get()->browser_context()); |
| 288 RenderProcessHost* spare_renderer = |
| 289 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting(); |
| 290 EXPECT_NE(nullptr, spare_renderer); |
| 291 |
| 292 // This should resuse the existing process and cause the spare renderer to be |
| 293 // dropped. |
| 294 Shell* new_browser = CreateBrowser(); |
| 295 EXPECT_EQ(shell()->web_contents()->GetMainFrame()->GetProcess(), |
| 296 new_browser->web_contents()->GetMainFrame()->GetProcess()); |
| 297 EXPECT_NE(spare_renderer, |
| 298 new_browser->web_contents()->GetMainFrame()->GetProcess()); |
| 299 EXPECT_EQ(nullptr, |
| 300 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting()); |
| 301 |
| 302 SetBrowserClientForTesting(old_client); |
| 303 } |
| 304 |
133 class ShellCloser : public RenderProcessHostObserver { | 305 class ShellCloser : public RenderProcessHostObserver { |
134 public: | 306 public: |
135 ShellCloser(Shell* shell, std::string* logging_string) | 307 ShellCloser(Shell* shell, std::string* logging_string) |
136 : shell_(shell), logging_string_(logging_string) {} | 308 : shell_(shell), logging_string_(logging_string) {} |
137 | 309 |
138 protected: | 310 protected: |
139 // RenderProcessHostObserver: | 311 // RenderProcessHostObserver: |
140 void RenderProcessExited(RenderProcessHost* host, | 312 void RenderProcessExited(RenderProcessHost* host, |
141 base::TerminationStatus status, | 313 base::TerminationStatus status, |
142 int exit_code) override { | 314 int exit_code) override { |
(...skipping 179 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
322 // Verify shutdown went as expected. | 494 // Verify shutdown went as expected. |
323 EXPECT_EQ(0, rph->get_audio_stream_count_for_testing()); | 495 EXPECT_EQ(0, rph->get_audio_stream_count_for_testing()); |
324 EXPECT_EQ(1, process_exits_); | 496 EXPECT_EQ(1, process_exits_); |
325 EXPECT_EQ(0, host_destructions_); | 497 EXPECT_EQ(0, host_destructions_); |
326 if (!host_destructions_) | 498 if (!host_destructions_) |
327 rph->RemoveObserver(this); | 499 rph->RemoveObserver(this); |
328 } | 500 } |
329 | 501 |
330 } // namespace | 502 } // namespace |
331 } // namespace content | 503 } // namespace content |
OLD | NEW |