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/message_loop/message_loop.h"
8 #include "base/strings/stringprintf.h"
9 #include "base/time/time.h"
10 #include "chrome/browser/extensions/extension_apitest.h"
11 #include "chrome/browser/extensions/tab_helper.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/ui/tabs/tab_strip_model.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
15 #include "chrome/browser/ui/tabs/tab_utils.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "chrome/common/chrome_version_info.h"
18 #include "content/public/browser/render_frame_host.h"
19 #include "content/public/browser/render_process_host.h"
20 #include "content/public/test/browser_test_utils.h"
21 #include "content/public/test/test_utils.h"
22 #include "extensions/browser/extension_registry.h"
23 #include "extensions/common/switches.h"
24 #include "extensions/test/extension_test_message_listener.h"
25 #include "extensions/test/result_catcher.h"
28 #include "base/win/windows_version.h"
31 namespace extensions
{
35 const char kExtensionId
[] = "ddchlicdkolnonkihahngkmmmjnjlkkf";
37 class TabCaptureApiTest
: public ExtensionApiTest
{
39 void SetUpCommandLine(base::CommandLine
* command_line
) override
{
40 ExtensionApiTest::SetUpCommandLine(command_line
);
41 // Specify smallish window size to make testing of tab capture less CPU
43 command_line
->AppendSwitchASCII(::switches::kWindowSize
, "300,300");
46 void AddExtensionToCommandLineWhitelist() {
47 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
48 switches::kWhitelistedExtensionID
, kExtensionId
);
52 void SimulateMouseClickInCurrentTab() {
53 content::SimulateMouseClick(
54 browser()->tab_strip_model()->GetActiveWebContents(),
56 blink::WebMouseEvent::ButtonLeft
);
60 class TabCaptureApiPixelTest
: public TabCaptureApiTest
{
62 void SetUp() override
{
63 if (!IsTooIntensiveForThisPlatform())
65 TabCaptureApiTest::SetUp();
69 bool IsTooIntensiveForThisPlatform() const {
71 if (base::win::GetVersion() < base::win::VERSION_VISTA
)
75 // The tests are too slow to succeed with OSMesa on the bots.
82 // TODO(miu): Look into enabling these tests for the Debug build bots once
83 // they prove to be stable again on the Release bots.
84 // http://crbug.com/396413
85 return !base::CommandLine::ForCurrentProcess()->HasSwitch(
86 "run-tab-capture-api-pixel-tests");
91 // Tests API behaviors, including info queries, and constraints violations.
92 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, ApiTests
) {
93 AddExtensionToCommandLineWhitelist();
94 ASSERT_TRUE(RunExtensionSubtest("tab_capture", "api_tests.html")) << message_
;
97 // Tests that tab capture video frames can be received in a VIDEO element.
98 IN_PROC_BROWSER_TEST_F(TabCaptureApiPixelTest
, EndToEndWithoutRemoting
) {
99 if (IsTooIntensiveForThisPlatform()) {
100 LOG(WARNING
) << "Skipping this CPU-intensive test on this platform/build.";
103 AddExtensionToCommandLineWhitelist();
104 ASSERT_TRUE(RunExtensionSubtest(
105 "tab_capture", "end_to_end.html?method=local&colorDeviation=10"))
109 // Tests that video frames are captured, transported via WebRTC, and finally
110 // received in a VIDEO element. More allowance is provided for color deviation
111 // because of the additional layers of video processing performed within
113 IN_PROC_BROWSER_TEST_F(TabCaptureApiPixelTest
, EndToEndThroughWebRTC
) {
114 if (IsTooIntensiveForThisPlatform()) {
115 LOG(WARNING
) << "Skipping this CPU-intensive test on this platform/build.";
118 AddExtensionToCommandLineWhitelist();
119 ASSERT_TRUE(RunExtensionSubtest(
120 "tab_capture", "end_to_end.html?method=webrtc&colorDeviation=50"))
124 // http://crbug.com/177163
125 #if defined(OS_WIN) && !defined(NDEBUG)
126 #define MAYBE_GetUserMediaTest DISABLED_GetUserMediaTest
128 #define MAYBE_GetUserMediaTest GetUserMediaTest
130 // Tests that getUserMedia() is NOT a way to start tab capture.
131 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_GetUserMediaTest
) {
132 ExtensionTestMessageListener
listener("ready", true);
134 ASSERT_TRUE(RunExtensionSubtest("tab_capture", "get_user_media_test.html"))
137 EXPECT_TRUE(listener
.WaitUntilSatisfied());
139 content::OpenURLParams
params(GURL("about:blank"), content::Referrer(),
141 ui::PAGE_TRANSITION_LINK
, false);
142 content::WebContents
* web_contents
= browser()->OpenURL(params
);
144 content::RenderFrameHost
* const main_frame
= web_contents
->GetMainFrame();
145 ASSERT_TRUE(main_frame
);
146 listener
.Reply(base::StringPrintf("web-contents-media-stream://%i:%i",
147 main_frame
->GetProcess()->GetID(),
148 main_frame
->GetRoutingID()));
150 ResultCatcher catcher
;
151 catcher
.RestrictToBrowserContext(browser()->profile());
152 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
155 // http://crbug.com/177163
156 #if defined(OS_WIN) && !defined(NDEBUG)
157 #define MAYBE_ActiveTabPermission DISABLED_ActiveTabPermission
159 #define MAYBE_ActiveTabPermission ActiveTabPermission
161 // Make sure tabCapture.capture only works if the tab has been granted
162 // permission via an extension icon click or the extension is whitelisted.
163 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_ActiveTabPermission
) {
164 ExtensionTestMessageListener
before_open_tab("ready1", true);
165 ExtensionTestMessageListener
before_grant_permission("ready2", true);
166 ExtensionTestMessageListener
before_open_new_tab("ready3", true);
167 ExtensionTestMessageListener
before_whitelist_extension("ready4", true);
169 ASSERT_TRUE(RunExtensionSubtest("tab_capture",
170 "active_tab_permission_test.html"))
173 // Open a new tab and make sure capture is denied.
174 EXPECT_TRUE(before_open_tab
.WaitUntilSatisfied());
175 content::OpenURLParams
params(GURL("http://google.com"), content::Referrer(),
177 ui::PAGE_TRANSITION_LINK
, false);
178 content::WebContents
* web_contents
= browser()->OpenURL(params
);
179 before_open_tab
.Reply("");
181 // Grant permission and make sure capture succeeds.
182 EXPECT_TRUE(before_grant_permission
.WaitUntilSatisfied());
183 const Extension
* extension
= ExtensionRegistry::Get(
184 web_contents
->GetBrowserContext())->enabled_extensions().GetByID(
186 TabHelper::FromWebContents(web_contents
)
187 ->active_tab_permission_granter()->GrantIfRequested(extension
);
188 before_grant_permission
.Reply("");
190 // Open a new tab and make sure capture is denied.
191 EXPECT_TRUE(before_open_new_tab
.WaitUntilSatisfied());
192 browser()->OpenURL(params
);
193 before_open_new_tab
.Reply("");
195 // Add extension to whitelist and make sure capture succeeds.
196 EXPECT_TRUE(before_whitelist_extension
.WaitUntilSatisfied());
197 AddExtensionToCommandLineWhitelist();
198 before_whitelist_extension
.Reply("");
200 ResultCatcher catcher
;
201 catcher
.RestrictToBrowserContext(browser()->profile());
202 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
205 // http://crbug.com/177163
206 #if defined(OS_WIN) && !defined(NDEBUG)
207 #define MAYBE_FullscreenEvents DISABLED_FullscreenEvents
209 #define MAYBE_FullscreenEvents FullscreenEvents
211 // Tests that fullscreen transitions during a tab capture session dispatch
212 // events to the onStatusChange listener. The test loads a page that toggles
213 // fullscreen mode, using the Fullscreen Javascript API, in response to mouse
215 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_FullscreenEvents
) {
216 AddExtensionToCommandLineWhitelist();
218 ExtensionTestMessageListener
capture_started("tab_capture_started", false);
219 ExtensionTestMessageListener
entered_fullscreen("entered_fullscreen", false);
221 ASSERT_TRUE(RunExtensionSubtest("tab_capture", "fullscreen_test.html"))
223 EXPECT_TRUE(capture_started
.WaitUntilSatisfied());
225 // Click on the page to trigger the Javascript that will toggle the tab into
227 SimulateMouseClickInCurrentTab();
228 EXPECT_TRUE(entered_fullscreen
.WaitUntilSatisfied());
230 // Click again to exit fullscreen mode.
231 SimulateMouseClickInCurrentTab();
233 // Wait until the page examines its results and calls chrome.test.succeed().
234 ResultCatcher catcher
;
235 catcher
.RestrictToBrowserContext(browser()->profile());
236 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
239 // Times out on Win dbg bots: http://crbug.com/177163
240 // Flaky on MSan bots: http://crbug.com/294431
241 #if (defined(OS_WIN) && !defined(NDEBUG)) || defined(MEMORY_SANITIZER)
242 #define MAYBE_GrantForChromePages DISABLED_GrantForChromePages
244 #define MAYBE_GrantForChromePages GrantForChromePages
246 // Make sure tabCapture API can be granted for Chrome:// pages.
247 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_GrantForChromePages
) {
248 ExtensionTestMessageListener
before_open_tab("ready1", true);
249 ASSERT_TRUE(RunExtensionSubtest("tab_capture",
250 "active_tab_chrome_pages.html"))
252 EXPECT_TRUE(before_open_tab
.WaitUntilSatisfied());
254 // Open a tab on a chrome:// page and make sure we can capture.
255 content::OpenURLParams
params(GURL("chrome://version"), content::Referrer(),
257 ui::PAGE_TRANSITION_LINK
, false);
258 content::WebContents
* web_contents
= browser()->OpenURL(params
);
259 const Extension
* extension
= ExtensionRegistry::Get(
260 web_contents
->GetBrowserContext())->enabled_extensions().GetByID(
262 TabHelper::FromWebContents(web_contents
)
263 ->active_tab_permission_granter()->GrantIfRequested(extension
);
264 before_open_tab
.Reply("");
266 ResultCatcher catcher
;
267 catcher
.RestrictToBrowserContext(browser()->profile());
268 EXPECT_TRUE(catcher
.GetNextResult()) << catcher
.message();
271 // http://crbug.com/177163
272 #if defined(OS_WIN) && !defined(NDEBUG)
273 #define MAYBE_CaptureInSplitIncognitoMode DISABLED_CaptureInSplitIncognitoMode
275 #define MAYBE_CaptureInSplitIncognitoMode CaptureInSplitIncognitoMode
277 // Tests that a tab in incognito mode can be captured.
278 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_CaptureInSplitIncognitoMode
) {
279 AddExtensionToCommandLineWhitelist();
280 ASSERT_TRUE(RunExtensionSubtest("tab_capture",
281 "start_tab_capture.html",
282 kFlagEnableIncognito
| kFlagUseIncognito
))
286 // http://crbug.com/177163
287 #if defined(OS_WIN) && !defined(NDEBUG)
288 #define MAYBE_Constraints DISABLED_Constraints
290 #define MAYBE_Constraints Constraints
292 // Tests that valid constraints allow tab capture to start, while invalid ones
294 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_Constraints
) {
295 AddExtensionToCommandLineWhitelist();
296 ASSERT_TRUE(RunExtensionSubtest("tab_capture", "constraints.html"))
300 // http://crbug.com/177163
301 #if defined(OS_WIN) && !defined(NDEBUG)
302 #define MAYBE_TabIndicator DISABLED_TabIndicator
304 #define MAYBE_TabIndicator TabIndicator
306 // Tests that the tab indicator (in the tab strip) is shown during tab capture.
307 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest
, MAYBE_TabIndicator
) {
308 ASSERT_EQ(TAB_MEDIA_STATE_NONE
,
309 chrome::GetTabMediaStateForContents(
310 browser()->tab_strip_model()->GetActiveWebContents()));
312 // Run an extension test that just turns on tab capture, which should cause
313 // the indicator to turn on.
314 AddExtensionToCommandLineWhitelist();
315 ASSERT_TRUE(RunExtensionSubtest("tab_capture", "start_tab_capture.html"))
318 // A TabStripModelObserver that quits the MessageLoop whenever the UI's model
319 // is sent an event that changes the indicator status.
320 class IndicatorChangeObserver
: public TabStripModelObserver
{
322 explicit IndicatorChangeObserver(Browser
* browser
)
323 : last_media_state_(chrome::GetTabMediaStateForContents(
324 browser
->tab_strip_model()->GetActiveWebContents())) {}
326 TabMediaState
last_media_state() const { return last_media_state_
; }
328 void TabChangedAt(content::WebContents
* contents
,
330 TabChangeType change_type
) override
{
331 const TabMediaState media_state
=
332 chrome::GetTabMediaStateForContents(contents
);
333 const bool has_changed
= media_state
!= last_media_state_
;
334 last_media_state_
= media_state
;
336 base::MessageLoop::current()->PostTask(
337 FROM_HERE
, base::MessageLoop::QuitClosure());
342 TabMediaState last_media_state_
;
345 // Run the browser until the indicator turns on.
346 IndicatorChangeObserver
observer(browser());
347 browser()->tab_strip_model()->AddObserver(&observer
);
348 const base::TimeTicks start_time
= base::TimeTicks::Now();
349 while (observer
.last_media_state() != TAB_MEDIA_STATE_CAPTURING
) {
350 if (base::TimeTicks::Now() - start_time
>
351 base::TimeDelta::FromSeconds(10)) {
352 EXPECT_EQ(TAB_MEDIA_STATE_CAPTURING
, observer
.last_media_state());
353 browser()->tab_strip_model()->RemoveObserver(&observer
);
356 content::RunMessageLoop();
358 browser()->tab_strip_model()->RemoveObserver(&observer
);
363 } // namespace extensions