Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / api / tab_capture / tab_capture_apitest.cc
blobe618eeac7bb44747c141ec2fdb54845be6d2b94f
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"
28 #if defined(OS_WIN)
29 #include "base/win/windows_version.h"
30 #endif
32 namespace extensions {
34 namespace {
36 const char kExtensionId[] = "ddchlicdkolnonkihahngkmmmjnjlkkf";
38 class TabCaptureApiTest : public ExtensionApiTest {
39 public:
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
43 // intensive.
44 command_line->AppendSwitchASCII(::switches::kWindowSize, "300,300");
47 void AddExtensionToCommandLineWhitelist() {
48 base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
49 switches::kWhitelistedExtensionID, kExtensionId);
52 protected:
53 void SimulateMouseClickInCurrentTab() {
54 content::SimulateMouseClick(
55 browser()->tab_strip_model()->GetActiveWebContents(),
57 blink::WebMouseEvent::ButtonLeft);
61 class TabCaptureApiPixelTest : public TabCaptureApiTest {
62 public:
63 void SetUp() override {
64 if (!IsTooIntensiveForThisPlatform())
65 EnablePixelOutput();
66 TabCaptureApiTest::SetUp();
69 protected:
70 bool IsTooIntensiveForThisPlatform() const {
71 #if defined(OS_WIN)
72 if (base::win::GetVersion() < base::win::VERSION_VISTA)
73 return true;
74 #endif
76 // The tests are too slow to succeed with OSMesa on the bots.
77 if (UsingOSMesa())
78 return true;
80 #if defined(NDEBUG)
81 return false;
82 #else
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");
88 #endif
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.";
102 return;
104 AddExtensionToCommandLineWhitelist();
105 ASSERT_TRUE(RunExtensionSubtest(
106 "tab_capture", "end_to_end.html?method=local&colorDeviation=10"))
107 << message_;
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
113 // WebRTC.
114 IN_PROC_BROWSER_TEST_F(TabCaptureApiPixelTest, EndToEndThroughWebRTC) {
115 if (IsTooIntensiveForThisPlatform()) {
116 LOG(WARNING) << "Skipping this CPU-intensive test on this platform/build.";
117 return;
119 AddExtensionToCommandLineWhitelist();
120 ASSERT_TRUE(RunExtensionSubtest(
121 "tab_capture", "end_to_end.html?method=webrtc&colorDeviation=50"))
122 << message_;
125 // http://crbug.com/177163
126 #if defined(OS_WIN) && !defined(NDEBUG)
127 #define MAYBE_GetUserMediaTest DISABLED_GetUserMediaTest
128 #else
129 #define MAYBE_GetUserMediaTest GetUserMediaTest
130 #endif
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"))
136 << message_;
138 EXPECT_TRUE(listener.WaitUntilSatisfied());
140 content::OpenURLParams params(GURL("about:blank"), content::Referrer(),
141 NEW_FOREGROUND_TAB,
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
159 #else
160 #define MAYBE_ActiveTabPermission ActiveTabPermission
161 #endif
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"))
172 << message_;
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(),
177 NEW_FOREGROUND_TAB,
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(
186 kExtensionId);
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
209 #else
210 #define MAYBE_FullscreenEvents FullscreenEvents
211 #endif
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
215 // clicks.
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"))
223 << message_;
224 EXPECT_TRUE(capture_started.WaitUntilSatisfied());
226 // Click on the page to trigger the Javascript that will toggle the tab into
227 // fullscreen mode.
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
244 #else
245 #define MAYBE_GrantForChromePages GrantForChromePages
246 #endif
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"))
252 << message_;
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(),
257 NEW_FOREGROUND_TAB,
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(
262 kExtensionId);
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
275 #else
276 #define MAYBE_CaptureInSplitIncognitoMode CaptureInSplitIncognitoMode
277 #endif
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))
284 << message_;
287 // http://crbug.com/177163
288 #if defined(OS_WIN) && !defined(NDEBUG)
289 #define MAYBE_Constraints DISABLED_Constraints
290 #else
291 #define MAYBE_Constraints Constraints
292 #endif
293 // Tests that valid constraints allow tab capture to start, while invalid ones
294 // do not.
295 IN_PROC_BROWSER_TEST_F(TabCaptureApiTest, MAYBE_Constraints) {
296 AddExtensionToCommandLineWhitelist();
297 ASSERT_TRUE(RunExtensionSubtest("tab_capture", "constraints.html"))
298 << message_;
301 // http://crbug.com/177163
302 #if defined(OS_WIN) && !defined(NDEBUG)
303 #define MAYBE_TabIndicator DISABLED_TabIndicator
304 #else
305 // Also flaky everywhere else: https://crbug.com/530657
306 #define MAYBE_TabIndicator DISABLED_TabIndicator
307 #endif
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"))
318 << message_;
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 {
323 public:
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,
331 int index,
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;
337 if (has_changed) {
338 base::ThreadTaskRunnerHandle::Get()->PostTask(
339 FROM_HERE, base::MessageLoop::QuitClosure());
343 private:
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);
356 return;
358 content::RunMessageLoop();
360 browser()->tab_strip_model()->RemoveObserver(&observer);
363 } // namespace
365 } // namespace extensions