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
3 // found in the LICENSE file.
4
5 #include "base/bind.h"
6 #include "base/callback_helpers.h"
7 #include "base/command_line.h"
8 #include "base/run_loop.h"
9 #include "base/synchronization/waitable_event.h"
10 #include "base/test/metrics/histogram_tester.h"
11 #include "base/test/scoped_feature_list.h"
12 #include "base/test/simple_test_tick_clock.h"
13 #include "base/test/test_timeouts.h"
14 #include "build/build_config.h"
15 #include "content/browser/renderer_host/render_frame_host_impl.h"
16 #include "content/browser/renderer_host/render_process_host_impl.h"
17 #include "content/public/browser/browser_task_traits.h"
18 #include "content/public/browser/browser_thread.h"
19 #include "content/public/browser/child_process_launcher_utils.h"
20 #include "content/public/browser/render_frame_host.h"
21 #include "content/public/browser/render_process_host.h"
22 #include "content/public/browser/render_process_host_observer.h"
23 #include "content/public/browser/web_contents.h"
24 #include "content/public/browser/web_contents_observer.h"
25 #include "content/public/common/content_client.h"
26 #include "content/public/common/content_features.h"
27 #include "content/public/common/content_switches.h"
28 #include "content/public/common/url_constants.h"
29 #include "content/public/test/back_forward_cache_util.h"
30 #include "content/public/test/browser_test.h"
31 #include "content/public/test/browser_test_utils.h"
32 #include "content/public/test/content_browser_test.h"
33 #include "content/public/test/content_browser_test_utils.h"
34 #include "content/public/test/no_renderer_crashes_assertion.h"
35 #include "content/public/test/test_service.mojom.h"
36 #include "content/public/test/test_utils.h"
37 #include "content/shell/browser/shell.h"
38 #include "content/shell/browser/shell_browser_context.h"
39 #include "content/shell/browser/shell_browser_main_parts.h"
40 #include "content/shell/browser/shell_content_browser_client.h"
41 #include "content/test/test_content_browser_client.h"
42 #include "media/base/bind_to_current_loop.h"
43 #include "media/base/media_switches.h"
44 #include "media/base/test_data_util.h"
45 #include "media/mojo/buildflags.h"
46 #include "mojo/public/cpp/bindings/remote.h"
47 #include "net/dns/mock_host_resolver.h"
48 #include "net/test/embedded_test_server/embedded_test_server.h"
49 #include "net/test/embedded_test_server/http_request.h"
50 #include "net/test/embedded_test_server/http_response.h"
51
52 #if defined(OS_WIN)
53 #include "base/win/windows_version.h"
54 #endif
55
56 namespace content {
57
58 namespace {
59
60 // Similar to net::test_server::DelayedHttpResponse, but the delay is resolved
61 // through Resolver.
62 class DelayedHttpResponseWithResolver final
63 : public net::test_server::BasicHttpResponse {
64 public:
65 struct ResponseWithCallbacks final {
66 net::test_server::SendBytesCallback send_callback;
67 net::test_server::SendCompleteCallback done_callback;
68 std::string response_string;
69 };
70
71 class Resolver final : public base::RefCountedThreadSafe<Resolver> {
72 public:
Resolve()73 void Resolve() {
74 base::AutoLock auto_lock(lock_);
75 DCHECK(!resolved_);
76 resolved_ = true;
77
78 if (!task_runner_) {
79 return;
80 }
81
82 task_runner_->PostTask(
83 FROM_HERE,
84 base::BindOnce(&Resolver::ResolveInServerTaskRunner, this));
85 }
86
Add(ResponseWithCallbacks response)87 void Add(ResponseWithCallbacks response) {
88 base::AutoLock auto_lock(lock_);
89
90 if (resolved_) {
91 response.send_callback.Run(response.response_string,
92 std::move(response.done_callback));
93 return;
94 }
95
96 scoped_refptr<base::SingleThreadTaskRunner> task_runner =
97 base::ThreadTaskRunnerHandle::Get();
98 if (task_runner_) {
99 DCHECK_EQ(task_runner_, task_runner);
100 } else {
101 task_runner_ = std::move(task_runner);
102 }
103
104 responses_with_callbacks_.push_back(std::move(response));
105 }
106
107 private:
ResolveInServerTaskRunner()108 void ResolveInServerTaskRunner() {
109 auto responses_with_callbacks = std::move(responses_with_callbacks_);
110 for (auto& response_with_callbacks : responses_with_callbacks) {
111 response_with_callbacks.send_callback.Run(
112 response_with_callbacks.response_string,
113 std::move(response_with_callbacks.done_callback));
114 }
115 }
116
117 friend class base::RefCountedThreadSafe<Resolver>;
118 ~Resolver() = default;
119
120 base::Lock lock_;
121
122 std::vector<ResponseWithCallbacks> responses_with_callbacks_;
123 bool resolved_ GUARDED_BY(lock_) = false;
124 scoped_refptr<base::SingleThreadTaskRunner> task_runner_ GUARDED_BY(lock_);
125 };
126
DelayedHttpResponseWithResolver(scoped_refptr<Resolver> resolver)127 explicit DelayedHttpResponseWithResolver(scoped_refptr<Resolver> resolver)
128 : resolver_(std::move(resolver)) {}
129
130 DelayedHttpResponseWithResolver(const DelayedHttpResponseWithResolver&) =
131 delete;
132 DelayedHttpResponseWithResolver& operator=(
133 const DelayedHttpResponseWithResolver&) = delete;
134
SendResponse(const net::test_server::SendBytesCallback & send,net::test_server::SendCompleteCallback done)135 void SendResponse(const net::test_server::SendBytesCallback& send,
136 net::test_server::SendCompleteCallback done) override {
137 resolver_->Add({send, std::move(done), ToResponseString()});
138 }
139
140 private:
141 const scoped_refptr<Resolver> resolver_;
142 };
143
HandleBeacon(const net::test_server::HttpRequest & request)144 std::unique_ptr<net::test_server::HttpResponse> HandleBeacon(
145 const net::test_server::HttpRequest& request) {
146 if (request.relative_url != "/beacon")
147 return nullptr;
148 return std::make_unique<net::test_server::BasicHttpResponse>();
149 }
150
HandleHungBeacon(const base::RepeatingClosure & on_called,const net::test_server::HttpRequest & request)151 std::unique_ptr<net::test_server::HttpResponse> HandleHungBeacon(
152 const base::RepeatingClosure& on_called,
153 const net::test_server::HttpRequest& request) {
154 if (request.relative_url != "/beacon")
155 return nullptr;
156 if (on_called) {
157 on_called.Run();
158 }
159 return std::make_unique<net::test_server::HungResponse>();
160 }
161
HandleHungBeaconWithResolver(scoped_refptr<DelayedHttpResponseWithResolver::Resolver> resolver,const net::test_server::HttpRequest & request)162 std::unique_ptr<net::test_server::HttpResponse> HandleHungBeaconWithResolver(
163 scoped_refptr<DelayedHttpResponseWithResolver::Resolver> resolver,
164 const net::test_server::HttpRequest& request) {
165 if (request.relative_url != "/beacon")
166 return nullptr;
167 return std::make_unique<DelayedHttpResponseWithResolver>(std::move(resolver));
168 }
169
170 } // namespace
171
172 class RenderProcessHostTest : public ContentBrowserTest,
173 public RenderProcessHostObserver {
174 public:
RenderProcessHostTest()175 RenderProcessHostTest()
176 : process_exits_(0), host_destructions_(0), use_frame_priority_(false) {}
177
SetUp()178 void SetUp() override {
179 if (use_frame_priority_) {
180 feature_list_.InitAndEnableFeature(
181 features::kUseFramePriorityInRenderProcessHost);
182 } else {
183 feature_list_.InitAndDisableFeature(
184 features::kUseFramePriorityInRenderProcessHost);
185 }
186 ContentBrowserTest::SetUp();
187 }
188
SetUpCommandLine(base::CommandLine * command_line)189 void SetUpCommandLine(base::CommandLine* command_line) override {
190 command_line->AppendSwitchASCII(
191 switches::kAutoplayPolicy,
192 switches::autoplay::kNoUserGestureRequiredPolicy);
193 }
194
SetUpOnMainThread()195 void SetUpOnMainThread() override {
196 // Support multiple sites on the test server.
197 host_resolver()->AddRule("*", "127.0.0.1");
198 }
199
SetVisibleClients(RenderProcessHost * process,int32_t visible_clients)200 void SetVisibleClients(RenderProcessHost* process, int32_t visible_clients) {
201 RenderProcessHostImpl* impl = static_cast<RenderProcessHostImpl*>(process);
202 impl->visible_clients_ = visible_clients;
203 }
204 protected:
set_process_exit_callback(base::OnceClosure callback)205 void set_process_exit_callback(base::OnceClosure callback) {
206 process_exit_callback_ = std::move(callback);
207 }
208
209 // RenderProcessHostObserver:
RenderProcessExited(RenderProcessHost * host,const ChildProcessTerminationInfo & info)210 void RenderProcessExited(RenderProcessHost* host,
211 const ChildProcessTerminationInfo& info) override {
212 ++process_exits_;
213 if (process_exit_callback_)
214 std::move(process_exit_callback_).Run();
215 }
RenderProcessHostDestroyed(RenderProcessHost * host)216 void RenderProcessHostDestroyed(RenderProcessHost* host) override {
217 ++host_destructions_;
218 }
WaitUntilProcessExits(int target)219 void WaitUntilProcessExits(int target) {
220 while (process_exits_ < target)
221 base::RunLoop().RunUntilIdle();
222 }
223
224 int process_exits_;
225 int host_destructions_;
226 base::OnceClosure process_exit_callback_;
227 bool use_frame_priority_;
228 base::test::ScopedFeatureList feature_list_;
229 };
230
231 // A mock ContentBrowserClient that only considers a spare renderer to be a
232 // suitable host.
233 class SpareRendererContentBrowserClient : public TestContentBrowserClient {
234 public:
IsSuitableHost(RenderProcessHost * process_host,const GURL & site_url)235 bool IsSuitableHost(RenderProcessHost* process_host,
236 const GURL& site_url) override {
237 if (RenderProcessHostImpl::GetSpareRenderProcessHostForTesting()) {
238 return process_host ==
239 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
240 }
241 return true;
242 }
243 };
244
245 // A mock ContentBrowserClient that only considers a non-spare renderer to be a
246 // suitable host, but otherwise tries to reuse processes.
247 class NonSpareRendererContentBrowserClient : public TestContentBrowserClient {
248 public:
249 NonSpareRendererContentBrowserClient() = default;
250
IsSuitableHost(RenderProcessHost * process_host,const GURL & site_url)251 bool IsSuitableHost(RenderProcessHost* process_host,
252 const GURL& site_url) override {
253 return RenderProcessHostImpl::GetSpareRenderProcessHostForTesting() !=
254 process_host;
255 }
256
ShouldTryToUseExistingProcessHost(BrowserContext * context,const GURL & url)257 bool ShouldTryToUseExistingProcessHost(BrowserContext* context,
258 const GURL& url) override {
259 return true;
260 }
261
ShouldUseSpareRenderProcessHost(BrowserContext * browser_context,const GURL & site_url)262 bool ShouldUseSpareRenderProcessHost(BrowserContext* browser_context,
263 const GURL& site_url) override {
264 return false;
265 }
266
267 private:
268 DISALLOW_COPY_AND_ASSIGN(NonSpareRendererContentBrowserClient);
269 };
270
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,GuestsAreNotSuitableHosts)271 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
272 GuestsAreNotSuitableHosts) {
273 // Set max renderers to 1 to force running out of processes.
274 RenderProcessHost::SetMaxRendererProcessCount(1);
275
276 ASSERT_TRUE(embedded_test_server()->Start());
277
278 GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
279 EXPECT_TRUE(NavigateToURL(shell(), test_url));
280 RenderProcessHost* rph =
281 shell()->web_contents()->GetMainFrame()->GetProcess();
282 // Make it believe it's a guest.
283 static_cast<RenderProcessHostImpl*>(rph)->set_is_for_guests_only_for_testing(
284 true);
285 EXPECT_EQ(1, RenderProcessHost::GetCurrentRenderProcessCountForTesting());
286
287 // Navigate to a different page.
288 GURL::Replacements replace_host;
289 replace_host.SetHostStr("localhost");
290 GURL another_url = embedded_test_server()->GetURL("/simple_page.html");
291 another_url = another_url.ReplaceComponents(replace_host);
292 EXPECT_TRUE(NavigateToURL(CreateBrowser(), another_url));
293
294 // Expect that we got another process (the guest renderer was not reused).
295 EXPECT_EQ(2, RenderProcessHost::GetCurrentRenderProcessCountForTesting());
296 }
297
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,SpareRenderProcessHostTaken)298 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRenderProcessHostTaken) {
299 ASSERT_TRUE(embedded_test_server()->Start());
300
301 RenderProcessHost::WarmupSpareRenderProcessHost(
302 ShellContentBrowserClient::Get()->browser_context());
303 RenderProcessHost* spare_renderer =
304 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
305 EXPECT_NE(nullptr, spare_renderer);
306
307 GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
308 Shell* window = CreateBrowser();
309 EXPECT_TRUE(NavigateToURL(window, test_url));
310
311 EXPECT_EQ(spare_renderer,
312 window->web_contents()->GetMainFrame()->GetProcess());
313
314 // The old spare render process host should no longer be available.
315 EXPECT_NE(spare_renderer,
316 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
317
318 // Check if a fresh spare is available (depending on the operating mode).
319 if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
320 EXPECT_NE(nullptr,
321 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
322 } else {
323 EXPECT_EQ(nullptr,
324 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
325 }
326 }
327
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,SpareRenderProcessHostNotTaken)328 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRenderProcessHostNotTaken) {
329 ASSERT_TRUE(embedded_test_server()->Start());
330
331 RenderProcessHost::WarmupSpareRenderProcessHost(
332 ShellContentBrowserClient::Get()->off_the_record_browser_context());
333 RenderProcessHost* spare_renderer =
334 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
335 GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
336 Shell* window = CreateBrowser();
337 EXPECT_TRUE(NavigateToURL(window, test_url));
338
339 // There should have been another process created for the navigation.
340 EXPECT_NE(spare_renderer,
341 window->web_contents()->GetMainFrame()->GetProcess());
342
343 // Check if a fresh spare is available (depending on the operating mode).
344 // Note this behavior is identical to what would have happened if the
345 // RenderProcessHost were taken.
346 if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
347 EXPECT_NE(nullptr,
348 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
349 } else {
350 EXPECT_EQ(nullptr,
351 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
352 }
353 }
354
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,SpareRenderProcessHostKilled)355 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRenderProcessHostKilled) {
356 RenderProcessHost::WarmupSpareRenderProcessHost(
357 ShellContentBrowserClient::Get()->browser_context());
358
359 RenderProcessHost* spare_renderer =
360 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
361 mojo::Remote<mojom::TestService> service;
362 ASSERT_NE(nullptr, spare_renderer);
363 spare_renderer->BindReceiver(service.BindNewPipeAndPassReceiver());
364
365 base::RunLoop run_loop;
366 set_process_exit_callback(run_loop.QuitClosure());
367 spare_renderer->AddObserver(this); // For process_exit_callback.
368
369 // Should reply with a bad message and cause process death.
370 {
371 ScopedAllowRendererCrashes scoped_allow_renderer_crashes(spare_renderer);
372 service->DoSomething(base::DoNothing());
373 run_loop.Run();
374 }
375
376 // The spare RenderProcessHost should disappear when its process dies.
377 EXPECT_EQ(nullptr,
378 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
379 }
380
381 // Test that the spare renderer works correctly when the limit on the maximum
382 // number of processes is small.
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,SpareRendererSurpressedMaxProcesses)383 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
384 SpareRendererSurpressedMaxProcesses) {
385 ASSERT_TRUE(embedded_test_server()->Start());
386
387 SpareRendererContentBrowserClient browser_client;
388 ContentBrowserClient* old_client =
389 SetBrowserClientForTesting(&browser_client);
390
391 RenderProcessHost::SetMaxRendererProcessCount(1);
392
393 // A process is created with shell startup, so with a maximum of one renderer
394 // process the spare RPH should not be created.
395 RenderProcessHost::WarmupSpareRenderProcessHost(
396 ShellContentBrowserClient::Get()->browser_context());
397 EXPECT_EQ(nullptr,
398 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
399
400 // A spare RPH should be created with a max of 2 renderer processes.
401 RenderProcessHost::SetMaxRendererProcessCount(2);
402 RenderProcessHost::WarmupSpareRenderProcessHost(
403 ShellContentBrowserClient::Get()->browser_context());
404 RenderProcessHost* spare_renderer =
405 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
406 EXPECT_NE(nullptr, spare_renderer);
407
408 // Thanks to the injected SpareRendererContentBrowserClient and the limit on
409 // processes, the spare RPH will always be used via GetExistingProcessHost()
410 // rather than picked up via MaybeTakeSpareRenderProcessHost().
411 GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
412 Shell* new_window = CreateBrowser();
413 EXPECT_TRUE(NavigateToURL(new_window, test_url));
414 // Outside of RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes mode, the
415 // spare RPH should have been dropped during CreateBrowser() and given to the
416 // new window. OTOH, even in the IsSpareProcessKeptAtAllTimes mode, the spare
417 // shouldn't be created because of the low process limit.
418 EXPECT_EQ(nullptr,
419 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
420 EXPECT_EQ(spare_renderer,
421 new_window->web_contents()->GetMainFrame()->GetProcess());
422
423 // Revert to the default process limit and original ContentBrowserClient.
424 RenderProcessHost::SetMaxRendererProcessCount(0);
425 SetBrowserClientForTesting(old_client);
426 }
427
428 // Check that the spare renderer is dropped if an existing process is reused.
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,SpareRendererOnProcessReuse)429 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRendererOnProcessReuse) {
430 ASSERT_TRUE(embedded_test_server()->Start());
431
432 NonSpareRendererContentBrowserClient browser_client;
433 ContentBrowserClient* old_client =
434 SetBrowserClientForTesting(&browser_client);
435
436 RenderProcessHost::WarmupSpareRenderProcessHost(
437 ShellContentBrowserClient::Get()->browser_context());
438 RenderProcessHost* spare_renderer =
439 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
440 EXPECT_NE(nullptr, spare_renderer);
441
442 // This should reuse the existing process.
443 Shell* new_browser = CreateBrowser();
444 EXPECT_EQ(shell()->web_contents()->GetMainFrame()->GetProcess(),
445 new_browser->web_contents()->GetMainFrame()->GetProcess());
446 EXPECT_NE(spare_renderer,
447 new_browser->web_contents()->GetMainFrame()->GetProcess());
448 if (RenderProcessHostImpl::IsSpareProcessKeptAtAllTimes()) {
449 EXPECT_NE(nullptr,
450 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
451 } else {
452 EXPECT_EQ(nullptr,
453 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting());
454 }
455
456 // The launcher thread reads state from browser_client, need to wait for it to
457 // be done before resetting the browser client. crbug.com/742533.
458 base::WaitableEvent launcher_thread_done(
459 base::WaitableEvent::ResetPolicy::MANUAL,
460 base::WaitableEvent::InitialState::NOT_SIGNALED);
461 GetProcessLauncherTaskRunner()->PostTask(
462 FROM_HERE,
463 base::BindOnce([](base::WaitableEvent* done) { done->Signal(); },
464 base::Unretained(&launcher_thread_done)));
465 ASSERT_TRUE(launcher_thread_done.TimedWait(TestTimeouts::action_timeout()));
466
467 SetBrowserClientForTesting(old_client);
468 }
469
470 // Verifies that the spare renderer maintained by SpareRenderProcessHostManager
471 // is correctly destroyed during browser shutdown. This test is an analogue
472 // to the //chrome-layer FastShutdown.SpareRenderProcessHost test.
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,SpareRenderProcessHostDuringShutdown)473 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
474 SpareRenderProcessHostDuringShutdown) {
475 content::RenderProcessHost::WarmupSpareRenderProcessHost(
476 shell()->web_contents()->GetBrowserContext());
477
478 // The verification is that there are no DCHECKs anywhere during test tear
479 // down.
480 }
481
482 // Verifies that the spare renderer maintained by SpareRenderProcessHostManager
483 // is correctly destroyed when closing the last content shell.
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,SpareRendererDuringClosing)484 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareRendererDuringClosing) {
485 content::RenderProcessHost::WarmupSpareRenderProcessHost(
486 shell()->web_contents()->GetBrowserContext());
487 shell()->web_contents()->Close();
488
489 // The verification is that there are no DCHECKs or UaF anywhere during test
490 // tear down.
491 }
492
493 // Class that simulates the fact that some //content embedders (e.g. by
494 // overriding ChromeContentBrowserClient::GetStoragePartitionConfigForSite) can
495 // cause BrowserContext::GetDefaultStoragePartition(browser_context) to differ
496 // from BrowserContext::GetStoragePartition(browser_context, site_instance) even
497 // if |site_instance| is not for guests.
498 class CustomStoragePartitionForSomeSites : public TestContentBrowserClient {
499 public:
CustomStoragePartitionForSomeSites(const GURL & site_to_isolate)500 explicit CustomStoragePartitionForSomeSites(const GURL& site_to_isolate)
501 : site_to_isolate_(site_to_isolate) {}
502
GetStoragePartitionConfigForSite(BrowserContext * browser_context,const GURL & site)503 StoragePartitionConfig GetStoragePartitionConfigForSite(
504 BrowserContext* browser_context,
505 const GURL& site) override {
506 // Override for |site_to_isolate_|.
507 if (site == site_to_isolate_) {
508 return StoragePartitionConfig::Create("blah_isolated_storage",
509 "blah_isolated_storage",
510 false /* in_memory */);
511 }
512
513 return StoragePartitionConfig::CreateDefault();
514 }
515
GetStoragePartitionIdForSite(BrowserContext * browser_context,const GURL & site)516 std::string GetStoragePartitionIdForSite(BrowserContext* browser_context,
517 const GURL& site) override {
518 if (site == site_to_isolate_)
519 return "custom";
520 return "";
521 }
522
IsValidStoragePartitionId(BrowserContext * browser_context,const std::string & partition_id)523 bool IsValidStoragePartitionId(BrowserContext* browser_context,
524 const std::string& partition_id) override {
525 return partition_id == "" || partition_id == "custom";
526 }
527
528 private:
529 GURL site_to_isolate_;
530
531 DISALLOW_COPY_AND_ASSIGN(CustomStoragePartitionForSomeSites);
532 };
533
534 // This test verifies that SpareRenderProcessHostManager correctly accounts
535 // for StoragePartition differences when handing out the spare process.
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,SpareProcessVsCustomStoragePartition)536 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
537 SpareProcessVsCustomStoragePartition) {
538 ASSERT_TRUE(embedded_test_server()->Start());
539
540 // Provide custom storage partition for test sites.
541 GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
542 BrowserContext* browser_context =
543 ShellContentBrowserClient::Get()->browser_context();
544 scoped_refptr<SiteInstance> test_site_instance =
545 SiteInstance::Create(browser_context)->GetRelatedSiteInstance(test_url);
546 GURL test_site = test_site_instance->GetSiteURL();
547 CustomStoragePartitionForSomeSites modified_client(test_site);
548 ContentBrowserClient* old_client =
549 SetBrowserClientForTesting(&modified_client);
550 StoragePartition* default_storage =
551 BrowserContext::GetDefaultStoragePartition(browser_context);
552 StoragePartition* custom_storage =
553 BrowserContext::GetStoragePartitionForSite(browser_context, test_site);
554 EXPECT_NE(default_storage, custom_storage);
555
556 // Open a test window - it should be associated with the default storage
557 // partition.
558 Shell* window = CreateBrowser();
559 RenderProcessHost* old_process =
560 window->web_contents()->GetMainFrame()->GetProcess();
561 EXPECT_EQ(default_storage, old_process->GetStoragePartition());
562
563 // Warm up the spare process - it should be associated with the default
564 // storage partition.
565 RenderProcessHost::WarmupSpareRenderProcessHost(browser_context);
566 RenderProcessHost* spare_renderer =
567 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
568 ASSERT_TRUE(spare_renderer);
569 EXPECT_EQ(default_storage, spare_renderer->GetStoragePartition());
570
571 // Navigate to a URL that requires a custom storage partition.
572 EXPECT_TRUE(NavigateToURL(window, test_url));
573 RenderProcessHost* new_process =
574 window->web_contents()->GetMainFrame()->GetProcess();
575 // Requirement to use a custom storage partition should force a process swap.
576 EXPECT_NE(new_process, old_process);
577 // The new process should be associated with the custom storage partition.
578 EXPECT_EQ(custom_storage, new_process->GetStoragePartition());
579 // And consequently, the spare shouldn't have been used.
580 EXPECT_NE(spare_renderer, new_process);
581
582 // Restore the original ContentBrowserClient.
583 SetBrowserClientForTesting(old_client);
584 }
585
586 class RenderProcessHostObserverCounter : public RenderProcessHostObserver {
587 public:
RenderProcessHostObserverCounter(RenderProcessHost * host)588 explicit RenderProcessHostObserverCounter(RenderProcessHost* host) {
589 host->AddObserver(this);
590 observing_ = true;
591 observed_host_ = host;
592 }
593
~RenderProcessHostObserverCounter()594 ~RenderProcessHostObserverCounter() override {
595 if (observing_)
596 observed_host_->RemoveObserver(this);
597 }
598
RenderProcessExited(RenderProcessHost * host,const ChildProcessTerminationInfo & info)599 void RenderProcessExited(RenderProcessHost* host,
600 const ChildProcessTerminationInfo& info) override {
601 DCHECK(observing_);
602 DCHECK_EQ(host, observed_host_);
603 exited_count_++;
604 }
605
RenderProcessHostDestroyed(RenderProcessHost * host)606 void RenderProcessHostDestroyed(RenderProcessHost* host) override {
607 DCHECK(observing_);
608 DCHECK_EQ(host, observed_host_);
609 destroyed_count_++;
610
611 host->RemoveObserver(this);
612 observing_ = false;
613 observed_host_ = nullptr;
614 }
615
exited_count() const616 int exited_count() const { return exited_count_; }
destroyed_count() const617 int destroyed_count() const { return destroyed_count_; }
618
619 private:
620 int exited_count_ = 0;
621 int destroyed_count_ = 0;
622 bool observing_ = false;
623 RenderProcessHost* observed_host_ = nullptr;
624
625 DISALLOW_COPY_AND_ASSIGN(RenderProcessHostObserverCounter);
626 };
627
628 // Check that the spare renderer is properly destroyed via
629 // DisableKeepAliveRefCount.
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,SpareVsDisableKeepAliveRefCount)630 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareVsDisableKeepAliveRefCount) {
631 RenderProcessHost::WarmupSpareRenderProcessHost(
632 ShellContentBrowserClient::Get()->browser_context());
633 base::RunLoop().RunUntilIdle();
634
635 RenderProcessHost* spare_renderer =
636 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
637 RenderProcessHostObserverCounter counter(spare_renderer);
638
639 RenderProcessHostWatcher process_watcher(
640 spare_renderer, RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
641
642 spare_renderer->DisableKeepAliveRefCount();
643
644 process_watcher.Wait();
645 EXPECT_TRUE(process_watcher.did_exit_normally());
646
647 // An important part of test verification is that UaF doesn't happen in the
648 // next revolution of the message pump - without extra care in the
649 // SpareRenderProcessHostManager RenderProcessHost::Cleanup could be called
650 // twice leading to a crash caused by double-free flavour of UaF in
651 // base::DeleteHelper<...>::DoDelete.
652 base::RunLoop().RunUntilIdle();
653
654 DCHECK_EQ(1, counter.exited_count());
655 DCHECK_EQ(1, counter.destroyed_count());
656 }
657
658 // Check that the spare renderer is properly destroyed via
659 // DisableKeepAliveRefCount.
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,SpareVsFastShutdown)660 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, SpareVsFastShutdown) {
661 RenderProcessHost::WarmupSpareRenderProcessHost(
662 ShellContentBrowserClient::Get()->browser_context());
663 base::RunLoop().RunUntilIdle();
664
665 RenderProcessHost* spare_renderer =
666 RenderProcessHostImpl::GetSpareRenderProcessHostForTesting();
667 RenderProcessHostObserverCounter counter(spare_renderer);
668
669 RenderProcessHostWatcher process_watcher(
670 spare_renderer, RenderProcessHostWatcher::WATCH_FOR_HOST_DESTRUCTION);
671
672 spare_renderer->FastShutdownIfPossible();
673
674 process_watcher.Wait();
675 EXPECT_FALSE(process_watcher.did_exit_normally());
676
677 // An important part of test verification is that UaF doesn't happen in the
678 // next revolution of the message pump - without extra care in the
679 // SpareRenderProcessHostManager RenderProcessHost::Cleanup could be called
680 // twice leading to a crash caused by double-free flavour of UaF in
681 // base::DeleteHelper<...>::DoDelete.
682 base::RunLoop().RunUntilIdle();
683
684 DCHECK_EQ(1, counter.exited_count());
685 DCHECK_EQ(1, counter.destroyed_count());
686 }
687
688 class ShellCloser : public RenderProcessHostObserver {
689 public:
ShellCloser(Shell * shell,std::string * logging_string)690 ShellCloser(Shell* shell, std::string* logging_string)
691 : shell_(shell), logging_string_(logging_string) {}
692
693 protected:
694 // RenderProcessHostObserver:
RenderProcessExited(RenderProcessHost * host,const ChildProcessTerminationInfo & info)695 void RenderProcessExited(RenderProcessHost* host,
696 const ChildProcessTerminationInfo& info) override {
697 logging_string_->append("ShellCloser::RenderProcessExited ");
698 shell_->Close();
699 }
700
RenderProcessHostDestroyed(RenderProcessHost * host)701 void RenderProcessHostDestroyed(RenderProcessHost* host) override {
702 logging_string_->append("ShellCloser::RenderProcessHostDestroyed ");
703 }
704
705 Shell* shell_;
706 std::string* logging_string_;
707 };
708
709 class ObserverLogger : public RenderProcessHostObserver {
710 public:
ObserverLogger(std::string * logging_string)711 explicit ObserverLogger(std::string* logging_string)
712 : logging_string_(logging_string), host_destroyed_(false) {}
713
host_destroyed()714 bool host_destroyed() { return host_destroyed_; }
715
716 protected:
717 // RenderProcessHostObserver:
RenderProcessExited(RenderProcessHost * host,const ChildProcessTerminationInfo & info)718 void RenderProcessExited(RenderProcessHost* host,
719 const ChildProcessTerminationInfo& info) override {
720 logging_string_->append("ObserverLogger::RenderProcessExited ");
721 }
722
RenderProcessHostDestroyed(RenderProcessHost * host)723 void RenderProcessHostDestroyed(RenderProcessHost* host) override {
724 logging_string_->append("ObserverLogger::RenderProcessHostDestroyed ");
725 host_destroyed_ = true;
726 }
727
728 std::string* logging_string_;
729 bool host_destroyed_;
730 };
731
732 // Flaky on Android. http://crbug.com/759514.
733 #if defined(OS_ANDROID)
734 #define MAYBE_AllProcessExitedCallsBeforeAnyHostDestroyedCalls \
735 DISABLED_AllProcessExitedCallsBeforeAnyHostDestroyedCalls
736 #else
737 #define MAYBE_AllProcessExitedCallsBeforeAnyHostDestroyedCalls \
738 AllProcessExitedCallsBeforeAnyHostDestroyedCalls
739 #endif
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,MAYBE_AllProcessExitedCallsBeforeAnyHostDestroyedCalls)740 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
741 MAYBE_AllProcessExitedCallsBeforeAnyHostDestroyedCalls) {
742 ASSERT_TRUE(embedded_test_server()->Start());
743
744 GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
745 EXPECT_TRUE(NavigateToURL(shell(), test_url));
746
747 std::string logging_string;
748 ShellCloser shell_closer(shell(), &logging_string);
749 ObserverLogger observer_logger(&logging_string);
750 RenderProcessHost* rph =
751 shell()->web_contents()->GetMainFrame()->GetProcess();
752
753 // Ensure that the ShellCloser observer is first, so that it will have first
754 // dibs on the ProcessExited callback.
755 rph->AddObserver(&shell_closer);
756 rph->AddObserver(&observer_logger);
757
758 // This will crash the render process, and start all the callbacks.
759 // We can't use NavigateToURL here since it accesses the shell() after
760 // navigating, which the shell_closer deletes.
761 ScopedAllowRendererCrashes scoped_allow_renderer_crashes(shell());
762 NavigateToURLBlockUntilNavigationsComplete(
763 shell(), GURL(kChromeUICrashURL), 1);
764
765 // The key here is that all the RenderProcessExited callbacks precede all the
766 // RenderProcessHostDestroyed callbacks.
767 EXPECT_EQ("ShellCloser::RenderProcessExited "
768 "ObserverLogger::RenderProcessExited "
769 "ShellCloser::RenderProcessHostDestroyed "
770 "ObserverLogger::RenderProcessHostDestroyed ", logging_string);
771
772 // If the test fails, and somehow the RPH is still alive somehow, at least
773 // deregister the observers so that the test fails and doesn't also crash.
774 if (!observer_logger.host_destroyed()) {
775 rph->RemoveObserver(&shell_closer);
776 rph->RemoveObserver(&observer_logger);
777 }
778 }
779
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,KillProcessOnBadMojoMessage)780 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessOnBadMojoMessage) {
781 ASSERT_TRUE(embedded_test_server()->Start());
782
783 GURL test_url = embedded_test_server()->GetURL("/simple_page.html");
784 EXPECT_TRUE(NavigateToURL(shell(), test_url));
785 RenderProcessHost* rph =
786 shell()->web_contents()->GetMainFrame()->GetProcess();
787
788 host_destructions_ = 0;
789 process_exits_ = 0;
790 rph->AddObserver(this);
791
792 mojo::Remote<mojom::TestService> service;
793 rph->BindReceiver(service.BindNewPipeAndPassReceiver());
794
795 base::RunLoop run_loop;
796 set_process_exit_callback(run_loop.QuitClosure());
797
798 // Should reply with a bad message and cause process death.
799 {
800 ScopedAllowRendererCrashes scoped_allow_renderer_crashes(rph);
801 service->DoSomething(base::DoNothing());
802 run_loop.Run();
803 }
804
805 EXPECT_EQ(1, process_exits_);
806 EXPECT_EQ(0, host_destructions_);
807 if (!host_destructions_)
808 rph->RemoveObserver(this);
809 }
810
811 // Observes a WebContents and a specific frame within it, and waits until they
812 // both indicate that they are audible.
813 class AudioStartObserver : public WebContentsObserver {
814 public:
AudioStartObserver(WebContents * web_contents,RenderFrameHost * render_frame_host,base::OnceClosure audible_closure)815 AudioStartObserver(WebContents* web_contents,
816 RenderFrameHost* render_frame_host,
817 base::OnceClosure audible_closure)
818 : WebContentsObserver(web_contents),
819 render_frame_host_(
820 static_cast<RenderFrameHostImpl*>(render_frame_host)),
821 contents_audible_(web_contents->IsCurrentlyAudible()),
822 frame_audible_(render_frame_host_->is_audible()),
823 audible_closure_(std::move(audible_closure)) {
824 MaybeFireClosure();
825 }
826 ~AudioStartObserver() override = default;
827
828 // WebContentsObserver:
OnAudioStateChanged(bool audible)829 void OnAudioStateChanged(bool audible) override {
830 DCHECK_NE(audible, contents_audible_);
831 contents_audible_ = audible;
832 MaybeFireClosure();
833 }
OnFrameAudioStateChanged(RenderFrameHost * render_frame_host,bool audible)834 void OnFrameAudioStateChanged(RenderFrameHost* render_frame_host,
835 bool audible) override {
836 if (render_frame_host_ != render_frame_host)
837 return;
838 DCHECK_NE(frame_audible_, audible);
839 frame_audible_ = audible;
840 MaybeFireClosure();
841 }
842
843 private:
MaybeFireClosure()844 void MaybeFireClosure() {
845 if (contents_audible_ && frame_audible_)
846 std::move(audible_closure_).Run();
847 }
848
849 RenderFrameHostImpl* render_frame_host_ = nullptr;
850 bool contents_audible_ = false;
851 bool frame_audible_ = false;
852 base::OnceClosure audible_closure_;
853 };
854
855 // Tests that audio stream counts (used for process priority calculations) are
856 // properly set and cleared during media playback and renderer terminations.
857 //
858 // Note: This test can't run when the Mojo Renderer is used since it does not
859 // create audio streams through the normal audio pathways; at present this is
860 // only used by Chromecast.
861 //
862 // crbug.com/864476: flaky on Android for unclear reasons.
863 #if BUILDFLAG(ENABLE_MOJO_RENDERER) || defined(OS_ANDROID)
864 #define KillProcessZerosAudioStreams DISABLED_KillProcessZerosAudioStreams
865 #endif
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,KillProcessZerosAudioStreams)866 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KillProcessZerosAudioStreams) {
867 // TODO(maxmorin): This test only uses an output stream. There should be a
868 // similar test for input streams.
869 embedded_test_server()->ServeFilesFromSourceDirectory(
870 media::GetTestDataPath());
871 ASSERT_TRUE(embedded_test_server()->Start());
872 ASSERT_TRUE(NavigateToURL(
873 shell(), embedded_test_server()->GetURL("/webaudio_oscillator.html")));
874 RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
875 shell()->web_contents()->GetMainFrame()->GetProcess());
876
877 {
878 // Start audio and wait for it to become audible, in both the frame *and*
879 // the page.
880 base::RunLoop run_loop;
881 AudioStartObserver observer(shell()->web_contents(),
882 shell()->web_contents()->GetMainFrame(),
883 run_loop.QuitClosure());
884
885 std::string result;
886 EXPECT_TRUE(
887 ExecuteScriptAndExtractString(shell(), "StartOscillator();", &result))
888 << "Failed to execute javascript.";
889 run_loop.Run();
890
891 // No point in running the rest of the test if this is wrong.
892 ASSERT_EQ(1, rph->get_media_stream_count_for_testing());
893 }
894
895 host_destructions_ = 0;
896 process_exits_ = 0;
897 rph->AddObserver(this);
898
899 mojo::Remote<mojom::TestService> service;
900 rph->BindReceiver(service.BindNewPipeAndPassReceiver());
901
902 {
903 // Force a bad message event to occur which will terminate the renderer.
904 // Note: We post task the QuitClosure since RenderProcessExited() is called
905 // before destroying BrowserMessageFilters; and the next portion of the test
906 // must run after these notifications have been delivered.
907 ScopedAllowRendererCrashes scoped_allow_renderer_crashes(rph);
908 base::RunLoop run_loop;
909 set_process_exit_callback(media::BindToCurrentLoop(run_loop.QuitClosure()));
910 service->DoSomething(base::DoNothing());
911 run_loop.Run();
912 }
913
914 {
915 // Cycle UI and IO loop once to ensure OnChannelClosing() has been delivered
916 // to audio stream owners and they get a chance to notify of stream closure.
917 base::RunLoop run_loop;
918 GetIOThreadTaskRunner({})->PostTask(
919 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
920 run_loop.Run();
921 }
922
923 // Verify shutdown went as expected.
924 EXPECT_EQ(0, rph->get_media_stream_count_for_testing());
925 EXPECT_EQ(1, process_exits_);
926 EXPECT_EQ(0, host_destructions_);
927 if (!host_destructions_)
928 rph->RemoveObserver(this);
929 }
930
931 // Test class instance to run specific setup steps for capture streams.
932 class CaptureStreamRenderProcessHostTest : public RenderProcessHostTest {
933 public:
SetUp()934 void SetUp() override {
935 // Pixel output is needed when digging pixel values out of video tags for
936 // verification in VideoCaptureStream tests.
937 EnablePixelOutput();
938 RenderProcessHostTest::SetUp();
939 }
940
SetUpCommandLine(base::CommandLine * command_line)941 void SetUpCommandLine(base::CommandLine* command_line) override {
942 // These flags are necessary to emulate camera input for getUserMedia()
943 // tests.
944 command_line->AppendSwitch(switches::kUseFakeUIForMediaStream);
945 RenderProcessHostTest::SetUpCommandLine(command_line);
946 }
947 };
948
949 // Tests that video capture stream count increments when getUserMedia() is
950 // called.
IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,GetUserMediaIncrementsVideoCaptureStreams)951 IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
952 GetUserMediaIncrementsVideoCaptureStreams) {
953 ASSERT_TRUE(embedded_test_server()->Start());
954 EXPECT_TRUE(NavigateToURL(
955 shell(), embedded_test_server()->GetURL("/media/getusermedia.html")));
956 RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
957 shell()->web_contents()->GetMainFrame()->GetProcess());
958 std::string result;
959 EXPECT_TRUE(ExecuteScriptAndExtractString(
960 shell(), "getUserMediaAndExpectSuccess({video: true});", &result))
961 << "Failed to execute javascript.";
962 EXPECT_EQ(1, rph->get_media_stream_count_for_testing());
963 }
964
965 // Tests that video capture stream count resets when getUserMedia() is called
966 // and stopped.
IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,StopResetsVideoCaptureStreams)967 IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
968 StopResetsVideoCaptureStreams) {
969 ASSERT_TRUE(embedded_test_server()->Start());
970 EXPECT_TRUE(NavigateToURL(
971 shell(), embedded_test_server()->GetURL("/media/getusermedia.html")));
972 RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
973 shell()->web_contents()->GetMainFrame()->GetProcess());
974 std::string result;
975 EXPECT_TRUE(ExecuteScriptAndExtractString(
976 shell(), "getUserMediaAndStop({video: true});", &result))
977 << "Failed to execute javascript.";
978 EXPECT_EQ(0, rph->get_media_stream_count_for_testing());
979 }
980
981 // Tests that video capture stream counts (used for process priority
982 // calculations) are properly set and cleared during media playback and renderer
983 // terminations.
IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,KillProcessZerosVideoCaptureStreams)984 IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
985 KillProcessZerosVideoCaptureStreams) {
986 ASSERT_TRUE(embedded_test_server()->Start());
987 EXPECT_TRUE(NavigateToURL(
988 shell(), embedded_test_server()->GetURL("/media/getusermedia.html")));
989 RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
990 shell()->web_contents()->GetMainFrame()->GetProcess());
991 std::string result;
992 EXPECT_TRUE(ExecuteScriptAndExtractString(
993 shell(), "getUserMediaAndExpectSuccess({video: true});", &result))
994 << "Failed to execute javascript.";
995 EXPECT_EQ(1, rph->get_media_stream_count_for_testing());
996
997 host_destructions_ = 0;
998 process_exits_ = 0;
999 rph->AddObserver(this);
1000
1001 mojo::Remote<mojom::TestService> service;
1002 rph->BindReceiver(service.BindNewPipeAndPassReceiver());
1003
1004 {
1005 // Force a bad message event to occur which will terminate the renderer.
1006 ScopedAllowRendererCrashes scoped_allow_renderer_crashes(rph);
1007 base::RunLoop run_loop;
1008 set_process_exit_callback(media::BindToCurrentLoop(run_loop.QuitClosure()));
1009 service->DoSomething(base::DoNothing());
1010 run_loop.Run();
1011 }
1012
1013 {
1014 // Cycle UI and IO loop once to ensure OnChannelClosing() has been delivered
1015 // to audio stream owners and they get a chance to notify of stream closure.
1016 base::RunLoop run_loop;
1017 GetIOThreadTaskRunner({})->PostTask(
1018 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
1019 run_loop.Run();
1020 }
1021
1022 EXPECT_EQ(0, rph->get_media_stream_count_for_testing());
1023 EXPECT_EQ(1, process_exits_);
1024 EXPECT_EQ(0, host_destructions_);
1025 if (!host_destructions_)
1026 rph->RemoveObserver(this);
1027 }
1028
1029 // Tests that media stream count increments when getUserMedia() is
1030 // called with audio only.
IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,GetUserMediaAudioOnlyIncrementsMediaStreams)1031 IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
1032 GetUserMediaAudioOnlyIncrementsMediaStreams) {
1033 ASSERT_TRUE(embedded_test_server()->Start());
1034 EXPECT_TRUE(NavigateToURL(
1035 shell(), embedded_test_server()->GetURL("/media/getusermedia.html")));
1036 RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
1037 shell()->web_contents()->GetMainFrame()->GetProcess());
1038 std::string result;
1039 EXPECT_TRUE(ExecuteScriptAndExtractString(
1040 shell(), "getUserMediaAndExpectSuccess({video: false, audio: true});",
1041 &result))
1042 << "Failed to execute javascript.";
1043 EXPECT_EQ(1, rph->get_media_stream_count_for_testing());
1044 }
1045
1046 // Tests that media stream counts (used for process priority
1047 // calculations) are properly set and cleared during media playback and renderer
1048 // terminations for audio only streams.
IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,KillProcessZerosAudioCaptureStreams)1049 IN_PROC_BROWSER_TEST_F(CaptureStreamRenderProcessHostTest,
1050 KillProcessZerosAudioCaptureStreams) {
1051 ASSERT_TRUE(embedded_test_server()->Start());
1052 EXPECT_TRUE(NavigateToURL(
1053 shell(), embedded_test_server()->GetURL("/media/getusermedia.html")));
1054 RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
1055 shell()->web_contents()->GetMainFrame()->GetProcess());
1056 std::string result;
1057 EXPECT_TRUE(ExecuteScriptAndExtractString(
1058 shell(), "getUserMediaAndExpectSuccess({video: false, audio: true});",
1059 &result))
1060 << "Failed to execute javascript.";
1061 EXPECT_EQ(1, rph->get_media_stream_count_for_testing());
1062
1063 host_destructions_ = 0;
1064 process_exits_ = 0;
1065 rph->AddObserver(this);
1066
1067 mojo::Remote<mojom::TestService> service;
1068 rph->BindReceiver(service.BindNewPipeAndPassReceiver());
1069
1070 {
1071 // Force a bad message event to occur which will terminate the renderer.
1072 ScopedAllowRendererCrashes scoped_allow_renderer_crashes(rph);
1073 base::RunLoop run_loop;
1074 set_process_exit_callback(media::BindToCurrentLoop(run_loop.QuitClosure()));
1075 service->DoSomething(base::DoNothing());
1076 run_loop.Run();
1077 }
1078
1079 {
1080 // Cycle UI and IO loop once to ensure OnChannelClosing() has been delivered
1081 // to audio stream owners and they get a chance to notify of stream closure.
1082 base::RunLoop run_loop;
1083 GetIOThreadTaskRunner({})->PostTask(
1084 FROM_HERE, media::BindToCurrentLoop(run_loop.QuitClosure()));
1085 run_loop.Run();
1086 }
1087
1088 EXPECT_EQ(0, rph->get_media_stream_count_for_testing());
1089 EXPECT_EQ(1, process_exits_);
1090 EXPECT_EQ(0, host_destructions_);
1091 if (!host_destructions_)
1092 rph->RemoveObserver(this);
1093 }
1094
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,KeepAliveRendererProcess)1095 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, KeepAliveRendererProcess) {
1096 embedded_test_server()->RegisterRequestHandler(
1097 base::BindRepeating(HandleBeacon));
1098 ASSERT_TRUE(embedded_test_server()->Start());
1099
1100 if (AreDefaultSiteInstancesEnabled()) {
1101 // Isolate "foo.com" so we are guaranteed that navigations to this site
1102 // will be in a different process.
1103 IsolateOriginsForTesting(embedded_test_server(), shell()->web_contents(),
1104 {"foo.com"});
1105 }
1106
1107 EXPECT_TRUE(NavigateToURL(
1108 shell(), embedded_test_server()->GetURL("/send-beacon.html")));
1109
1110 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
1111 shell()->web_contents()->GetMainFrame());
1112 RenderProcessHostImpl* rph =
1113 static_cast<RenderProcessHostImpl*>(rfh->GetProcess());
1114
1115 // Disable the BackForwardCache to ensure the old process is going to be
1116 // released.
1117 DisableBackForwardCacheForTesting(shell()->web_contents(),
1118 BackForwardCache::TEST_ASSUMES_NO_CACHING);
1119
1120 host_destructions_ = 0;
1121 process_exits_ = 0;
1122 rph->AddObserver(this);
1123 rfh->SetKeepAliveTimeoutForTesting(base::TimeDelta::FromSeconds(30));
1124
1125 // Navigate to a site that will be in a different process.
1126 base::TimeTicks start = base::TimeTicks::Now();
1127 EXPECT_TRUE(NavigateToURL(
1128 shell(), embedded_test_server()->GetURL("foo.com", "/title1.html")));
1129
1130 WaitUntilProcessExits(1);
1131
1132 EXPECT_LT(base::TimeTicks::Now() - start, base::TimeDelta::FromSeconds(30));
1133 if (!host_destructions_)
1134 rph->RemoveObserver(this);
1135 }
1136
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,KeepAliveRendererProcessWithServiceWorker)1137 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
1138 KeepAliveRendererProcessWithServiceWorker) {
1139 base::RunLoop run_loop;
1140 embedded_test_server()->RegisterRequestHandler(
1141 base::BindRepeating(HandleHungBeacon, run_loop.QuitClosure()));
1142 ASSERT_TRUE(embedded_test_server()->Start());
1143
1144 EXPECT_TRUE(NavigateToURL(
1145 shell(),
1146 embedded_test_server()->GetURL("/workers/service_worker_setup.html")));
1147 EXPECT_EQ("ok", EvalJs(shell(), "setup();"));
1148
1149 RenderProcessHostImpl* rph = static_cast<RenderProcessHostImpl*>(
1150 shell()->web_contents()->GetMainFrame()->GetProcess());
1151 // 1 for the service worker.
1152 EXPECT_EQ(rph->keep_alive_ref_count(), 1u);
1153
1154 // We use /workers/send-beacon.html, not send-beacon.html, due to the
1155 // service worker scope rule.
1156 EXPECT_TRUE(NavigateToURL(
1157 shell(), embedded_test_server()->GetURL("/workers/send-beacon.html")));
1158
1159 run_loop.Run();
1160 // We are still using the same process.
1161 ASSERT_EQ(shell()->web_contents()->GetMainFrame()->GetProcess(), rph);
1162 // 1 for the service worker, 1 for the keepalive fetch.
1163 EXPECT_EQ(rph->keep_alive_ref_count(), 2u);
1164 }
1165
1166 // Test is flaky on Android builders: https://crbug.com/875179
1167 #if defined(OS_ANDROID)
1168 #define MAYBE_KeepAliveRendererProcess_Hung \
1169 DISABLED_KeepAliveRendererProcess_Hung
1170 #else
1171 #define MAYBE_KeepAliveRendererProcess_Hung KeepAliveRendererProcess_Hung
1172 #endif
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,MAYBE_KeepAliveRendererProcess_Hung)1173 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
1174 MAYBE_KeepAliveRendererProcess_Hung) {
1175 embedded_test_server()->RegisterRequestHandler(
1176 base::BindRepeating(HandleHungBeacon, base::RepeatingClosure()));
1177 ASSERT_TRUE(embedded_test_server()->Start());
1178
1179 EXPECT_TRUE(NavigateToURL(
1180 shell(), embedded_test_server()->GetURL("/send-beacon.html")));
1181
1182 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
1183 shell()->web_contents()->GetMainFrame());
1184 RenderProcessHostImpl* rph =
1185 static_cast<RenderProcessHostImpl*>(rfh->GetProcess());
1186
1187 host_destructions_ = 0;
1188 process_exits_ = 0;
1189 rph->AddObserver(this);
1190 rfh->SetKeepAliveTimeoutForTesting(base::TimeDelta::FromSeconds(1));
1191
1192 base::TimeTicks start = base::TimeTicks::Now();
1193 EXPECT_TRUE(NavigateToURL(shell(), GURL("data:text/html,<p>hello</p>")));
1194
1195 WaitUntilProcessExits(1);
1196
1197 EXPECT_GE(base::TimeTicks::Now() - start, base::TimeDelta::FromSeconds(1));
1198 if (!host_destructions_)
1199 rph->RemoveObserver(this);
1200 }
1201
1202 // Test is flaky on Android builders: https://crbug.com/875179
1203 #if defined(OS_ANDROID)
1204 #define MAYBE_FetchKeepAliveRendererProcess_Hung \
1205 DISABLED_FetchKeepAliveRendererProcess_Hung
1206 #else
1207 #define MAYBE_FetchKeepAliveRendererProcess_Hung \
1208 FetchKeepAliveRendererProcess_Hung
1209 #endif
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,MAYBE_FetchKeepAliveRendererProcess_Hung)1210 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,
1211 MAYBE_FetchKeepAliveRendererProcess_Hung) {
1212 embedded_test_server()->RegisterRequestHandler(
1213 base::BindRepeating(HandleHungBeacon, base::RepeatingClosure()));
1214 ASSERT_TRUE(embedded_test_server()->Start());
1215
1216 EXPECT_TRUE(NavigateToURL(
1217 shell(), embedded_test_server()->GetURL("/fetch-keepalive.html")));
1218
1219 RenderFrameHostImpl* rfh = static_cast<RenderFrameHostImpl*>(
1220 shell()->web_contents()->GetMainFrame());
1221 RenderProcessHostImpl* rph =
1222 static_cast<RenderProcessHostImpl*>(rfh->GetProcess());
1223
1224 host_destructions_ = 0;
1225 process_exits_ = 0;
1226 rph->AddObserver(this);
1227 rfh->SetKeepAliveTimeoutForTesting(base::TimeDelta::FromSeconds(1));
1228
1229 base::TimeTicks start = base::TimeTicks::Now();
1230 EXPECT_TRUE(NavigateToURL(shell(), GURL("data:text/html,<p>hello</p>")));
1231
1232 WaitUntilProcessExits(1);
1233
1234 EXPECT_GE(base::TimeTicks::Now() - start, base::TimeDelta::FromSeconds(1));
1235 if (!host_destructions_)
1236 rph->RemoveObserver(this);
1237 }
1238
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,ManyKeepaliveRequests)1239 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, ManyKeepaliveRequests) {
1240 auto resolver =
1241 base::MakeRefCounted<DelayedHttpResponseWithResolver::Resolver>();
1242 embedded_test_server()->RegisterRequestHandler(
1243 base::BindRepeating(HandleHungBeaconWithResolver, resolver));
1244 const base::string16 title = base::ASCIIToUTF16("Resolved");
1245 const base::string16 waiting = base::ASCIIToUTF16("Waiting");
1246
1247 ASSERT_TRUE(embedded_test_server()->Start());
1248 EXPECT_TRUE(NavigateToURL(
1249 shell(),
1250 embedded_test_server()->GetURL("/fetch-keepalive.html?requests=256")));
1251
1252 {
1253 // Wait for the page to make all the keepalive requests.
1254 TitleWatcher watcher(shell()->web_contents(), waiting);
1255 EXPECT_EQ(waiting, watcher.WaitAndGetTitle());
1256 }
1257
1258 resolver->Resolve();
1259
1260 {
1261 TitleWatcher watcher(shell()->web_contents(), title);
1262 EXPECT_EQ(title, watcher.WaitAndGetTitle());
1263 }
1264 }
1265
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,TooManyKeepaliveRequests)1266 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, TooManyKeepaliveRequests) {
1267 embedded_test_server()->RegisterRequestHandler(
1268 base::BindRepeating(HandleHungBeacon, base::RepeatingClosure()));
1269 ASSERT_TRUE(embedded_test_server()->Start());
1270 const base::string16 title = base::ASCIIToUTF16("Rejected");
1271
1272 TitleWatcher watcher(shell()->web_contents(), title);
1273
1274 EXPECT_TRUE(NavigateToURL(
1275 shell(),
1276 embedded_test_server()->GetURL("/fetch-keepalive.html?requests=257")));
1277
1278 EXPECT_EQ(title, watcher.WaitAndGetTitle());
1279 }
1280
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,LowPriorityFramesDisabled)1281 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, LowPriorityFramesDisabled) {
1282 // RenderProcessHostImpl::UpdateProcessPriority has an early check of
1283 // run_renderer_in_process and exits for RenderProcessHosts without a child
1284 // process launcher. In order to skip initializing that here and the layer of
1285 // indirection, we explicitly run in-process, which we must also disable once
1286 // the test has finished to prevent crashing on exit.
1287 RenderProcessHost::SetRunRendererInProcess(true);
1288 RenderProcessHostImpl* process = static_cast<RenderProcessHostImpl*>(
1289 RenderProcessHostImpl::CreateRenderProcessHost(
1290 ShellContentBrowserClient::Get()->browser_context(), nullptr));
1291 // It starts off as normal priority.
1292 EXPECT_FALSE(process->IsProcessBackgrounded());
1293 // With the feature off it stays low priority when adding low priority frames.
1294 process->UpdateFrameWithPriority(base::nullopt,
1295 RenderProcessHostImpl::FramePriority::kLow);
1296 process->UpdateFrameWithPriority(base::nullopt,
1297 RenderProcessHostImpl::FramePriority::kLow);
1298 EXPECT_FALSE(process->IsProcessBackgrounded());
1299 RenderProcessHost::SetRunRendererInProcess(false);
1300 }
1301
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,PriorityOverride)1302 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, PriorityOverride) {
1303 // RenderProcessHostImpl::UpdateProcessPriority has an early check of
1304 // run_renderer_in_process and exits for RenderProcessHosts without a child
1305 // process launcher. In order to skip initializing that here and the layer of
1306 // indirection, we explicitly run in-process, which we must also disable once
1307 // the test has finished to prevent crashing on exit.
1308 RenderProcessHost::SetRunRendererInProcess(true);
1309 RenderProcessHostImpl* process = static_cast<RenderProcessHostImpl*>(
1310 RenderProcessHostImpl::CreateRenderProcessHost(
1311 ShellContentBrowserClient::Get()->browser_context(), nullptr));
1312
1313 // It starts off as normal priority with no override.
1314 EXPECT_FALSE(process->HasPriorityOverride());
1315 EXPECT_FALSE(process->IsProcessBackgrounded());
1316
1317 process->SetPriorityOverride(false /* foreground */);
1318 EXPECT_TRUE(process->HasPriorityOverride());
1319 EXPECT_TRUE(process->IsProcessBackgrounded());
1320
1321 process->SetPriorityOverride(true /* foreground */);
1322 EXPECT_TRUE(process->HasPriorityOverride());
1323 EXPECT_FALSE(process->IsProcessBackgrounded());
1324
1325 process->SetPriorityOverride(false /* foreground */);
1326 EXPECT_TRUE(process->HasPriorityOverride());
1327 EXPECT_TRUE(process->IsProcessBackgrounded());
1328
1329 // Add a pending view, and expect the process to *stay* backgrounded.
1330 process->AddPendingView();
1331 EXPECT_TRUE(process->HasPriorityOverride());
1332 EXPECT_TRUE(process->IsProcessBackgrounded());
1333
1334 // Clear the override. The pending view should cause the process to go back to
1335 // being foregrounded.
1336 process->ClearPriorityOverride();
1337 EXPECT_FALSE(process->HasPriorityOverride());
1338 EXPECT_FALSE(process->IsProcessBackgrounded());
1339
1340 // Clear the pending view so the test doesn't explode.
1341 process->RemovePendingView();
1342 EXPECT_FALSE(process->HasPriorityOverride());
1343 EXPECT_TRUE(process->IsProcessBackgrounded());
1344
1345 RenderProcessHost::SetRunRendererInProcess(false);
1346 }
1347
1348 // This test verifies properties of RenderProcessHostImpl *before* Init method
1349 // is called.
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,ConstructedButNotInitializedYet)1350 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, ConstructedButNotInitializedYet) {
1351 RenderProcessHost* process = RenderProcessHostImpl::CreateRenderProcessHost(
1352 ShellContentBrowserClient::Get()->browser_context(), nullptr);
1353
1354 // Just verifying that the arguments of CreateRenderProcessHost got processed
1355 // correctly.
1356 EXPECT_EQ(ShellContentBrowserClient::Get()->browser_context(),
1357 process->GetBrowserContext());
1358 EXPECT_FALSE(process->IsForGuestsOnly());
1359
1360 // There should be no OS process before Init() method is called.
1361 EXPECT_FALSE(process->IsInitializedAndNotDead());
1362 EXPECT_FALSE(process->IsReady());
1363 EXPECT_FALSE(process->GetProcess().IsValid());
1364 EXPECT_EQ(base::kNullProcessHandle, process->GetProcess().Handle());
1365
1366 // TODO(lukasza): https://crbug.com/813045: RenderProcessHost shouldn't have
1367 // an associated IPC channel (and shouldn't accumulate IPC messages) unless
1368 // the Init() method was called and the RPH either has connection to an actual
1369 // OS process or is currently attempting to spawn the OS process. After this
1370 // bug is fixed the 1st test assertion below should be reversed (unsure about
1371 // the 2nd one).
1372 EXPECT_TRUE(process->GetChannel());
1373 EXPECT_TRUE(process->GetRendererInterface());
1374
1375 // Cleanup the resources acquired by the test.
1376 process->Cleanup();
1377 }
1378
1379 // This test verifies that a fast shutdown is possible for a starting process.
IN_PROC_BROWSER_TEST_F(RenderProcessHostTest,FastShutdownForStartingProcess)1380 IN_PROC_BROWSER_TEST_F(RenderProcessHostTest, FastShutdownForStartingProcess) {
1381 RenderProcessHost* process = RenderProcessHostImpl::CreateRenderProcessHost(
1382 ShellContentBrowserClient::Get()->browser_context(), nullptr);
1383 process->Init();
1384 EXPECT_TRUE(process->FastShutdownIfPossible());
1385 process->Cleanup();
1386 }
1387
1388 class RenderProcessHostFramePriorityTest : public RenderProcessHostTest {
1389 public:
1390 // Initialize the clock and set the fixture to use frame priority feature.
RenderProcessHostFramePriorityTest()1391 RenderProcessHostFramePriorityTest() {
1392 clock_ = std::make_unique<base::SimpleTestTickClock>();
1393 use_frame_priority_ = true;
1394 }
1395
1396 // Check the histograms at TearDown.
TearDown()1397 void TearDown() override {
1398 RenderProcessHostTest::TearDown();
1399 // TODO(crbug/1045958): Check the histograms directly in the tests.
1400 CheckHistograms();
1401 }
1402
1403 // Set the expected frame priorities seen and set TearDown check variable.
SetFramePrioritiesExpected(bool low,bool normal)1404 void SetFramePrioritiesExpected(bool low, bool normal) {
1405 low_priority_frames_expected_ = low;
1406 normal_priority_frames_expected_ = normal;
1407 check_frame_priorities_ = true;
1408 }
1409
1410 // Set the times expected at low priority and overall.
SetPriorityTimesExpected(base::TimeDelta low_time,base::TimeDelta total_time)1411 void SetPriorityTimesExpected(base::TimeDelta low_time,
1412 base::TimeDelta total_time) {
1413 low_priority_time_expected_ = low_time;
1414 total_time_expected_ = total_time;
1415 }
1416
1417 // Advance the internal clock for the RenderProcessHost.
AdvanceClock(base::TimeDelta time)1418 void AdvanceClock(base::TimeDelta time) { clock_->Advance(time); }
1419
1420 // Create the process with the test clock, initialize, and return it.
CreateAndInitializeProcess()1421 RenderProcessHostImpl* CreateAndInitializeProcess() {
1422 // RenderProcessHostImpl::UpdateProcessPriority has an early check of
1423 // run_renderer_in_process and exits for RenderProcessHosts without a child
1424 // process launcher. In order to skip initializing that here and the layer
1425 // of indirection, we explicitly run in-process, which we must also disable
1426 // once the test has finished to prevent crashing on exit.
1427 RenderProcessHostImpl::SetRunRendererInProcess(true);
1428 // Initialize the clock's value to the current time.
1429 clock_->SetNowTicks(base::TimeTicks::Now());
1430 // Create the process itself.
1431 process_ = static_cast<RenderProcessHostImpl*>(
1432 RenderProcessHostImpl::CreateRenderProcessHost(
1433 ShellContentBrowserClient::Get()->browser_context(), nullptr));
1434 // For these tests, assume something is always visible.
1435 SetVisibleClients(process_, 1);
1436 // Any advancement before Init is ignored.
1437 AdvanceClock(base::TimeDelta::FromSeconds(10));
1438 // Don't start an actual process, just initialize times.
1439 process_->SetClockForTesting(clock_.get());
1440 // When no frames are attached, it's not low priority.
1441 EXPECT_FALSE(process_->IsProcessBackgrounded());
1442 // Return it so it can be used by tests.
1443 return process_;
1444 }
1445
1446 // Shut down the created process.
ShutDownAndCleanUpProcess()1447 void ShutDownAndCleanUpProcess() {
1448 RenderProcessHostImpl::SetRunRendererInProcess(false);
1449 }
1450
1451 private:
1452 // Check the histograms related to frame priority and backgrounding.
CheckHistograms()1453 void CheckHistograms() {
1454 if (total_time_expected_ != base::TimeDelta()) {
1455 histogram_tester_.ExpectUniqueSample(
1456 "BrowserRenderProcessHost.TotalTime",
1457 total_time_expected_.InMilliseconds(), 1);
1458 histogram_tester_.ExpectUniqueSample(
1459 "BrowserRenderProcessHost.BackgroundTime",
1460 low_priority_time_expected_.InMilliseconds(), 1);
1461 }
1462
1463 if (!check_frame_priorities_)
1464 return;
1465
1466 if (low_priority_frames_expected_ && normal_priority_frames_expected_) {
1467 histogram_tester_.ExpectBucketCount(
1468 "BrowserRenderProcessHost.FramePrioritiesSeen",
1469 RenderProcessHostImpl::FramePrioritiesSeen::kMixedPrioritiesSeen, 1);
1470 } else if (low_priority_frames_expected_) {
1471 histogram_tester_.ExpectBucketCount(
1472 "BrowserRenderProcessHost.FramePrioritiesSeen",
1473 RenderProcessHostImpl::FramePrioritiesSeen::kOnlyLowPrioritiesSeen,
1474 1);
1475 } else if (normal_priority_frames_expected_) {
1476 histogram_tester_.ExpectBucketCount(
1477 "BrowserRenderProcessHost.FramePrioritiesSeen",
1478 RenderProcessHostImpl::FramePrioritiesSeen::kOnlyNormalPrioritiesSeen,
1479 1);
1480 } else {
1481 // Two are expected here because tests using this create their own
1482 // process, meaning the default process is never used/has no frames
1483 // attached.
1484 histogram_tester_.ExpectBucketCount(
1485 "BrowserRenderProcessHost.FramePrioritiesSeen",
1486 RenderProcessHostImpl::FramePrioritiesSeen::kNoFramesSeen, 2);
1487 }
1488 }
1489
1490 // The process that is created to add frames with various priorities.
1491 RenderProcessHostImpl* process_;
1492 // The histogram tester, to check backgrounding and priority histograms.
1493 base::HistogramTester histogram_tester_;
1494 // Whether frames with low priority have been attached to the process.
1495 bool low_priority_frames_expected_ = false;
1496 // Whether frames with normal priority have been attached to the process.
1497 bool normal_priority_frames_expected_ = false;
1498 // Whether we should check the frame priority histograms.
1499 bool check_frame_priorities_ = false;
1500 // The expected time a process hosts only low priority frames.
1501 base::TimeDelta low_priority_time_expected_;
1502 // The expected time a process hosts frames overall.
1503 base::TimeDelta total_time_expected_;
1504 // The clock that is used by the RenderProcessHost.
1505 std::unique_ptr<base::SimpleTestTickClock> clock_;
1506 };
1507
IN_PROC_BROWSER_TEST_F(RenderProcessHostFramePriorityTest,NoFramesSeenPriorityTest)1508 IN_PROC_BROWSER_TEST_F(RenderProcessHostFramePriorityTest,
1509 NoFramesSeenPriorityTest) {
1510 RenderProcessHostImpl* process = CreateAndInitializeProcess();
1511 DCHECK(process);
1512 ShutDownAndCleanUpProcess();
1513 SetFramePrioritiesExpected(false, false);
1514 }
1515
IN_PROC_BROWSER_TEST_F(RenderProcessHostFramePriorityTest,LowPriorityFramesEnabled)1516 IN_PROC_BROWSER_TEST_F(RenderProcessHostFramePriorityTest,
1517 LowPriorityFramesEnabled) {
1518 // When the process is first created with no frames, it's not low priority.
1519 RenderProcessHostImpl* process = CreateAndInitializeProcess();
1520 EXPECT_FALSE(process->IsProcessBackgrounded());
1521 AdvanceClock(base::TimeDelta::FromSeconds(1));
1522 // When all frames added are low priority, it's low priority.
1523 process->UpdateFrameWithPriority(base::nullopt,
1524 RenderProcessHostImpl::FramePriority::kLow);
1525 process->UpdateFrameWithPriority(base::nullopt,
1526 RenderProcessHostImpl::FramePriority::kLow);
1527 EXPECT_TRUE(process->IsProcessBackgrounded());
1528 AdvanceClock(base::TimeDelta::FromSeconds(2));
1529 // When all the low priority frames are removed, it's not low priority.
1530 process->UpdateFrameWithPriority(RenderProcessHostImpl::FramePriority::kLow,
1531 base::nullopt);
1532 process->UpdateFrameWithPriority(RenderProcessHostImpl::FramePriority::kLow,
1533 base::nullopt);
1534 EXPECT_FALSE(process->IsProcessBackgrounded());
1535 AdvanceClock(base::TimeDelta::FromSeconds(1));
1536 // When a low priority frame is added back in, it's low priority.
1537 process->UpdateFrameWithPriority(base::nullopt,
1538 RenderProcessHostImpl::FramePriority::kLow);
1539 EXPECT_TRUE(process->IsProcessBackgrounded());
1540 AdvanceClock(base::TimeDelta::FromSeconds(1));
1541 // As soon as a non-low priority frame is added, it's not low priority.
1542 process->UpdateFrameWithPriority(
1543 base::nullopt, RenderProcessHostImpl::FramePriority::kNormal);
1544 EXPECT_FALSE(process->IsProcessBackgrounded());
1545 AdvanceClock(base::TimeDelta::FromSeconds(1));
1546 // It remains not low priority even if we add more low priority frames.
1547 process->UpdateFrameWithPriority(base::nullopt,
1548 RenderProcessHostImpl::FramePriority::kLow);
1549 EXPECT_FALSE(process->IsProcessBackgrounded());
1550 AdvanceClock(base::TimeDelta::FromSeconds(1));
1551 // As soon as the non-low priority frame is removed, it becomes low priority.
1552 process->UpdateFrameWithPriority(
1553 RenderProcessHostImpl::FramePriority::kNormal, base::nullopt);
1554 EXPECT_TRUE(process->IsProcessBackgrounded());
1555 AdvanceClock(base::TimeDelta::FromSeconds(1));
1556 // Add a non-low priority frame, but then transition it to low, the process
1557 // should go from unbackgrounded to backgrounded.
1558 process->UpdateFrameWithPriority(
1559 base::nullopt, RenderProcessHostImpl::FramePriority::kNormal);
1560 EXPECT_FALSE(process->IsProcessBackgrounded());
1561 AdvanceClock(base::TimeDelta::FromSeconds(1));
1562 process->UpdateFrameWithPriority(
1563 RenderProcessHostImpl::FramePriority::kNormal,
1564 RenderProcessHostImpl::FramePriority::kLow);
1565 EXPECT_TRUE(process->IsProcessBackgrounded());
1566 AdvanceClock(base::TimeDelta::FromSeconds(2));
1567 // Transition the frame back to normal priority, it becomes normal priority.
1568 process->UpdateFrameWithPriority(
1569 RenderProcessHostImpl::FramePriority::kLow,
1570 RenderProcessHostImpl::FramePriority::kNormal);
1571 EXPECT_FALSE(process->IsProcessBackgrounded());
1572 AdvanceClock(base::TimeDelta::FromSeconds(1));
1573
1574 // This process has had low and normal priority frames attached to it.
1575 ShutDownAndCleanUpProcess();
1576 SetFramePrioritiesExpected(true, true);
1577 SetPriorityTimesExpected(base::TimeDelta::FromSeconds(6),
1578 base::TimeDelta::FromSeconds(12));
1579 }
1580
IN_PROC_BROWSER_TEST_F(RenderProcessHostFramePriorityTest,LowPriorityFramesEnabledOnlyLowPriority)1581 IN_PROC_BROWSER_TEST_F(RenderProcessHostFramePriorityTest,
1582 LowPriorityFramesEnabledOnlyLowPriority) {
1583 RenderProcessHostImpl* process = CreateAndInitializeProcess();
1584 AdvanceClock(base::TimeDelta::FromSeconds(1));
1585 // When all frames added are low priority, it's low priority.
1586 process->UpdateFrameWithPriority(base::nullopt,
1587 RenderProcessHostImpl::FramePriority::kLow);
1588 process->UpdateFrameWithPriority(base::nullopt,
1589 RenderProcessHostImpl::FramePriority::kLow);
1590 EXPECT_TRUE(process->IsProcessBackgrounded());
1591 AdvanceClock(base::TimeDelta::FromSeconds(2));
1592
1593 // This process has had only low priority frames attached to it.
1594 ShutDownAndCleanUpProcess();
1595 SetFramePrioritiesExpected(true, false);
1596 SetPriorityTimesExpected(base::TimeDelta::FromSeconds(2),
1597 base::TimeDelta::FromSeconds(3));
1598 }
1599
IN_PROC_BROWSER_TEST_F(RenderProcessHostFramePriorityTest,LowPriorityFramesEnabledOnlyNormalPriority)1600 IN_PROC_BROWSER_TEST_F(RenderProcessHostFramePriorityTest,
1601 LowPriorityFramesEnabledOnlyNormalPriority) {
1602 RenderProcessHostImpl* process = CreateAndInitializeProcess();
1603 AdvanceClock(base::TimeDelta::FromSeconds(1));
1604 // When all frames added are normal priority, it's not low priority.
1605 process->UpdateFrameWithPriority(
1606 base::nullopt, RenderProcessHostImpl::FramePriority::kNormal);
1607 process->UpdateFrameWithPriority(
1608 base::nullopt, RenderProcessHostImpl::FramePriority::kNormal);
1609 EXPECT_FALSE(process->IsProcessBackgrounded());
1610 AdvanceClock(base::TimeDelta::FromSeconds(2));
1611
1612 // This process has had only normal priority frames attached to it.
1613 ShutDownAndCleanUpProcess();
1614 SetFramePrioritiesExpected(false, true);
1615 SetPriorityTimesExpected(base::TimeDelta(), base::TimeDelta::FromSeconds(3));
1616 }
1617
1618 } // namespace content
1619