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
3 // found in the LICENSE file.
5 #include "base/basictypes.h"
6 #include "base/command_line.h"
7 #include "base/location.h"
8 #include "base/single_thread_task_runner.h"
9 #include "base/strings/stringprintf.h"
10 #include "base/thread_task_runner_handle.h"
11 #include "base/time/time.h"
12 #include "chrome/browser/extensions/extension_apitest.h"
13 #include "chrome/browser/extensions/tab_helper.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/browser/ui/tabs/tab_strip_model.h"
16 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
17 #include "chrome/browser/ui/tabs/tab_utils.h"
18 #include "chrome/common/chrome_switches.h"
19 #include "content/public/browser/render_frame_host.h"
20 #include "content/public/browser/render_process_host.h"
21 #include "content/public/test/browser_test_utils.h"
22 #include "content/public/test/test_utils.h"
23 #include "extensions/browser/extension_registry.h"
24 #include "extensions/common/switches.h"
25 #include "extensions/test/extension_test_message_listener.h"
26 #include "extensions/test/result_catcher.h"
29 #include "base/win/windows_version.h"
32 namespace extensions
{
36 const char kExtensionId
[] = "ddchlicdkolnonkihahngkmmmjnjlkkf";
38 class TabCaptureApiTest
: public ExtensionApiTest
{
40 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
41 ExtensionApiTest::SetUpCommandLine(command_line
);
42 // Specify smallish window size to make testing of tab capture less CPU
44 command_line
->AppendSwitchASCII(::switches::kWindowSize
, "300,300");
47 void AddExtensionToCommandLineWhitelist() {
48 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
49 switches::kWhitelistedExtensionID
, kExtensionId
);
53 void SimulateMouseClickInCurrentTab() {
54 content::SimulateMouseClick(
55 browser()->tab_strip_model()->GetActiveWebContents(),
57 blink::WebMouseEvent::ButtonLeft
);
61 class TabCaptureApiPixelTest
: public TabCaptureApiTest
{
63 void SetUp() override
{
64 if (!IsTooIntensiveForThisPlatform())
66 TabCaptureApiTest::SetUp();
70 bool IsTooIntensiveForThisPlatform() const {
72 if (base::win::GetVersion() < base::win::VERSION_VISTA
)
76 // The tests are too slow to succeed with OSMesa on the bots.
83 // TODO(miu): Look into enabling these tests for the Debug build bots once
84 // they prove to be stable again on the Release bots.
85 // http://crbug.com/396413
86 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
87 "run-tab-capture-api-pixel-tests");
92 // Tests API behaviors, including info queries, and constraints violations.
93 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, ApiTests
) {
94 AddExtensionToCommandLineWhitelist();
95 ASSERT_TRUE(RunExtensionSubtest("tab_capture", "api_tests.html")) << message_
;
98 // Tests that tab capture video frames can be received in a VIDEO element.
99 IN_PROC_BROWSER_TEST_F(TabCaptureApiPixelTest
, EndToEndWithoutRemoting
) {
100 if (IsTooIntensiveForThisPlatform()) {
101 LOG(WARNING
) << "Skipping this CPU-intensive test on this platform/build.";
104 AddExtensionToCommandLineWhitelist();
105 ASSERT_TRUE(RunExtensionSubtest(
106 "tab_capture", "end_to_end.html?method=local&colorDeviation=10"))
110 // Tests that video frames are captured, transported via WebRTC, and finally
111 // received in a VIDEO element. More allowance is provided for color deviation
112 // because of the additional layers of video processing performed within
114 IN_PROC_BROWSER_TEST_F(TabCaptureApiPixelTest
, EndToEndThroughWebRTC
) {
115 if (IsTooIntensiveForThisPlatform()) {
116 LOG(WARNING
) << "Skipping this CPU-intensive test on this platform/build.";
119 AddExtensionToCommandLineWhitelist();
120 ASSERT_TRUE(RunExtensionSubtest(
121 "tab_capture", "end_to_end.html?method=webrtc&colorDeviation=50"))
125 // http://crbug.com/177163
126 #if defined(OS_WIN) && !defined(NDEBUG)
127 #define MAYBE_GetUserMediaTest DISABLED_GetUserMediaTest
129 #define MAYBE_GetUserMediaTest GetUserMediaTest
131 // Tests that getUserMedia() is NOT a way to start tab capture.
132 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_GetUserMediaTest
) {
133 ExtensionTestMessageListener
listener("ready", true);
135 ASSERT_TRUE(RunExtensionSubtest("tab_capture", "get_user_media_test.html"))
138 EXPECT_TRUE(listener
.WaitUntilSatisfied());
140 content::OpenURLParams
params(GURL("about:blank"), content::Referrer(),
142 ui::PAGE_TRANSITION_LINK
, false);
143 content::WebContents
* web_contents
= browser()->OpenURL(params
);
145 content::RenderFrameHost
* const main_frame
= web_contents
->GetMainFrame();
146 ASSERT_TRUE(main_frame
);
147 listener
.Reply(base::StringPrintf("web-contents-media-stream://%i:%i",
148 main_frame
->GetProcess()->GetID(),
149 main_frame
->GetRoutingID()));
151 ResultCatcher catcher
;
152 catcher
.RestrictToBrowserContext(browser()->profile());
153 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
156 // http://crbug.com/177163
157 #if defined(OS_WIN) && !defined(NDEBUG)
158 #define MAYBE_ActiveTabPermission DISABLED_ActiveTabPermission
160 #define MAYBE_ActiveTabPermission ActiveTabPermission
162 // Make sure tabCapture.capture only works if the tab has been granted
163 // permission via an extension icon click or the extension is whitelisted.
164 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_ActiveTabPermission
) {
165 ExtensionTestMessageListener
before_open_tab("ready1", true);
166 ExtensionTestMessageListener
before_grant_permission("ready2", true);
167 ExtensionTestMessageListener
before_open_new_tab("ready3", true);
168 ExtensionTestMessageListener
before_whitelist_extension("ready4", true);
170 ASSERT_TRUE(RunExtensionSubtest("tab_capture",
171 "active_tab_permission_test.html"))
174 // Open a new tab and make sure capture is denied.
175 EXPECT_TRUE(before_open_tab
.WaitUntilSatisfied());
176 content::OpenURLParams
params(GURL("http://google.com"), content::Referrer(),
178 ui::PAGE_TRANSITION_LINK
, false);
179 content::WebContents
* web_contents
= browser()->OpenURL(params
);
180 before_open_tab
.Reply("");
182 // Grant permission and make sure capture succeeds.
183 EXPECT_TRUE(before_grant_permission
.WaitUntilSatisfied());
184 const Extension
* extension
= ExtensionRegistry::Get(
185 web_contents
->GetBrowserContext())->enabled_extensions().GetByID(
187 TabHelper::FromWebContents(web_contents
)
188 ->active_tab_permission_granter()->GrantIfRequested(extension
);
189 before_grant_permission
.Reply("");
191 // Open a new tab and make sure capture is denied.
192 EXPECT_TRUE(before_open_new_tab
.WaitUntilSatisfied());
193 browser()->OpenURL(params
);
194 before_open_new_tab
.Reply("");
196 // Add extension to whitelist and make sure capture succeeds.
197 EXPECT_TRUE(before_whitelist_extension
.WaitUntilSatisfied());
198 AddExtensionToCommandLineWhitelist();
199 before_whitelist_extension
.Reply("");
201 ResultCatcher catcher
;
202 catcher
.RestrictToBrowserContext(browser()->profile());
203 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
206 // http://crbug.com/177163
207 #if defined(OS_WIN) && !defined(NDEBUG)
208 #define MAYBE_FullscreenEvents DISABLED_FullscreenEvents
210 #define MAYBE_FullscreenEvents FullscreenEvents
212 // Tests that fullscreen transitions during a tab capture session dispatch
213 // events to the onStatusChange listener. The test loads a page that toggles
214 // fullscreen mode, using the Fullscreen Javascript API, in response to mouse
216 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_FullscreenEvents
) {
217 AddExtensionToCommandLineWhitelist();
219 ExtensionTestMessageListener
capture_started("tab_capture_started", false);
220 ExtensionTestMessageListener
entered_fullscreen("entered_fullscreen", false);
222 ASSERT_TRUE(RunExtensionSubtest("tab_capture", "fullscreen_test.html"))
224 EXPECT_TRUE(capture_started
.WaitUntilSatisfied());
226 // Click on the page to trigger the Javascript that will toggle the tab into
228 SimulateMouseClickInCurrentTab();
229 EXPECT_TRUE(entered_fullscreen
.WaitUntilSatisfied());
231 // Click again to exit fullscreen mode.
232 SimulateMouseClickInCurrentTab();
234 // Wait until the page examines its results and calls chrome.test.succeed().
235 ResultCatcher catcher
;
236 catcher
.RestrictToBrowserContext(browser()->profile());
237 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
240 // Times out on Win dbg bots: http://crbug.com/177163
241 // Flaky on MSan bots: http://crbug.com/294431
242 #if (defined(OS_WIN) && !defined(NDEBUG)) || defined(MEMORY_SANITIZER)
243 #define MAYBE_GrantForChromePages DISABLED_GrantForChromePages
245 #define MAYBE_GrantForChromePages GrantForChromePages
247 // Make sure tabCapture API can be granted for Chrome:// pages.
248 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_GrantForChromePages
) {
249 ExtensionTestMessageListener
before_open_tab("ready1", true);
250 ASSERT_TRUE(RunExtensionSubtest("tab_capture",
251 "active_tab_chrome_pages.html"))
253 EXPECT_TRUE(before_open_tab
.WaitUntilSatisfied());
255 // Open a tab on a chrome:// page and make sure we can capture.
256 content::OpenURLParams
params(GURL("chrome://version"), content::Referrer(),
258 ui::PAGE_TRANSITION_LINK
, false);
259 content::WebContents
* web_contents
= browser()->OpenURL(params
);
260 const Extension
* extension
= ExtensionRegistry::Get(
261 web_contents
->GetBrowserContext())->enabled_extensions().GetByID(
263 TabHelper::FromWebContents(web_contents
)
264 ->active_tab_permission_granter()->GrantIfRequested(extension
);
265 before_open_tab
.Reply("");
267 ResultCatcher catcher
;
268 catcher
.RestrictToBrowserContext(browser()->profile());
269 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
272 // http://crbug.com/177163
273 #if defined(OS_WIN) && !defined(NDEBUG)
274 #define MAYBE_CaptureInSplitIncognitoMode DISABLED_CaptureInSplitIncognitoMode
276 #define MAYBE_CaptureInSplitIncognitoMode CaptureInSplitIncognitoMode
278 // Tests that a tab in incognito mode can be captured.
279 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_CaptureInSplitIncognitoMode
) {
280 AddExtensionToCommandLineWhitelist();
281 ASSERT_TRUE(RunExtensionSubtest("tab_capture",
282 "start_tab_capture.html",
283 kFlagEnableIncognito
| kFlagUseIncognito
))
287 // http://crbug.com/177163
288 #if defined(OS_WIN) && !defined(NDEBUG)
289 #define MAYBE_Constraints DISABLED_Constraints
291 #define MAYBE_Constraints Constraints
293 // Tests that valid constraints allow tab capture to start, while invalid ones
295 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_Constraints
) {
296 AddExtensionToCommandLineWhitelist();
297 ASSERT_TRUE(RunExtensionSubtest("tab_capture", "constraints.html"))
301 // http://crbug.com/177163
302 #if defined(OS_WIN) && !defined(NDEBUG)
303 #define MAYBE_TabIndicator DISABLED_TabIndicator
305 // Also flaky everywhere else: https://crbug.com/530657
306 #define MAYBE_TabIndicator DISABLED_TabIndicator
308 // Tests that the tab indicator (in the tab strip) is shown during tab capture.
309 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_TabIndicator
) {
310 ASSERT_EQ(TAB_MEDIA_STATE_NONE
,
311 chrome::GetTabMediaStateForContents(
312 browser()->tab_strip_model()->GetActiveWebContents()));
314 // Run an extension test that just turns on tab capture, which should cause
315 // the indicator to turn on.
316 AddExtensionToCommandLineWhitelist();
317 ASSERT_TRUE(RunExtensionSubtest("tab_capture", "start_tab_capture.html"))
320 // A TabStripModelObserver that quits the MessageLoop whenever the UI's model
321 // is sent an event that changes the indicator status.
322 class IndicatorChangeObserver
: public TabStripModelObserver
{
324 explicit IndicatorChangeObserver(Browser
* browser
)
325 : last_media_state_(chrome::GetTabMediaStateForContents(
326 browser
->tab_strip_model()->GetActiveWebContents())) {}
328 TabMediaState
last_media_state() const { return last_media_state_
; }
330 void TabChangedAt(content::WebContents
* contents
,
332 TabChangeType change_type
) override
{
333 const TabMediaState media_state
=
334 chrome::GetTabMediaStateForContents(contents
);
335 const bool has_changed
= media_state
!= last_media_state_
;
336 last_media_state_
= media_state
;
338 base::ThreadTaskRunnerHandle::Get()->PostTask(
339 FROM_HERE
, base::MessageLoop::QuitClosure());
344 TabMediaState last_media_state_
;
347 // Run the browser until the indicator turns on.
348 IndicatorChangeObserver
observer(browser());
349 browser()->tab_strip_model()->AddObserver(&observer
);
350 const base::TimeTicks start_time
= base::TimeTicks::Now();
351 while (observer
.last_media_state() != TAB_MEDIA_STATE_CAPTURING
) {
352 if (base::TimeTicks::Now() - start_time
>
353 base::TimeDelta::FromSeconds(10)) {
354 EXPECT_EQ(TAB_MEDIA_STATE_CAPTURING
, observer
.last_media_state());
355 browser()->tab_strip_model()->RemoveObserver(&observer
);
358 content::RunMessageLoop();
360 browser()->tab_strip_model()->RemoveObserver(&observer
);
365 } // namespace extensions