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