Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(180)

Side by Side Diff: chrome/browser/renderer_host/render_process_host_chrome_browsertest.cc

Issue 1214883004: Fixed the audio backgrounding bug (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fixed bad rebase merge Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | chrome/test/data/extensions/loop_audio.html » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/command_line.h" 5 #include "base/command_line.h"
6 #include "base/path_service.h"
6 #include "base/process/process.h" 7 #include "base/process/process.h"
8 #include "base/test/test_timeouts.h"
7 #include "chrome/browser/chrome_notification_types.h" 9 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/devtools/devtools_window.h" 10 #include "chrome/browser/devtools/devtools_window.h"
9 #include "chrome/browser/search/search.h" 11 #include "chrome/browser/search/search.h"
10 #include "chrome/browser/ui/browser.h" 12 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/browser_commands.h" 13 #include "chrome/browser/ui/browser_commands.h"
12 #include "chrome/browser/ui/singleton_tabs.h" 14 #include "chrome/browser/ui/singleton_tabs.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h" 15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/common/chrome_switches.h" 16 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/url_constants.h" 17 #include "chrome/common/url_constants.h"
16 #include "chrome/test/base/in_process_browser_test.h" 18 #include "chrome/test/base/in_process_browser_test.h"
17 #include "chrome/test/base/test_switches.h" 19 #include "chrome/test/base/test_switches.h"
18 #include "chrome/test/base/ui_test_utils.h" 20 #include "chrome/test/base/ui_test_utils.h"
19 #include "content/public/browser/notification_service.h" 21 #include "content/public/browser/notification_service.h"
20 #include "content/public/browser/render_process_host.h" 22 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/render_view_host.h" 23 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/render_widget_host_iterator.h" 24 #include "content/public/browser/render_widget_host_iterator.h"
23 #include "content/public/browser/web_contents.h" 25 #include "content/public/browser/web_contents.h"
24 #include "content/public/browser/web_contents_observer.h" 26 #include "content/public/browser/web_contents_observer.h"
25 #include "content/public/test/browser_test_utils.h" 27 #include "content/public/test/browser_test_utils.h"
28 #include "net/base/filename_util.h"
29 #include "net/test/embedded_test_server/embedded_test_server.h"
26 30
27 using content::RenderViewHost; 31 using content::RenderViewHost;
28 using content::RenderWidgetHost; 32 using content::RenderWidgetHost;
29 using content::WebContents; 33 using content::WebContents;
30 34
31 namespace { 35 namespace {
32 36
33 int RenderProcessHostCount() { 37 int RenderProcessHostCount() {
34 content::RenderProcessHost::iterator hosts = 38 content::RenderProcessHost::iterator hosts =
35 content::RenderProcessHost::AllHostsIterator(); 39 content::RenderProcessHost::AllHostsIterator();
(...skipping 24 matching lines...) Expand all
60 } 64 }
61 65
62 // TODO(rvargas) crbug.com/417532: Remove this code. 66 // TODO(rvargas) crbug.com/417532: Remove this code.
63 base::Process ProcessFromHandle(base::ProcessHandle handle) { 67 base::Process ProcessFromHandle(base::ProcessHandle handle) {
64 #if defined(OS_WIN) 68 #if defined(OS_WIN)
65 if (handle == GetCurrentProcess()) 69 if (handle == GetCurrentProcess())
66 return base::Process::Current(); 70 return base::Process::Current();
67 71
68 base::ProcessHandle out_handle; 72 base::ProcessHandle out_handle;
69 if (!::DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), 73 if (!::DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
70 &out_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { 74 &out_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
71 return base::Process(); 75 return base::Process();
72 } 76 }
73 handle = out_handle; 77 handle = out_handle;
74 #endif // defined(OS_WIN) 78 #endif // defined(OS_WIN)
75 return base::Process(handle); 79 return base::Process(handle);
76 } 80 }
77 81
78 } // namespace 82 } // namespace
79 83
80 class ChromeRenderProcessHostTest : public InProcessBrowserTest { 84 class ChromeRenderProcessHostTest : public InProcessBrowserTest {
81 public: 85 public:
82 ChromeRenderProcessHostTest() {} 86 ChromeRenderProcessHostTest() {}
83 87
84 // Show a tab, activating the current one if there is one, and wait for 88 // Show a tab, activating the current one if there is one, and wait for
85 // the renderer process to be created or foregrounded, returning the process 89 // the renderer process to be created or foregrounded, returning the process
86 // handle. 90 // handle.
87 base::Process ShowSingletonTab(const GURL& page) { 91 base::Process ShowSingletonTab(const GURL& page) {
88 chrome::ShowSingletonTab(browser(), page); 92 chrome::ShowSingletonTab(browser(), page);
89 WebContents* wc = browser()->tab_strip_model()->GetActiveWebContents(); 93 WebContents* wc = browser()->tab_strip_model()->GetActiveWebContents();
90 CHECK(wc->GetURL() == page); 94 CHECK(wc->GetURL() == page);
91 95
92 WaitForLauncherThread(); 96 WaitForLauncherThread();
93 WaitForMessageProcessing(wc); 97 WaitForMessageProcessing(wc);
94 return ProcessFromHandle(wc->GetRenderProcessHost()->GetHandle()); 98 return ProcessFromHandle(wc->GetRenderProcessHost()->GetHandle());
95 } 99 }
96 100
97 // Loads the given url in a new background tab and returns the handle of its 101 // Loads the given url in a new background tab and returns the handle of its
98 // renderer. 102 // renderer.
99 base::Process OpenBackgroundTab(const GURL& page) { 103 base::Process OpenBackgroundTab(const GURL& page) {
100 ui_test_utils::NavigateToURLWithDisposition(browser(), page, 104 ui_test_utils::NavigateToURLWithDisposition(
101 NEW_BACKGROUND_TAB, ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION); 105 browser(), page, NEW_BACKGROUND_TAB,
106 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
102 107
103 TabStripModel* tab_strip = browser()->tab_strip_model(); 108 TabStripModel* tab_strip = browser()->tab_strip_model();
104 WebContents* wc = tab_strip->GetWebContentsAt( 109 WebContents* wc =
105 tab_strip->active_index() + 1); 110 tab_strip->GetWebContentsAt(tab_strip->active_index() + 1);
106 CHECK(wc->GetVisibleURL() == page); 111 CHECK(wc->GetVisibleURL() == page);
107 112
108 WaitForLauncherThread(); 113 WaitForLauncherThread();
109 WaitForMessageProcessing(wc); 114 WaitForMessageProcessing(wc);
110 return ProcessFromHandle(wc->GetRenderProcessHost()->GetHandle()); 115 return ProcessFromHandle(wc->GetRenderProcessHost()->GetHandle());
111 } 116 }
112 117
113 // Ensures that the backgrounding / foregrounding gets a chance to run. 118 // Ensures that the backgrounding / foregrounding gets a chance to run.
114 void WaitForLauncherThread() { 119 void WaitForLauncherThread() {
115 content::BrowserThread::PostTaskAndReply( 120 content::BrowserThread::PostTaskAndReply(
(...skipping 92 matching lines...) Expand 10 before | Expand all | Expand 10 after
208 EXPECT_EQ(tab_count, browser()->tab_strip_model()->count()); 213 EXPECT_EQ(tab_count, browser()->tab_strip_model()->count());
209 tab1 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1); 214 tab1 = browser()->tab_strip_model()->GetWebContentsAt(tab_count - 1);
210 rph3 = tab1->GetRenderProcessHost(); 215 rph3 = tab1->GetRenderProcessHost();
211 EXPECT_EQ(tab1->GetURL(), bookmarks); 216 EXPECT_EQ(tab1->GetURL(), bookmarks);
212 EXPECT_EQ(host_count, RenderProcessHostCount()); 217 EXPECT_EQ(host_count, RenderProcessHostCount());
213 EXPECT_NE(rph1, rph3); 218 EXPECT_NE(rph1, rph3);
214 EXPECT_NE(rph2, rph3); 219 EXPECT_NE(rph2, rph3);
215 } 220 }
216 }; 221 };
217 222
218
219 class ChromeRenderProcessHostTestWithCommandLine 223 class ChromeRenderProcessHostTestWithCommandLine
220 : public ChromeRenderProcessHostTest { 224 : public ChromeRenderProcessHostTest {
221 protected: 225 protected:
222 void SetUpCommandLine(base::CommandLine* command_line) override { 226 void SetUpCommandLine(base::CommandLine* command_line) override {
223 command_line->AppendSwitchASCII(switches::kRendererProcessLimit, "1"); 227 command_line->AppendSwitchASCII(switches::kRendererProcessLimit, "1");
224 } 228 }
225 }; 229 };
226 230
227 // Disable on Mac and Windows due to ongoing flakiness. (crbug.com/442785) 231 // Disable on Mac and Windows due to ongoing flakiness. (crbug.com/442785)
228 #if defined(OS_MACOSX) || defined(OS_WIN) 232 #if defined(OS_MACOSX) || defined(OS_WIN)
(...skipping 242 matching lines...) Expand 10 before | Expand all | Expand 10 after
471 chrome::ToggleDevToolsWindow(browser(), DevToolsToggleAction::Toggle()); 475 chrome::ToggleDevToolsWindow(browser(), DevToolsToggleAction::Toggle());
472 close_observer.Wait(); 476 close_observer.Wait();
473 } 477 }
474 478
475 // This class's goal is to close the browser window when a renderer process has 479 // This class's goal is to close the browser window when a renderer process has
476 // crashed. It does so by monitoring WebContents for RenderProcessGone event and 480 // crashed. It does so by monitoring WebContents for RenderProcessGone event and
477 // closing the passed in TabStripModel. This is used in the following test case. 481 // closing the passed in TabStripModel. This is used in the following test case.
478 class WindowDestroyer : public content::WebContentsObserver { 482 class WindowDestroyer : public content::WebContentsObserver {
479 public: 483 public:
480 WindowDestroyer(content::WebContents* web_contents, TabStripModel* model) 484 WindowDestroyer(content::WebContents* web_contents, TabStripModel* model)
481 : content::WebContentsObserver(web_contents), 485 : content::WebContentsObserver(web_contents), tab_strip_model_(model) {}
482 tab_strip_model_(model) {
483 }
484 486
485 void RenderProcessGone(base::TerminationStatus status) override { 487 void RenderProcessGone(base::TerminationStatus status) override {
486 // Wait for the window to be destroyed, which will ensure all other 488 // Wait for the window to be destroyed, which will ensure all other
487 // RenderViewHost objects are deleted before we return and proceed with 489 // RenderViewHost objects are deleted before we return and proceed with
488 // the next iteration of notifications. 490 // the next iteration of notifications.
489 content::WindowedNotificationObserver observer( 491 content::WindowedNotificationObserver observer(
490 chrome::NOTIFICATION_BROWSER_CLOSED, 492 chrome::NOTIFICATION_BROWSER_CLOSED,
491 content::NotificationService::AllSources()); 493 content::NotificationService::AllSources());
492 tab_strip_model_->CloseAllTabs(); 494 tab_strip_model_->CloseAllTabs();
493 observer.Wait(); 495 observer.Wait();
(...skipping 30 matching lines...) Expand all
524 chrome::NOTIFICATION_BROWSER_CLOSED, 526 chrome::NOTIFICATION_BROWSER_CLOSED,
525 content::NotificationService::AllSources()); 527 content::NotificationService::AllSources());
526 528
527 // Kill the renderer process, simulating a crash. This should the ProcessDied 529 // Kill the renderer process, simulating a crash. This should the ProcessDied
528 // method to be called. Alternatively, RenderProcessHost::OnChannelError can 530 // method to be called. Alternatively, RenderProcessHost::OnChannelError can
529 // be called to directly force a call to ProcessDied. 531 // be called to directly force a call to ProcessDied.
530 wc1->GetRenderProcessHost()->Shutdown(-1, true); 532 wc1->GetRenderProcessHost()->Shutdown(-1, true);
531 533
532 observer.Wait(); 534 observer.Wait();
533 } 535 }
536
537 // Sets up the browser in order to start the tests with two tabs open: one
538 // called "no audio" in foreground and another called "audio" in background with
539 // audio in playing state. Also sets up the variables containing the process
540 // associated with each tab, the urls of the two pages and the WebContents of
541 // the "audio" page.
542 class ChromeRenderProcessHostBackgroundingTest
543 : public ChromeRenderProcessHostTest {
544 public:
545 ChromeRenderProcessHostBackgroundingTest() {}
546
547 void SetUpCommandLine(base::CommandLine* command_line) override {
548 command_line->AppendSwitch(switches::kProcessPerTab);
549 }
550
551 void SetUpOnMainThread() override {
552 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
553
554 // Set up the server and get the test pages.
555 base::FilePath test_data_dir;
556 ASSERT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &test_data_dir));
557 embedded_test_server()->ServeFilesFromDirectory(
558 test_data_dir.AppendASCII("chrome/test/data/"));
559 audio_url_ = embedded_test_server()->GetURL("/extensions/loop_audio.html");
560 no_audio_url_ = embedded_test_server()->GetURL("/title1.html");
561
562 // Open a browser, navigate to the audio page and get its WebContents.
563 ui_test_utils::NavigateToURL(browser(), audio_url_);
564 audio_tab_web_contents_ =
565 browser()->tab_strip_model()->GetActiveWebContents();
566
567 // Create a new tab for the no audio page and confirm that the process of
568 // each tab is different and that both are valid.
569 audio_process_ = ProcessFromHandle(
570 audio_tab_web_contents_->GetRenderProcessHost()->GetHandle());
571 no_audio_process_ = ShowSingletonTab(no_audio_url_);
572 ASSERT_NE(audio_process_.Pid(), no_audio_process_.Pid());
573 ASSERT_TRUE(no_audio_process_.IsValid());
574 ASSERT_TRUE(audio_process_.IsValid());
575 }
576
577 protected:
578 GURL audio_url_;
579 GURL no_audio_url_;
580
581 base::Process audio_process_;
582 base::Process no_audio_process_;
583
584 content::WebContents* audio_tab_web_contents_;
585
586 private:
587 DISALLOW_COPY_AND_ASSIGN(ChromeRenderProcessHostBackgroundingTest);
588 };
589
590 // Test to make sure that a process is backgrounded when the audio stops playing
591 // from the active tab and there is an immediate tab switch.
592 IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostBackgroundingTest,
593 ProcessPriorityAfterStoppedAudio) {
594 // This test is invalid on platforms that can't background.
595 if (!base::Process::CanBackgroundProcesses())
596 return;
597
598 ShowSingletonTab(audio_url_);
599
600 // Wait until the no audio page is backgrounded and the audio page is not
601 // backgrounded.
602 while (!no_audio_process_.IsProcessBackgrounded() ||
603 audio_process_.IsProcessBackgrounded()) {
604 base::RunLoop().RunUntilIdle();
605 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
606 }
607
608 // Pause the audio and immediately switch to the no audio tab.
609 ASSERT_TRUE(content::ExecuteScript(
610 audio_tab_web_contents_,
611 "document.getElementById('audioPlayer').pause();"));
612 ShowSingletonTab(no_audio_url_);
613
614 // Wait until the no audio page is not backgrounded and the audio page is
615 // backgrounded.
616 while (no_audio_process_.IsProcessBackgrounded() ||
617 !audio_process_.IsProcessBackgrounded()) {
618 base::RunLoop().RunUntilIdle();
619 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
620 }
621 }
622
623 // Test to make sure that a process is backgrounded automatically when audio
624 // stops playing from a hidden tab.
625 IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostBackgroundingTest,
626 ProcessPriorityAfterAudioStopsOnNotVisibleTab) {
627 // This test is invalid on platforms that can't background.
628 if (!base::Process::CanBackgroundProcesses())
629 return;
630
631 // Wait until the two pages are not backgrounded.
632 while (no_audio_process_.IsProcessBackgrounded() ||
633 audio_process_.IsProcessBackgrounded()) {
634 base::RunLoop().RunUntilIdle();
635 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
636 }
637
638 // Stop the audio.
639 ASSERT_TRUE(content::ExecuteScript(
640 audio_tab_web_contents_,
641 "document.getElementById('audioPlayer').pause();"));
642
643 // Wait until the no audio page is not backgrounded and the audio page is
644 // backgrounded.
645 while (no_audio_process_.IsProcessBackgrounded() ||
646 !audio_process_.IsProcessBackgrounded()) {
647 base::RunLoop().RunUntilIdle();
648 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
649 }
650 }
651
652 // Test to make sure that a process is un-backgrounded automatically when audio
653 // starts playing from a backgrounded tab.
654 IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostBackgroundingTest,
655 ProcessPriorityAfterAudioStartsFromBackgroundTab) {
656 // This test is invalid on platforms that can't background.
657 if (!base::Process::CanBackgroundProcesses())
658 return;
659
660 // Stop the audio.
661 ASSERT_TRUE(content::ExecuteScript(
662 audio_tab_web_contents_,
663 "document.getElementById('audioPlayer').pause();"));
664
665 // Wait until the no audio page is not backgrounded and the audio page is
666 // backgrounded.
667 while (no_audio_process_.IsProcessBackgrounded() ||
668 !audio_process_.IsProcessBackgrounded()) {
669 base::RunLoop().RunUntilIdle();
670 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
671 }
672
673 // Start the audio from the backgrounded tab.
674 ASSERT_TRUE(
675 content::ExecuteScript(audio_tab_web_contents_,
676 "document.getElementById('audioPlayer').play();"));
677
678 // Wait until the two pages are not backgrounded.
679 while (no_audio_process_.IsProcessBackgrounded() ||
680 audio_process_.IsProcessBackgrounded()) {
681 base::RunLoop().RunUntilIdle();
682 base::PlatformThread::Sleep(TestTimeouts::tiny_timeout());
683 }
684 }
OLDNEW
« no previous file with comments | « no previous file | chrome/test/data/extensions/loop_audio.html » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698