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

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: Rebased and fixed the tests for macosx Created 5 years, 4 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
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"
7 #include "chrome/browser/chrome_notification_types.h" 8 #include "chrome/browser/chrome_notification_types.h"
8 #include "chrome/browser/devtools/devtools_window.h" 9 #include "chrome/browser/devtools/devtools_window.h"
9 #include "chrome/browser/search/search.h" 10 #include "chrome/browser/search/search.h"
10 #include "chrome/browser/ui/browser.h" 11 #include "chrome/browser/ui/browser.h"
11 #include "chrome/browser/ui/browser_commands.h" 12 #include "chrome/browser/ui/browser_commands.h"
12 #include "chrome/browser/ui/singleton_tabs.h" 13 #include "chrome/browser/ui/singleton_tabs.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h" 14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/common/chrome_switches.h" 15 #include "chrome/common/chrome_switches.h"
15 #include "chrome/common/url_constants.h" 16 #include "chrome/common/url_constants.h"
16 #include "chrome/test/base/in_process_browser_test.h" 17 #include "chrome/test/base/in_process_browser_test.h"
17 #include "chrome/test/base/test_switches.h" 18 #include "chrome/test/base/test_switches.h"
18 #include "chrome/test/base/ui_test_utils.h" 19 #include "chrome/test/base/ui_test_utils.h"
19 #include "content/public/browser/notification_service.h" 20 #include "content/public/browser/notification_service.h"
20 #include "content/public/browser/render_process_host.h" 21 #include "content/public/browser/render_process_host.h"
21 #include "content/public/browser/render_view_host.h" 22 #include "content/public/browser/render_view_host.h"
22 #include "content/public/browser/render_widget_host_iterator.h" 23 #include "content/public/browser/render_widget_host_iterator.h"
23 #include "content/public/browser/web_contents.h" 24 #include "content/public/browser/web_contents.h"
24 #include "content/public/browser/web_contents_observer.h" 25 #include "content/public/browser/web_contents_observer.h"
25 #include "content/public/test/browser_test_utils.h" 26 #include "content/public/test/browser_test_utils.h"
27 #include "net/base/filename_util.h"
28 #include "net/test/embedded_test_server/embedded_test_server.h"
26 29
27 using content::RenderViewHost; 30 using content::RenderViewHost;
28 using content::RenderWidgetHost; 31 using content::RenderWidgetHost;
29 using content::WebContents; 32 using content::WebContents;
30 33
31 namespace { 34 namespace {
32 35
33 int RenderProcessHostCount() { 36 int RenderProcessHostCount() {
34 content::RenderProcessHost::iterator hosts = 37 content::RenderProcessHost::iterator hosts =
35 content::RenderProcessHost::AllHostsIterator(); 38 content::RenderProcessHost::AllHostsIterator();
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
68 base::ProcessHandle out_handle; 71 base::ProcessHandle out_handle;
69 if (!::DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(), 72 if (!::DuplicateHandle(GetCurrentProcess(), handle, GetCurrentProcess(),
70 &out_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) { 73 &out_handle, 0, FALSE, DUPLICATE_SAME_ACCESS)) {
71 return base::Process(); 74 return base::Process();
72 } 75 }
73 handle = out_handle; 76 handle = out_handle;
74 #endif // defined(OS_WIN) 77 #endif // defined(OS_WIN)
75 return base::Process(handle); 78 return base::Process(handle);
76 } 79 }
77 80
81 GURL GetSimplePageUrl() {
82 base::FilePath no_audio_path;
83 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &no_audio_path));
84 no_audio_path = no_audio_path.Append(FILE_PATH_LITERAL("content"));
85 no_audio_path = no_audio_path.Append(FILE_PATH_LITERAL("test"));
86 no_audio_path = no_audio_path.Append(FILE_PATH_LITERAL("data"));
87 no_audio_path = no_audio_path.Append(FILE_PATH_LITERAL("simple_page.html"));
gab 2015/08/07 19:55:06 GetTestUrl("simple_page.html") from content_browse
sebsg 2015/08/09 21:07:34 Good to know! But, as Nick recommended I now use t
88 EXPECT_TRUE(base::PathExists(no_audio_path));
89 return net::FilePathToFileURL(no_audio_path);
90 }
91
92 GURL GetAudioPlayingPage() {
93 base::FilePath audio_path;
94 EXPECT_TRUE(PathService::Get(base::DIR_SOURCE_ROOT, &audio_path));
95 audio_path = audio_path.Append(FILE_PATH_LITERAL("chrome"));
96 audio_path = audio_path.Append(FILE_PATH_LITERAL("test"));
97 audio_path = audio_path.Append(FILE_PATH_LITERAL("data"));
98 audio_path = audio_path.Append(FILE_PATH_LITERAL("extensions"));
99 audio_path = audio_path.Append(FILE_PATH_LITERAL("loop_audio.html"));
100 EXPECT_TRUE(base::PathExists(audio_path));
101 return net::FilePathToFileURL(audio_path);
102 }
103
104 bool IsProcessBackgroundedHelper(base::Process* process) {
gab 2015/08/07 19:55:06 const base::Process& process (i.e. always use con
sebsg 2015/08/09 21:07:34 Done.
105 #if defined(OS_MACOSX)
106 MachBroker* broker = MachBroker::GetInstance();
107 mach_port_t task_port = broker->TaskForPid(process.Pid());
gab 2015/08/07 19:55:06 I predict this won't compile because you're invoki
sebsg 2015/08/09 21:07:34 Done.
108 return process->IsProcessBackgrounded(task_port);
109 #else
110 return process->IsProcessBackgrounded();
111 #endif // defined(OS_MACOSX)
112 }
113
78 } // namespace 114 } // namespace
79 115
80 class ChromeRenderProcessHostTest : public InProcessBrowserTest { 116 class ChromeRenderProcessHostTest : public InProcessBrowserTest {
81 public: 117 public:
82 ChromeRenderProcessHostTest() {} 118 ChromeRenderProcessHostTest() {}
83 119
84 // Show a tab, activating the current one if there is one, and wait for 120 // 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 121 // the renderer process to be created or foregrounded, returning the process
86 // handle. 122 // handle.
87 base::Process ShowSingletonTab(const GURL& page) { 123 base::Process ShowSingletonTab(const GURL& page) {
(...skipping 436 matching lines...) Expand 10 before | Expand all | Expand 10 after
524 chrome::NOTIFICATION_BROWSER_CLOSED, 560 chrome::NOTIFICATION_BROWSER_CLOSED,
525 content::NotificationService::AllSources()); 561 content::NotificationService::AllSources());
526 562
527 // Kill the renderer process, simulating a crash. This should the ProcessDied 563 // Kill the renderer process, simulating a crash. This should the ProcessDied
528 // method to be called. Alternatively, RenderProcessHost::OnChannelError can 564 // method to be called. Alternatively, RenderProcessHost::OnChannelError can
529 // be called to directly force a call to ProcessDied. 565 // be called to directly force a call to ProcessDied.
530 wc1->GetRenderProcessHost()->Shutdown(-1, true); 566 wc1->GetRenderProcessHost()->Shutdown(-1, true);
531 567
532 observer.Wait(); 568 observer.Wait();
533 } 569 }
570
571 // Test to make sure that a process is backgrounded when the audio stops playing
572 // from it playing and there is an immediate tab switch.
gab 2015/08/07 19:55:06 Remove "from it playing" it makes the sentence con
sebsg 2015/08/09 21:07:34 Done.
573 IN_PROC_BROWSER_TEST_F(
574 ChromeRenderProcessHostTest,
575 BackgroundingLogicOfStoppedAudioAndImmediateTabSwitching) {
ncarter (slow) 2015/08/06 22:15:58 ProcessPriorityAfterStoppedAudio
sebsg 2015/08/09 21:07:34 Done.
576 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
ncarter (slow) 2015/08/06 22:15:58 Seems like you launch the embedded_test_server, bu
sebsg 2015/08/09 21:07:34 Done.
577
578 if (!base::Process::CanBackgroundProcesses()) {
gab 2015/08/07 19:55:06 Make this the first line of the test with a commen
sebsg 2015/08/09 21:07:34 Done.
579 LOG(ERROR) << "Can't background processes";
gab 2015/08/07 19:55:06 Avoid all types of logging in tests (and in genera
sebsg 2015/08/09 21:07:34 Done.
580 return;
581 }
582 base::CommandLine& parsed_command_line =
gab 2015/08/07 19:55:06 non-const & is banned by the style-guide.
sebsg 2015/08/09 21:07:34 Done.
583 *base::CommandLine::ForCurrentProcess();
584 parsed_command_line.AppendSwitch(switches::kProcessPerTab);
gab 2015/08/07 19:55:06 Instead of doing this here, override SetUpCommandL
sebsg 2015/08/09 21:07:34 Done.
585
586 GURL no_audio_url = GetSimplePageUrl();
587 GURL audio_url = GetAudioPlayingPage();
gab 2015/08/07 19:55:06 Make both of these const
sebsg 2015/08/09 21:07:34 Done.
588
589 ui_test_utils::NavigateToURL(browser(), audio_url);
590
591 content::WebContents* audio_tab_web_content =
592 browser()->tab_strip_model()->GetActiveWebContents();
593
594 // Add a new tab to the no audio page and make the tab with the audio page
595 // be the one that is visible. Get the process corresponding to the pages.
596 base::Process no_audio_process = ShowSingletonTab(no_audio_url);
597 base::Process audio_process = ShowSingletonTab(audio_url);
gab 2015/08/07 19:55:06 const
sebsg 2015/08/09 21:07:34 Done.
598
599 // Wait until the no audio page is backgrounded and the audio page is not
600 // backgrounded.
601 while (!IsProcessBackgroundedHelper(&no_audio_process) ||
602 IsProcessBackgroundedHelper(&audio_process)) {
603 base::RunLoop().RunUntilIdle();
604 }
605 EXPECT_TRUE(IsProcessBackgroundedHelper(&no_audio_process));
606 EXPECT_FALSE(IsProcessBackgroundedHelper(&audio_process));
ncarter (slow) 2015/08/06 22:15:58 With the while loop above, these EXPECT's are kind
sebsg 2015/08/09 21:07:34 Done.
607
608 // Pause the audio and immediately switch to the no audio tab.
609 content::ExecuteScript(audio_tab_web_content,
610 "document.getElementById('audioPlayer').pause();");
611 ShowSingletonTab(no_audio_url);
612
613 // Wait until the no audio page is not backgrounded and the audio page is
614 // backgrounded.
615 while (IsProcessBackgroundedHelper(&no_audio_process) ||
616 !IsProcessBackgroundedHelper(&audio_process)) {
617 base::RunLoop().RunUntilIdle();
ncarter (slow) 2015/08/06 22:15:58 What'll happen in practice here, is that RunUntilI
gab 2015/08/07 19:55:06 There is no event we can wait in the browser becau
sebsg 2015/08/09 21:07:34 Unfortunately, the results from using the OS' GetP
618 }
619 EXPECT_FALSE(IsProcessBackgroundedHelper(&no_audio_process));
620 EXPECT_TRUE(IsProcessBackgroundedHelper(&audio_process));
621 }
622
623 // Test to make sure that a process is backgrounded automatically when audio
624 // stops playing from it playing if it is not the active tab.
625 IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest,
626 BackgroundingLogicAudioStopsFromNotVisibleTab) {
627 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
628
629 if (!base::Process::CanBackgroundProcesses()) {
630 LOG(ERROR) << "Can't background processes";
631 return;
632 }
633 base::CommandLine& parsed_command_line =
634 *base::CommandLine::ForCurrentProcess();
635 parsed_command_line.AppendSwitch(switches::kProcessPerTab);
636
637 GURL no_audio_url = GetSimplePageUrl();
638 GURL audio_url = GetAudioPlayingPage();
639
640 ui_test_utils::NavigateToURL(browser(), audio_url);
641
642 content::WebContents* audio_tab_web_content =
643 browser()->tab_strip_model()->GetActiveWebContents();
644
645 // Get the process corresponding to the audio playing page.
646 base::Process audio_process = ProcessFromHandle(
647 audio_tab_web_content->GetRenderProcessHost()->GetHandle());
648
649 // Add a new tab to the no audio page and get its process.
650 base::Process no_audio_process = ShowSingletonTab(no_audio_url);
651
652 ASSERT_TRUE(no_audio_process.IsValid());
653 ASSERT_TRUE(audio_process.IsValid());
654 EXPECT_NE(audio_process.Pid(), no_audio_process.Pid());
gab 2015/08/07 19:55:06 A lot of the test setup is the same for all 3 of t
sebsg 2015/08/09 21:07:34 Done.
655
656 // Wait until the two pages are not backgrounded.
657 while (IsProcessBackgroundedHelper(&no_audio_process) ||
658 IsProcessBackgroundedHelper(&audio_process)) {
659 base::RunLoop().RunUntilIdle();
660 }
661 EXPECT_FALSE(IsProcessBackgroundedHelper(&no_audio_process));
662 EXPECT_FALSE(IsProcessBackgroundedHelper(&audio_process));
663
664 // Stop the audio.
665 content::ExecuteScript(audio_tab_web_content,
666 "document.getElementById('audioPlayer').pause();");
667
668 // Wait until the no audio page is not backgrounded and the audio page is
669 // backgrounded.
670 while (IsProcessBackgroundedHelper(&no_audio_process) ||
671 !IsProcessBackgroundedHelper(&audio_process)) {
672 base::RunLoop().RunUntilIdle();
673 }
674 EXPECT_FALSE(IsProcessBackgroundedHelper(&no_audio_process));
675 EXPECT_TRUE(IsProcessBackgroundedHelper(&audio_process));
676 }
677
678 // Test to make sure that a process is un-backgrounded automatically when audio
679 // starts playing from it if it is not the active tab.
680 IN_PROC_BROWSER_TEST_F(ChromeRenderProcessHostTest,
681 BackgroundingLogicAudioStartsFromBackgroundTab) {
682 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
683
684 if (!base::Process::CanBackgroundProcesses()) {
685 LOG(ERROR) << "Can't background processes";
686 return;
687 }
688 base::CommandLine& parsed_command_line =
689 *base::CommandLine::ForCurrentProcess();
690 parsed_command_line.AppendSwitch(switches::kProcessPerTab);
691
692 GURL no_audio_url = GetSimplePageUrl();
693 GURL audio_url = GetAudioPlayingPage();
694
695 ui_test_utils::NavigateToURL(browser(), audio_url);
696
697 content::WebContents* audio_tab_web_content =
698 browser()->tab_strip_model()->GetActiveWebContents();
699
700 // Stop the audio.
701 content::ExecuteScript(audio_tab_web_content,
702 "document.getElementById('audioPlayer').pause();");
703
704 // Get the process corresponding to the pages and creates a new tab to for
705 // the no audio page.
706 base::Process audio_process = ProcessFromHandle(
707 audio_tab_web_content->GetRenderProcessHost()->GetHandle());
708 base::Process no_audio_process = ShowSingletonTab(no_audio_url);
709
710 ASSERT_TRUE(no_audio_process.IsValid());
711 ASSERT_TRUE(audio_process.IsValid());
712 EXPECT_NE(audio_process.Pid(), no_audio_process.Pid());
713
714 // Wait until the no audio page is not backgrounded and the audio page is
715 // backgrounded.
716 while (IsProcessBackgroundedHelper(&no_audio_process) ||
717 !IsProcessBackgroundedHelper(&audio_process)) {
718 base::RunLoop().RunUntilIdle();
719 }
720 EXPECT_FALSE(IsProcessBackgroundedHelper(&no_audio_process));
721 EXPECT_TRUE(IsProcessBackgroundedHelper(&audio_process));
722
723 // Start the audio from the backgrounded tab.
724 content::ExecuteScript(audio_tab_web_content,
725 "document.getElementById('audioPlayer').play();");
726
727 // Wait until the two pages are not backgrounded.
728 while (IsProcessBackgroundedHelper(&no_audio_process) ||
729 IsProcessBackgroundedHelper(&audio_process)) {
730 base::RunLoop().RunUntilIdle();
731 }
732 EXPECT_FALSE(IsProcessBackgroundedHelper(&no_audio_process));
733 EXPECT_FALSE(IsProcessBackgroundedHelper(&audio_process));
734 }
OLDNEW
« no previous file with comments | « no previous file | chrome/test/data/extensions/loop_audio.html » ('j') | content/browser/renderer_host/render_process_host_impl.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698