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.
8 #include "base/memory/ref_counted.h"
9 #include "base/memory/scoped_ptr.h"
10 #include "base/prefs/pref_service.h"
11 #include "base/strings/pattern.h"
12 #include "base/strings/string_split.h"
13 #include "base/strings/string_util.h"
14 #include "base/strings/stringprintf.h"
15 #include "base/values.h"
16 #include "chrome/browser/apps/app_browsertest_util.h"
17 #include "chrome/browser/devtools/devtools_window_testing.h"
18 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
19 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
20 #include "chrome/browser/extensions/extension_apitest.h"
21 #include "chrome/browser/extensions/extension_function_test_utils.h"
22 #include "chrome/browser/extensions/extension_tab_util.h"
23 #include "chrome/browser/extensions/window_controller.h"
24 #include "chrome/browser/prefs/incognito_mode_prefs.h"
25 #include "chrome/browser/profiles/profile.h"
26 #include "chrome/browser/ui/browser.h"
27 #include "chrome/browser/ui/browser_commands.h"
28 #include "chrome/browser/ui/browser_window.h"
29 #include "chrome/browser/ui/tabs/tab_strip_model.h"
30 #include "chrome/browser/ui/views/frame/browser_view.h"
31 #include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h"
32 #include "chrome/test/base/ui_test_utils.h"
33 #include "content/public/browser/browser_context.h"
34 #include "content/public/browser/storage_partition.h"
35 #include "content/public/common/page_zoom.h"
36 #include "content/public/common/url_constants.h"
37 #include "extensions/browser/api_test_utils.h"
38 #include "extensions/browser/app_window/app_window.h"
39 #include "extensions/browser/app_window/app_window_registry.h"
40 #include "extensions/browser/app_window/native_app_window.h"
41 #include "extensions/common/manifest_constants.h"
42 #include "extensions/common/test_util.h"
43 #include "extensions/test/extension_test_message_listener.h"
44 #include "extensions/test/result_catcher.h"
45 #include "net/test/spawned_test_server/spawned_test_server.h"
46 #include "ui/gfx/geometry/rect.h"
47 #include "ui/views/widget/widget.h"
48 #include "ui/views/widget/widget_observer.h"
50 namespace extensions
{
52 namespace keys
= tabs_constants
;
53 namespace utils
= extension_function_test_utils
;
56 using ExtensionTabsTest
= PlatformAppBrowserTest
;
58 class ExtensionWindowCreateTest
: public InProcessBrowserTest
{
60 // Runs chrome.windows.create(), expecting an error.
61 std::string
RunCreateWindowExpectError(const std::string
& args
) {
62 scoped_refptr
<WindowsCreateFunction
> function(new WindowsCreateFunction
);
63 function
->set_extension(test_util::CreateEmptyExtension().get());
64 return api_test_utils::RunFunctionAndReturnError(function
.get(), args
,
65 browser()->profile());
69 const int kUndefinedId
= INT_MIN
;
71 int GetTabId(base::DictionaryValue
* tab
) {
72 int id
= kUndefinedId
;
74 tab
->GetInteger(keys::kIdKey
, &id
);
78 int GetTabWindowId(base::DictionaryValue
* tab
) {
79 int id
= kUndefinedId
;
81 tab
->GetInteger(keys::kWindowIdKey
, &id
);
85 int GetWindowId(base::DictionaryValue
* window
) {
86 int id
= kUndefinedId
;
88 window
->GetInteger(keys::kIdKey
, &id
);
94 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, GetWindow
) {
95 int window_id
= ExtensionTabUtil::GetWindowId(browser());
97 // Invalid window ID error.
98 scoped_refptr
<WindowsGetFunction
> function
= new WindowsGetFunction();
99 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension());
100 function
->set_extension(extension
.get());
101 EXPECT_TRUE(base::MatchPattern(
102 utils::RunFunctionAndReturnError(
103 function
.get(), base::StringPrintf("[%u]", window_id
+ 1), browser()),
104 keys::kWindowNotFoundError
));
106 // Basic window details.
108 if (browser()->window()->IsMinimized())
109 bounds
= browser()->window()->GetRestoredBounds();
111 bounds
= browser()->window()->GetBounds();
113 function
= new WindowsGetFunction();
114 function
->set_extension(extension
.get());
115 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(
116 utils::RunFunctionAndReturnSingleResult(
118 base::StringPrintf("[%u]", window_id
),
120 EXPECT_EQ(window_id
, GetWindowId(result
.get()));
121 EXPECT_FALSE(api_test_utils::GetBoolean(result
.get(), "incognito"));
122 EXPECT_EQ("normal", api_test_utils::GetString(result
.get(), "type"));
123 EXPECT_EQ(bounds
.x(), api_test_utils::GetInteger(result
.get(), "left"));
124 EXPECT_EQ(bounds
.y(), api_test_utils::GetInteger(result
.get(), "top"));
125 EXPECT_EQ(bounds
.width(), api_test_utils::GetInteger(result
.get(), "width"));
126 EXPECT_EQ(bounds
.height(),
127 api_test_utils::GetInteger(result
.get(), "height"));
129 // With "populate" enabled.
130 function
= new WindowsGetFunction();
131 function
->set_extension(extension
.get());
132 result
.reset(utils::ToDictionary(
133 utils::RunFunctionAndReturnSingleResult(
135 base::StringPrintf("[%u, {\"populate\": true}]", window_id
),
138 EXPECT_EQ(window_id
, GetWindowId(result
.get()));
139 // "populate" was enabled so tabs should be populated.
140 base::ListValue
* tabs
= nullptr;
141 EXPECT_TRUE(result
.get()->GetList(keys::kTabsKey
, &tabs
));
143 base::Value
* tab0
= nullptr;
144 EXPECT_TRUE(tabs
->Get(0, &tab0
));
145 EXPECT_GE(GetTabId(utils::ToDictionary(tab0
)), 0);
147 // TODO(aa): Can't assume window is focused. On mac, calling Activate() from a
148 // browser test doesn't seem to do anything, so can't test the opposite
150 EXPECT_EQ(browser()->window()->IsActive(),
151 api_test_utils::GetBoolean(result
.get(), "focused"));
153 // TODO(aa): Minimized and maximized dimensions. Is there a way to set
154 // minimize/maximize programmatically?
157 Browser
* popup_browser
= new Browser(
158 Browser::CreateParams(Browser::TYPE_POPUP
, browser()->profile(),
159 browser()->host_desktop_type()));
160 function
= new WindowsGetFunction();
161 function
->set_extension(extension
.get());
162 result
.reset(utils::ToDictionary(
163 utils::RunFunctionAndReturnSingleResult(
166 "[%u]", ExtensionTabUtil::GetWindowId(popup_browser
)),
168 EXPECT_EQ("popup", api_test_utils::GetString(result
.get(), "type"));
171 Browser
* incognito_browser
= CreateIncognitoBrowser();
172 int incognito_window_id
= ExtensionTabUtil::GetWindowId(incognito_browser
);
174 // Without "include_incognito".
175 function
= new WindowsGetFunction();
176 function
->set_extension(extension
.get());
177 EXPECT_TRUE(base::MatchPattern(
178 utils::RunFunctionAndReturnError(
179 function
.get(), base::StringPrintf("[%u]", incognito_window_id
),
181 keys::kWindowNotFoundError
));
183 // With "include_incognito".
184 function
= new WindowsGetFunction();
185 function
->set_extension(extension
.get());
186 result
.reset(utils::ToDictionary(
187 utils::RunFunctionAndReturnSingleResult(
189 base::StringPrintf("[%u]", incognito_window_id
),
191 utils::INCLUDE_INCOGNITO
)));
192 EXPECT_TRUE(api_test_utils::GetBoolean(result
.get(), "incognito"));
195 DevToolsWindow
* devtools
= DevToolsWindowTesting::OpenDevToolsWindowSync(
196 browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
198 function
= new WindowsGetFunction();
199 function
->set_extension(extension
.get());
200 result
.reset(utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
202 base::StringPrintf("[%u, {\"windowTypes\": [\"devtools\"]}]",
203 ExtensionTabUtil::GetWindowId(
204 DevToolsWindowTesting::Get(devtools
)->browser())),
205 browser(), utils::INCLUDE_INCOGNITO
)));
206 EXPECT_EQ("devtools", api_test_utils::GetString(result
.get(), "type"));
208 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools
);
211 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, GetCurrentWindow
) {
212 int window_id
= ExtensionTabUtil::GetWindowId(browser());
213 Browser
* new_browser
= CreateBrowser(browser()->profile());
214 int new_id
= ExtensionTabUtil::GetWindowId(new_browser
);
216 // Get the current window using new_browser.
217 scoped_refptr
<WindowsGetCurrentFunction
> function
=
218 new WindowsGetCurrentFunction();
219 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension());
220 function
->set_extension(extension
.get());
221 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(
222 utils::RunFunctionAndReturnSingleResult(function
.get(),
226 // The id should match the window id of the browser instance that was passed
227 // to RunFunctionAndReturnSingleResult.
228 EXPECT_EQ(new_id
, GetWindowId(result
.get()));
229 base::ListValue
* tabs
= nullptr;
230 EXPECT_FALSE(result
.get()->GetList(keys::kTabsKey
, &tabs
));
232 // Get the current window using the old window and make the tabs populated.
233 function
= new WindowsGetCurrentFunction();
234 function
->set_extension(extension
.get());
235 result
.reset(utils::ToDictionary(
236 utils::RunFunctionAndReturnSingleResult(function
.get(),
237 "[{\"populate\": true}]",
240 // The id should match the window id of the browser instance that was passed
241 // to RunFunctionAndReturnSingleResult.
242 EXPECT_EQ(window_id
, GetWindowId(result
.get()));
243 // "populate" was enabled so tabs should be populated.
244 EXPECT_TRUE(result
.get()->GetList(keys::kTabsKey
, &tabs
));
246 // The tab id should not be -1 as this is a browser window.
247 base::Value
* tab0
= nullptr;
248 EXPECT_TRUE(tabs
->Get(0, &tab0
));
249 EXPECT_GE(GetTabId(utils::ToDictionary(tab0
)), 0);
252 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, GetAllWindows
) {
253 const size_t NUM_WINDOWS
= 5;
254 std::set
<int> window_ids
;
255 std::set
<int> result_ids
;
256 window_ids
.insert(ExtensionTabUtil::GetWindowId(browser()));
258 for (size_t i
= 0; i
< NUM_WINDOWS
- 1; ++i
) {
259 Browser
* new_browser
= CreateBrowser(browser()->profile());
260 window_ids
.insert(ExtensionTabUtil::GetWindowId(new_browser
));
263 // Application windows should not be accessible, unless allWindowTypes is set
265 AppWindow
* app_window
= CreateTestAppWindow("{}");
267 // Undocked DevTools window should not be accessible, unless allWindowTypes is
269 DevToolsWindow
* devtools
= DevToolsWindowTesting::OpenDevToolsWindowSync(
270 browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
272 scoped_refptr
<WindowsGetAllFunction
> function
= new WindowsGetAllFunction();
273 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension());
274 function
->set_extension(extension
.get());
275 scoped_ptr
<base::ListValue
> result(utils::ToList(
276 utils::RunFunctionAndReturnSingleResult(function
.get(),
280 base::ListValue
* windows
= result
.get();
281 EXPECT_EQ(window_ids
.size(), windows
->GetSize());
282 for (size_t i
= 0; i
< windows
->GetSize(); ++i
) {
283 base::DictionaryValue
* result_window
= nullptr;
284 EXPECT_TRUE(windows
->GetDictionary(i
, &result_window
));
285 result_ids
.insert(GetWindowId(result_window
));
287 // "populate" was not passed in so tabs are not populated.
288 base::ListValue
* tabs
= nullptr;
289 EXPECT_FALSE(result_window
->GetList(keys::kTabsKey
, &tabs
));
291 // The returned ids should contain all the current browser instance ids.
292 EXPECT_EQ(window_ids
, result_ids
);
295 function
= new WindowsGetAllFunction();
296 function
->set_extension(extension
.get());
297 result
.reset(utils::ToList(
298 utils::RunFunctionAndReturnSingleResult(function
.get(),
299 "[{\"populate\": true}]",
302 windows
= result
.get();
303 EXPECT_EQ(window_ids
.size(), windows
->GetSize());
304 for (size_t i
= 0; i
< windows
->GetSize(); ++i
) {
305 base::DictionaryValue
* result_window
= nullptr;
306 EXPECT_TRUE(windows
->GetDictionary(i
, &result_window
));
307 result_ids
.insert(GetWindowId(result_window
));
309 // "populate" was enabled so tabs should be populated.
310 base::ListValue
* tabs
= nullptr;
311 EXPECT_TRUE(result_window
->GetList(keys::kTabsKey
, &tabs
));
313 // The returned ids should contain all the current app, browser and
314 // devtools instance ids.
315 EXPECT_EQ(window_ids
, result_ids
);
317 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools
);
319 CloseAppWindow(app_window
);
322 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, GetAllWindowsAllTypes
) {
323 const size_t NUM_WINDOWS
= 5;
324 std::set
<int> window_ids
;
325 std::set
<int> result_ids
;
326 window_ids
.insert(ExtensionTabUtil::GetWindowId(browser()));
328 for (size_t i
= 0; i
< NUM_WINDOWS
- 1; ++i
) {
329 Browser
* new_browser
= CreateBrowser(browser()->profile());
330 window_ids
.insert(ExtensionTabUtil::GetWindowId(new_browser
));
333 // Application windows should be accessible.
334 AppWindow
* app_window
= CreateTestAppWindow("{}");
335 window_ids
.insert(app_window
->session_id().id());
337 // Undocked DevTools window should be accessible too.
338 DevToolsWindow
* devtools
= DevToolsWindowTesting::OpenDevToolsWindowSync(
339 browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
340 window_ids
.insert(ExtensionTabUtil::GetWindowId(
341 DevToolsWindowTesting::Get(devtools
)->browser()));
343 scoped_refptr
<WindowsGetAllFunction
> function
= new WindowsGetAllFunction();
344 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension());
345 function
->set_extension(extension
.get());
346 scoped_ptr
<base::ListValue
> result(
347 utils::ToList(utils::RunFunctionAndReturnSingleResult(
349 "[{\"windowTypes\": [\"app\", \"devtools\", \"normal\", \"panel\", "
353 base::ListValue
* windows
= result
.get();
354 EXPECT_EQ(window_ids
.size(), windows
->GetSize());
355 for (size_t i
= 0; i
< windows
->GetSize(); ++i
) {
356 base::DictionaryValue
* result_window
= nullptr;
357 EXPECT_TRUE(windows
->GetDictionary(i
, &result_window
));
358 result_ids
.insert(GetWindowId(result_window
));
360 // "populate" was not passed in so tabs are not populated.
361 base::ListValue
* tabs
= nullptr;
362 EXPECT_FALSE(result_window
->GetList(keys::kTabsKey
, &tabs
));
364 // The returned ids should contain all the current app, browser and
365 // devtools instance ids.
366 EXPECT_EQ(window_ids
, result_ids
);
369 function
= new WindowsGetAllFunction();
370 function
->set_extension(extension
.get());
371 result
.reset(utils::ToList(utils::RunFunctionAndReturnSingleResult(
373 "[{\"populate\": true, \"windowTypes\": [\"app\", \"devtools\", "
374 "\"normal\", \"panel\", \"popup\"]}]",
377 windows
= result
.get();
378 EXPECT_EQ(window_ids
.size(), windows
->GetSize());
379 for (size_t i
= 0; i
< windows
->GetSize(); ++i
) {
380 base::DictionaryValue
* result_window
= nullptr;
381 EXPECT_TRUE(windows
->GetDictionary(i
, &result_window
));
382 result_ids
.insert(GetWindowId(result_window
));
384 // "populate" was enabled so tabs should be populated.
385 base::ListValue
* tabs
= nullptr;
386 EXPECT_TRUE(result_window
->GetList(keys::kTabsKey
, &tabs
));
388 // The returned ids should contain all the current app, browser and
389 // devtools instance ids.
390 EXPECT_EQ(window_ids
, result_ids
);
392 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools
);
394 CloseAppWindow(app_window
);
397 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, UpdateNoPermissions
) {
398 // The test empty extension has no permissions, therefore it should not get
399 // tab data in the function result.
400 scoped_refptr
<TabsUpdateFunction
> update_tab_function(
401 new TabsUpdateFunction());
402 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
403 update_tab_function
->set_extension(empty_extension
.get());
404 // Without a callback the function will not generate a result.
405 update_tab_function
->set_has_callback(true);
407 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(
408 utils::RunFunctionAndReturnSingleResult(
409 update_tab_function
.get(),
410 "[null, {\"url\": \"about:blank\", \"pinned\": true}]",
412 // The url is stripped since the extension does not have tab permissions.
413 EXPECT_FALSE(result
->HasKey("url"));
414 EXPECT_TRUE(api_test_utils::GetBoolean(result
.get(), "pinned"));
417 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
,
418 DefaultToIncognitoWhenItIsForced
) {
419 static const char kArgsWithoutExplicitIncognitoParam
[] =
420 "[{\"url\": \"about:blank\"}]";
421 // Force Incognito mode.
422 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
423 IncognitoModePrefs::FORCED
);
424 // Run without an explicit "incognito" param.
425 scoped_refptr
<WindowsCreateFunction
> function(new WindowsCreateFunction());
426 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension());
427 function
->set_extension(extension
.get());
428 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(
429 utils::RunFunctionAndReturnSingleResult(
431 kArgsWithoutExplicitIncognitoParam
,
433 utils::INCLUDE_INCOGNITO
)));
435 // Make sure it is a new(different) window.
436 EXPECT_NE(ExtensionTabUtil::GetWindowId(browser()),
437 GetWindowId(result
.get()));
438 // ... and it is incognito.
439 EXPECT_TRUE(api_test_utils::GetBoolean(result
.get(), "incognito"));
441 // Now try creating a window from incognito window.
442 Browser
* incognito_browser
= CreateIncognitoBrowser();
443 // Run without an explicit "incognito" param.
444 function
= new WindowsCreateFunction();
445 function
->set_extension(extension
.get());
446 result
.reset(utils::ToDictionary(
447 utils::RunFunctionAndReturnSingleResult(
449 kArgsWithoutExplicitIncognitoParam
,
451 utils::INCLUDE_INCOGNITO
)));
452 // Make sure it is a new(different) window.
453 EXPECT_NE(ExtensionTabUtil::GetWindowId(incognito_browser
),
454 GetWindowId(result
.get()));
455 // ... and it is incognito.
456 EXPECT_TRUE(api_test_utils::GetBoolean(result
.get(), "incognito"));
459 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
,
460 DefaultToIncognitoWhenItIsForcedAndNoArgs
) {
461 static const char kEmptyArgs
[] = "[]";
462 // Force Incognito mode.
463 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
464 IncognitoModePrefs::FORCED
);
465 // Run without an explicit "incognito" param.
466 scoped_refptr
<WindowsCreateFunction
> function
= new WindowsCreateFunction();
467 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension());
468 function
->set_extension(extension
.get());
469 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(
470 utils::RunFunctionAndReturnSingleResult(function
.get(),
473 utils::INCLUDE_INCOGNITO
)));
475 // Make sure it is a new(different) window.
476 EXPECT_NE(ExtensionTabUtil::GetWindowId(browser()),
477 GetWindowId(result
.get()));
478 // ... and it is incognito.
479 EXPECT_TRUE(api_test_utils::GetBoolean(result
.get(), "incognito"));
481 // Now try creating a window from incognito window.
482 Browser
* incognito_browser
= CreateIncognitoBrowser();
483 // Run without an explicit "incognito" param.
484 function
= new WindowsCreateFunction();
485 function
->set_extension(extension
.get());
486 result
.reset(utils::ToDictionary(
487 utils::RunFunctionAndReturnSingleResult(function
.get(),
490 utils::INCLUDE_INCOGNITO
)));
491 // Make sure it is a new(different) window.
492 EXPECT_NE(ExtensionTabUtil::GetWindowId(incognito_browser
),
493 GetWindowId(result
.get()));
494 // ... and it is incognito.
495 EXPECT_TRUE(api_test_utils::GetBoolean(result
.get(), "incognito"));
498 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
,
499 DontCreateNormalWindowWhenIncognitoForced
) {
500 static const char kArgsWithExplicitIncognitoParam
[] =
501 "[{\"url\": \"about:blank\", \"incognito\": false }]";
502 // Force Incognito mode.
503 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
504 IncognitoModePrefs::FORCED
);
506 // Run with an explicit "incognito" param.
507 scoped_refptr
<WindowsCreateFunction
> function
= new WindowsCreateFunction();
508 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension());
509 function
->set_extension(extension
.get());
510 EXPECT_TRUE(base::MatchPattern(
511 utils::RunFunctionAndReturnError(
512 function
.get(), kArgsWithExplicitIncognitoParam
, browser()),
513 keys::kIncognitoModeIsForced
));
515 // Now try opening a normal window from incognito window.
516 Browser
* incognito_browser
= CreateIncognitoBrowser();
517 // Run with an explicit "incognito" param.
518 function
= new WindowsCreateFunction();
519 function
->set_extension(extension
.get());
520 EXPECT_TRUE(base::MatchPattern(
521 utils::RunFunctionAndReturnError(
522 function
.get(), kArgsWithExplicitIncognitoParam
, incognito_browser
),
523 keys::kIncognitoModeIsForced
));
526 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
,
527 DontCreateIncognitoWindowWhenIncognitoDisabled
) {
528 static const char kArgs
[] =
529 "[{\"url\": \"about:blank\", \"incognito\": true }]";
531 Browser
* incognito_browser
= CreateIncognitoBrowser();
532 // Disable Incognito mode.
533 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
534 IncognitoModePrefs::DISABLED
);
535 // Run in normal window.
536 scoped_refptr
<WindowsCreateFunction
> function
= new WindowsCreateFunction();
537 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension());
538 function
->set_extension(extension
.get());
539 EXPECT_TRUE(base::MatchPattern(
540 utils::RunFunctionAndReturnError(function
.get(), kArgs
, browser()),
541 keys::kIncognitoModeIsDisabled
));
543 // Run in incognito window.
544 function
= new WindowsCreateFunction();
545 function
->set_extension(extension
.get());
546 EXPECT_TRUE(base::MatchPattern(utils::RunFunctionAndReturnError(
547 function
.get(), kArgs
, incognito_browser
),
548 keys::kIncognitoModeIsDisabled
));
551 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, QueryCurrentWindowTabs
) {
552 const size_t kExtraWindows
= 3;
553 for (size_t i
= 0; i
< kExtraWindows
; ++i
)
554 CreateBrowser(browser()->profile());
556 GURL
url(url::kAboutBlankURL
);
557 AddTabAtIndex(0, url
, ui::PAGE_TRANSITION_LINK
);
558 int window_id
= ExtensionTabUtil::GetWindowId(browser());
560 // Get tabs in the 'current' window called from non-focused browser.
561 scoped_refptr
<TabsQueryFunction
> function
= new TabsQueryFunction();
562 function
->set_extension(test_util::CreateEmptyExtension().get());
563 scoped_ptr
<base::ListValue
> result(utils::ToList(
564 utils::RunFunctionAndReturnSingleResult(function
.get(),
565 "[{\"currentWindow\":true}]",
568 base::ListValue
* result_tabs
= result
.get();
569 // We should have one initial tab and one added tab.
570 EXPECT_EQ(2u, result_tabs
->GetSize());
571 for (size_t i
= 0; i
< result_tabs
->GetSize(); ++i
) {
572 base::DictionaryValue
* result_tab
= nullptr;
573 EXPECT_TRUE(result_tabs
->GetDictionary(i
, &result_tab
));
574 EXPECT_EQ(window_id
, GetTabWindowId(result_tab
));
577 // Get tabs NOT in the 'current' window called from non-focused browser.
578 function
= new TabsQueryFunction();
579 function
->set_extension(test_util::CreateEmptyExtension().get());
580 result
.reset(utils::ToList(
581 utils::RunFunctionAndReturnSingleResult(function
.get(),
582 "[{\"currentWindow\":false}]",
585 result_tabs
= result
.get();
586 // We should have one tab for each extra window.
587 EXPECT_EQ(kExtraWindows
, result_tabs
->GetSize());
588 for (size_t i
= 0; i
< kExtraWindows
; ++i
) {
589 base::DictionaryValue
* result_tab
= nullptr;
590 EXPECT_TRUE(result_tabs
->GetDictionary(i
, &result_tab
));
591 EXPECT_NE(window_id
, GetTabWindowId(result_tab
));
595 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, QueryAllTabsWithDevTools
) {
596 const size_t kNumWindows
= 3;
597 std::set
<int> window_ids
;
598 window_ids
.insert(ExtensionTabUtil::GetWindowId(browser()));
599 for (size_t i
= 0; i
< kNumWindows
- 1; ++i
) {
600 Browser
* new_browser
= CreateBrowser(browser()->profile());
601 window_ids
.insert(ExtensionTabUtil::GetWindowId(new_browser
));
604 // Undocked DevTools window should not be accessible.
605 DevToolsWindow
* devtools
= DevToolsWindowTesting::OpenDevToolsWindowSync(
606 browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
608 // Get tabs in the 'current' window called from non-focused browser.
609 scoped_refptr
<TabsQueryFunction
> function
= new TabsQueryFunction();
610 function
->set_extension(test_util::CreateEmptyExtension().get());
611 scoped_ptr
<base::ListValue
> result(utils::ToList(
612 utils::RunFunctionAndReturnSingleResult(function
.get(),
616 std::set
<int> result_ids
;
617 base::ListValue
* result_tabs
= result
.get();
618 // We should have one tab per browser except for DevTools.
619 EXPECT_EQ(kNumWindows
, result_tabs
->GetSize());
620 for (size_t i
= 0; i
< result_tabs
->GetSize(); ++i
) {
621 base::DictionaryValue
* result_tab
= nullptr;
622 EXPECT_TRUE(result_tabs
->GetDictionary(i
, &result_tab
));
623 result_ids
.insert(GetTabWindowId(result_tab
));
625 EXPECT_EQ(window_ids
, result_ids
);
627 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools
);
630 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, DontCreateTabInClosingPopupWindow
) {
631 // Test creates new popup window, closes it right away and then tries to open
632 // a new tab in it. Tab should not be opened in the popup window, but in a
633 // tabbed browser window.
634 Browser
* popup_browser
= new Browser(
635 Browser::CreateParams(Browser::TYPE_POPUP
, browser()->profile(),
636 browser()->host_desktop_type()));
637 int window_id
= ExtensionTabUtil::GetWindowId(popup_browser
);
638 chrome::CloseWindow(popup_browser
);
640 scoped_refptr
<TabsCreateFunction
> create_tab_function(
641 new TabsCreateFunction());
642 create_tab_function
->set_extension(test_util::CreateEmptyExtension().get());
643 // Without a callback the function will not generate a result.
644 create_tab_function
->set_has_callback(true);
646 static const char kNewBlankTabArgs
[] =
647 "[{\"url\": \"about:blank\", \"windowId\": %u}]";
649 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(
650 utils::RunFunctionAndReturnSingleResult(
651 create_tab_function
.get(),
652 base::StringPrintf(kNewBlankTabArgs
, window_id
),
655 EXPECT_NE(window_id
, GetTabWindowId(result
.get()));
658 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, InvalidUpdateWindowState
) {
659 int window_id
= ExtensionTabUtil::GetWindowId(browser());
661 static const char kArgsMinimizedWithFocus
[] =
662 "[%u, {\"state\": \"minimized\", \"focused\": true}]";
663 scoped_refptr
<WindowsUpdateFunction
> function
= new WindowsUpdateFunction();
664 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension());
665 function
->set_extension(extension
.get());
666 EXPECT_TRUE(base::MatchPattern(
667 utils::RunFunctionAndReturnError(
669 base::StringPrintf(kArgsMinimizedWithFocus
, window_id
), browser()),
670 keys::kInvalidWindowStateError
));
672 static const char kArgsMaximizedWithoutFocus
[] =
673 "[%u, {\"state\": \"maximized\", \"focused\": false}]";
674 function
= new WindowsUpdateFunction();
675 function
->set_extension(extension
.get());
676 EXPECT_TRUE(base::MatchPattern(
677 utils::RunFunctionAndReturnError(
679 base::StringPrintf(kArgsMaximizedWithoutFocus
, window_id
), browser()),
680 keys::kInvalidWindowStateError
));
682 static const char kArgsMinimizedWithBounds
[] =
683 "[%u, {\"state\": \"minimized\", \"width\": 500}]";
684 function
= new WindowsUpdateFunction();
685 function
->set_extension(extension
.get());
686 EXPECT_TRUE(base::MatchPattern(
687 utils::RunFunctionAndReturnError(
689 base::StringPrintf(kArgsMinimizedWithBounds
, window_id
), browser()),
690 keys::kInvalidWindowStateError
));
692 static const char kArgsMaximizedWithBounds
[] =
693 "[%u, {\"state\": \"maximized\", \"width\": 500}]";
694 function
= new WindowsUpdateFunction();
695 function
->set_extension(extension
.get());
696 EXPECT_TRUE(base::MatchPattern(
697 utils::RunFunctionAndReturnError(
699 base::StringPrintf(kArgsMaximizedWithBounds
, window_id
), browser()),
700 keys::kInvalidWindowStateError
));
703 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, UpdateAppWindowSizeConstraint
) {
704 AppWindow
* app_window
= CreateTestAppWindow(
706 "{\"width\": 300, \"height\": 300,"
707 " \"minWidth\": 200, \"minHeight\": 200,"
708 " \"maxWidth\": 400, \"maxHeight\": 400}}");
710 scoped_refptr
<WindowsGetFunction
> get_function
= new WindowsGetFunction();
711 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension().get());
712 get_function
->set_extension(extension
.get());
713 scoped_ptr
<base::DictionaryValue
> result(
714 utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
716 base::StringPrintf("[%u, {\"windowTypes\": [\"app\"]}]",
717 app_window
->session_id().id()),
720 EXPECT_EQ(300, api_test_utils::GetInteger(result
.get(), "width"));
721 EXPECT_EQ(300, api_test_utils::GetInteger(result
.get(), "height"));
723 // Verify the min width/height of the application window are
725 scoped_refptr
<WindowsUpdateFunction
> update_min_function
=
726 new WindowsUpdateFunction();
727 result
.reset(utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
728 update_min_function
.get(),
729 base::StringPrintf("[%u, {\"width\": 100, \"height\": 100}]",
730 app_window
->session_id().id()),
733 EXPECT_EQ(200, api_test_utils::GetInteger(result
.get(), "width"));
734 EXPECT_EQ(200, api_test_utils::GetInteger(result
.get(), "height"));
736 // Verify the max width/height of the application window are
738 scoped_refptr
<WindowsUpdateFunction
> update_max_function
=
739 new WindowsUpdateFunction();
740 result
.reset(utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
741 update_max_function
.get(),
742 base::StringPrintf("[%u, {\"width\": 500, \"height\": 500}]",
743 app_window
->session_id().id()),
746 EXPECT_EQ(400, api_test_utils::GetInteger(result
.get(), "width"));
747 EXPECT_EQ(400, api_test_utils::GetInteger(result
.get(), "height"));
749 CloseAppWindow(app_window
);
752 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, UpdateDevToolsWindow
) {
753 DevToolsWindow
* devtools
= DevToolsWindowTesting::OpenDevToolsWindowSync(
754 browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
756 scoped_refptr
<WindowsGetFunction
> get_function
= new WindowsGetFunction();
757 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension().get());
758 get_function
->set_extension(extension
.get());
759 scoped_ptr
<base::DictionaryValue
> result(
760 utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
763 "[%u, {\"windowTypes\": [\"devtools\"]}]",
764 ExtensionTabUtil::GetWindowId(
765 DevToolsWindowTesting::Get(devtools
)->browser())),
768 // Verify the updating width/height works.
769 int32_t new_width
= api_test_utils::GetInteger(result
.get(), "width") - 50;
770 int32_t new_height
= api_test_utils::GetInteger(result
.get(), "height") - 50;
772 scoped_refptr
<WindowsUpdateFunction
> update_function
=
773 new WindowsUpdateFunction();
774 result
.reset(utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
775 update_function
.get(),
776 base::StringPrintf("[%u, {\"width\": %d, \"height\": %d}]",
777 ExtensionTabUtil::GetWindowId(
778 DevToolsWindowTesting::Get(devtools
)->browser()),
779 new_width
, new_height
),
782 EXPECT_EQ(new_width
, api_test_utils::GetInteger(result
.get(), "width"));
783 EXPECT_EQ(new_height
, api_test_utils::GetInteger(result
.get(), "height"));
785 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools
);
788 // TODO(llandwerlin): Activating a browser window and waiting for the
789 // action to happen requires views::Widget which is not available on
790 // MacOSX. Deactivate for now.
791 #if !defined(OS_MACOSX)
792 class ExtensionWindowLastFocusedTest
: public ExtensionTabsTest
{
794 void SetUpOnMainThread() override
;
796 void ActivateAppWindow(AppWindow
* app_window
);
798 void ActivateBrowserWindow(Browser
* browser
);
800 Browser
* CreateBrowserWithEmptyTab(bool as_popup
);
802 int GetTabId(const base::DictionaryValue
* value
) const;
804 base::Value
* RunFunction(UIThreadExtensionFunction
* function
,
805 const std::string
& params
);
808 // A helper class to wait for an AppWindow to become activated. On
809 // window system like X11, for a NativeWidget to be activated, we
810 // need to wait for the round trip communication with the X server.
811 class AppWindowActivatedWaiter
: public AppWindowRegistry::Observer
{
813 AppWindowActivatedWaiter(AppWindow
* app_window
,
814 content::BrowserContext
* browser_context
)
815 : app_window_(app_window
),
816 browser_context_(browser_context
),
818 AppWindowRegistry::Get(browser_context_
)->AddObserver(this);
820 ~AppWindowActivatedWaiter() override
{
821 AppWindowRegistry::Get(browser_context_
)->RemoveObserver(this);
824 void ActivateAndWait() {
825 app_window_
->GetBaseWindow()->Activate();
826 if (!app_window_
->GetBaseWindow()->IsActive()) {
828 content::RunMessageLoop();
832 // AppWindowRegistry::Observer:
833 void OnAppWindowActivated(AppWindow
* app_window
) override
{
834 if (app_window_
== app_window
&& waiting_
) {
835 base::MessageLoopForUI::current()->Quit();
841 AppWindow
* app_window_
;
842 content::BrowserContext
* browser_context_
;
846 // A helper class to wait for an views::Widget to become activated.
847 class WidgetActivatedWaiter
: public views::WidgetObserver
{
849 explicit WidgetActivatedWaiter(views::Widget
* widget
)
850 : widget_(widget
), waiting_(false) {
851 widget_
->AddObserver(this);
853 ~WidgetActivatedWaiter() override
{ widget_
->RemoveObserver(this); }
855 void ActivateAndWait() {
857 if (!widget_
->IsActive()) {
859 content::RunMessageLoop();
863 // views::WidgetObserver:
864 void OnWidgetActivationChanged(views::Widget
* widget
,
865 bool active
) override
{
866 if (widget_
== widget
&& waiting_
) {
867 base::MessageLoopForUI::current()->Quit();
873 views::Widget
* widget_
;
877 scoped_refptr
<Extension
> extension_
;
880 void ExtensionWindowLastFocusedTest::SetUpOnMainThread() {
881 ExtensionTabsTest::SetUpOnMainThread();
882 extension_
= test_util::CreateEmptyExtension();
885 void ExtensionWindowLastFocusedTest::ActivateAppWindow(AppWindow
* app_window
) {
886 AppWindowActivatedWaiter
waiter(app_window
, browser()->profile());
887 waiter
.ActivateAndWait();
890 void ExtensionWindowLastFocusedTest::ActivateBrowserWindow(Browser
* browser
) {
891 BrowserView
* view
= BrowserView::GetBrowserViewForBrowser(browser
);
892 EXPECT_NE(nullptr, view
);
893 views::Widget
* widget
= view
->frame();
894 EXPECT_NE(nullptr, widget
);
895 WidgetActivatedWaiter
waiter(widget
);
896 waiter
.ActivateAndWait();
899 Browser
* ExtensionWindowLastFocusedTest::CreateBrowserWithEmptyTab(
901 Browser
* new_browser
;
903 new_browser
= new Browser(
904 Browser::CreateParams(Browser::TYPE_POPUP
, browser()->profile(),
905 browser()->host_desktop_type()));
907 new_browser
= new Browser(Browser::CreateParams(
908 browser()->profile(), browser()->host_desktop_type()));
909 AddBlankTabAndShow(new_browser
);
913 int ExtensionWindowLastFocusedTest::GetTabId(
914 const base::DictionaryValue
* value
) const {
915 const base::ListValue
* tabs
= NULL
;
916 if (!value
->GetList(keys::kTabsKey
, &tabs
))
918 const base::Value
* tab
= NULL
;
919 if (!tabs
->Get(0, &tab
))
921 const base::DictionaryValue
* tab_dict
= NULL
;
922 if (!tab
->GetAsDictionary(&tab_dict
))
925 if (!tab_dict
->GetInteger(keys::kIdKey
, &tab_id
))
930 base::Value
* ExtensionWindowLastFocusedTest::RunFunction(
931 UIThreadExtensionFunction
* function
,
932 const std::string
& params
) {
933 function
->set_extension(extension_
.get());
934 return utils::RunFunctionAndReturnSingleResult(function
, params
, browser());
937 IN_PROC_BROWSER_TEST_F(ExtensionWindowLastFocusedTest
,
938 NoDevtoolsAndAppWindows
) {
939 DevToolsWindow
* devtools
= DevToolsWindowTesting::OpenDevToolsWindowSync(
940 browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
942 int devtools_window_id
= ExtensionTabUtil::GetWindowId(
943 DevToolsWindowTesting::Get(devtools
)->browser());
944 ActivateBrowserWindow(DevToolsWindowTesting::Get(devtools
)->browser());
946 scoped_refptr
<WindowsGetLastFocusedFunction
> function
=
947 new WindowsGetLastFocusedFunction();
948 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(
949 RunFunction(function
.get(), "[{\"populate\": true}]")));
950 EXPECT_NE(devtools_window_id
,
951 api_test_utils::GetInteger(result
.get(), "id"));
954 AppWindow
* app_window
= CreateTestAppWindow(
956 "{\"width\": 300, \"height\": 300,"
957 " \"minWidth\": 200, \"minHeight\": 200,"
958 " \"maxWidth\": 400, \"maxHeight\": 400}}");
960 ActivateAppWindow(app_window
);
962 scoped_refptr
<WindowsGetLastFocusedFunction
> get_current_app_function
=
963 new WindowsGetLastFocusedFunction();
964 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(
965 RunFunction(get_current_app_function
.get(), "[{\"populate\": true}]")));
966 int app_window_id
= app_window
->session_id().id();
967 EXPECT_NE(app_window_id
, api_test_utils::GetInteger(result
.get(), "id"));
970 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools
);
971 CloseAppWindow(app_window
);
974 IN_PROC_BROWSER_TEST_F(ExtensionWindowLastFocusedTest
,
975 NoTabIdForDevToolsAndAppWindows
) {
976 Browser
* normal_browser
= CreateBrowserWithEmptyTab(false);
978 ActivateBrowserWindow(normal_browser
);
980 scoped_refptr
<WindowsGetLastFocusedFunction
> function
=
981 new WindowsGetLastFocusedFunction();
982 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(
983 RunFunction(function
.get(), "[{\"populate\": true}]")));
984 int normal_browser_window_id
=
985 ExtensionTabUtil::GetWindowId(normal_browser
);
986 EXPECT_EQ(normal_browser_window_id
,
987 api_test_utils::GetInteger(result
.get(), "id"));
988 EXPECT_NE(-1, GetTabId(result
.get()));
989 EXPECT_EQ("normal", api_test_utils::GetString(result
.get(), "type"));
992 Browser
* popup_browser
= CreateBrowserWithEmptyTab(true);
994 ActivateBrowserWindow(popup_browser
);
996 scoped_refptr
<WindowsGetLastFocusedFunction
> function
=
997 new WindowsGetLastFocusedFunction();
998 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(
999 RunFunction(function
.get(), "[{\"populate\": true}]")));
1000 int popup_browser_window_id
= ExtensionTabUtil::GetWindowId(popup_browser
);
1001 EXPECT_EQ(popup_browser_window_id
,
1002 api_test_utils::GetInteger(result
.get(), "id"));
1003 EXPECT_NE(-1, GetTabId(result
.get()));
1004 EXPECT_EQ("popup", api_test_utils::GetString(result
.get(), "type"));
1007 DevToolsWindow
* devtools
= DevToolsWindowTesting::OpenDevToolsWindowSync(
1008 browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
1010 ActivateBrowserWindow(DevToolsWindowTesting::Get(devtools
)->browser());
1012 scoped_refptr
<WindowsGetLastFocusedFunction
> function
=
1013 new WindowsGetLastFocusedFunction();
1014 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(RunFunction(
1016 "[{\"populate\": true, \"windowTypes\": [ \"devtools\" ]}]")));
1017 int devtools_window_id
= ExtensionTabUtil::GetWindowId(
1018 DevToolsWindowTesting::Get(devtools
)->browser());
1019 EXPECT_EQ(devtools_window_id
,
1020 api_test_utils::GetInteger(result
.get(), "id"));
1021 EXPECT_EQ(-1, GetTabId(result
.get()));
1022 EXPECT_EQ("devtools", api_test_utils::GetString(result
.get(), "type"));
1025 AppWindow
* app_window
= CreateTestAppWindow(
1026 "{\"outerBounds\": "
1027 "{\"width\": 300, \"height\": 300,"
1028 " \"minWidth\": 200, \"minHeight\": 200,"
1029 " \"maxWidth\": 400, \"maxHeight\": 400}}");
1031 ActivateAppWindow(app_window
);
1033 scoped_refptr
<WindowsGetLastFocusedFunction
> get_current_app_function
=
1034 new WindowsGetLastFocusedFunction();
1035 scoped_ptr
<base::DictionaryValue
> result(utils::ToDictionary(
1036 RunFunction(get_current_app_function
.get(),
1037 "[{\"populate\": true, \"windowTypes\": [ \"app\" ]}]")));
1038 int app_window_id
= app_window
->session_id().id();
1039 EXPECT_EQ(app_window_id
, api_test_utils::GetInteger(result
.get(), "id"));
1040 EXPECT_EQ(-1, GetTabId(result
.get()));
1041 EXPECT_EQ("app", api_test_utils::GetString(result
.get(), "type"));
1044 chrome::CloseWindow(normal_browser
);
1045 chrome::CloseWindow(popup_browser
);
1046 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools
);
1047 CloseAppWindow(app_window
);
1049 #endif // !defined(OS_MACOSX)
1051 IN_PROC_BROWSER_TEST_F(ExtensionWindowCreateTest
, AcceptState
) {
1052 scoped_refptr
<WindowsCreateFunction
> function(new WindowsCreateFunction());
1053 scoped_refptr
<Extension
> extension(test_util::CreateEmptyExtension());
1054 function
->set_extension(extension
.get());
1056 scoped_ptr
<base::DictionaryValue
> result(
1057 utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
1058 function
.get(), "[{\"state\": \"minimized\"}]", browser(),
1059 utils::INCLUDE_INCOGNITO
)));
1060 int window_id
= GetWindowId(result
.get());
1062 Browser
* new_window
= ExtensionTabUtil::GetBrowserFromWindowID(
1063 function
.get(), window_id
, &error
);
1064 EXPECT_TRUE(error
.empty());
1065 #if !defined(OS_LINUX) || defined(OS_CHROMEOS)
1066 // DesktopWindowTreeHostX11::IsMinimized() relies on an asynchronous update
1067 // from the window server.
1068 EXPECT_TRUE(new_window
->window()->IsMinimized());
1071 // TODO(limasdf): Flaky on mac. See http://crbug.com/482433.
1072 #if !defined(OS_MACOSX)
1073 function
= new WindowsCreateFunction();
1074 function
->set_extension(extension
.get());
1075 result
.reset(utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
1076 function
.get(), "[{\"state\": \"fullscreen\"}]", browser(),
1077 utils::INCLUDE_INCOGNITO
)));
1078 window_id
= GetWindowId(result
.get());
1079 new_window
= ExtensionTabUtil::GetBrowserFromWindowID(function
.get(),
1081 EXPECT_TRUE(error
.empty());
1082 EXPECT_TRUE(new_window
->window()->IsFullscreen());
1083 #endif // !defined(OS_MACOSX)
1086 IN_PROC_BROWSER_TEST_F(ExtensionWindowCreateTest
, ValidateCreateWindowState
) {
1087 EXPECT_TRUE(base::MatchPattern(
1088 RunCreateWindowExpectError(
1089 "[{\"state\": \"fullscreen\", \"type\": \"panel\"}]"),
1090 keys::kInvalidWindowStateError
));
1091 EXPECT_TRUE(base::MatchPattern(
1092 RunCreateWindowExpectError(
1093 "[{\"state\": \"maximized\", \"type\": \"panel\"}]"),
1094 keys::kInvalidWindowStateError
));
1095 EXPECT_TRUE(base::MatchPattern(
1096 RunCreateWindowExpectError(
1097 "[{\"state\": \"minimized\", \"type\": \"panel\"}]"),
1098 keys::kInvalidWindowStateError
));
1100 base::MatchPattern(RunCreateWindowExpectError(
1101 "[{\"state\": \"minimized\", \"focused\": true}]"),
1102 keys::kInvalidWindowStateError
));
1103 EXPECT_TRUE(base::MatchPattern(
1104 RunCreateWindowExpectError(
1105 "[{\"state\": \"maximized\", \"focused\": false}]"),
1106 keys::kInvalidWindowStateError
));
1107 EXPECT_TRUE(base::MatchPattern(
1108 RunCreateWindowExpectError(
1109 "[{\"state\": \"fullscreen\", \"focused\": false}]"),
1110 keys::kInvalidWindowStateError
));
1112 base::MatchPattern(RunCreateWindowExpectError(
1113 "[{\"state\": \"minimized\", \"width\": 500}]"),
1114 keys::kInvalidWindowStateError
));
1116 base::MatchPattern(RunCreateWindowExpectError(
1117 "[{\"state\": \"maximized\", \"width\": 500}]"),
1118 keys::kInvalidWindowStateError
));
1120 base::MatchPattern(RunCreateWindowExpectError(
1121 "[{\"state\": \"fullscreen\", \"width\": 500}]"),
1122 keys::kInvalidWindowStateError
));
1125 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, DuplicateTab
) {
1126 content::OpenURLParams
params(GURL(url::kAboutBlankURL
),
1127 content::Referrer(),
1129 ui::PAGE_TRANSITION_LINK
,
1131 content::WebContents
* web_contents
= browser()->OpenURL(params
);
1132 int tab_id
= ExtensionTabUtil::GetTabId(web_contents
);
1133 int window_id
= ExtensionTabUtil::GetWindowIdOfTab(web_contents
);
1135 TabStripModel
* tab_strip
;
1136 ExtensionTabUtil::GetTabStripModel(web_contents
, &tab_strip
, &tab_index
);
1138 scoped_refptr
<TabsDuplicateFunction
> duplicate_tab_function(
1139 new TabsDuplicateFunction());
1140 scoped_ptr
<base::DictionaryValue
> test_extension_value(
1141 api_test_utils::ParseDictionary(
1142 "{\"name\": \"Test\", \"version\": \"1.0\", \"permissions\": "
1144 scoped_refptr
<Extension
> empty_tab_extension(
1145 api_test_utils::CreateExtension(test_extension_value
.get()));
1146 duplicate_tab_function
->set_extension(empty_tab_extension
.get());
1147 duplicate_tab_function
->set_has_callback(true);
1149 scoped_ptr
<base::DictionaryValue
> duplicate_result(utils::ToDictionary(
1150 utils::RunFunctionAndReturnSingleResult(
1151 duplicate_tab_function
.get(), base::StringPrintf("[%u]", tab_id
),
1154 int duplicate_tab_id
= GetTabId(duplicate_result
.get());
1155 int duplicate_tab_window_id
= GetTabWindowId(duplicate_result
.get());
1156 int duplicate_tab_index
=
1157 api_test_utils::GetInteger(duplicate_result
.get(), "index");
1158 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, duplicate_result
->GetType());
1159 // Duplicate tab id should be different from the original tab id.
1160 EXPECT_NE(tab_id
, duplicate_tab_id
);
1161 EXPECT_EQ(window_id
, duplicate_tab_window_id
);
1162 EXPECT_EQ(tab_index
+ 1, duplicate_tab_index
);
1163 // The test empty tab extension has tabs permissions, therefore
1164 // |duplicate_result| should contain url, title, and faviconUrl
1165 // in the function result.
1166 EXPECT_TRUE(utils::HasPrivacySensitiveFields(duplicate_result
.get()));
1169 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, DuplicateTabNoPermission
) {
1170 content::OpenURLParams
params(GURL(url::kAboutBlankURL
),
1171 content::Referrer(),
1173 ui::PAGE_TRANSITION_LINK
,
1175 content::WebContents
* web_contents
= browser()->OpenURL(params
);
1176 int tab_id
= ExtensionTabUtil::GetTabId(web_contents
);
1177 int window_id
= ExtensionTabUtil::GetWindowIdOfTab(web_contents
);
1179 TabStripModel
* tab_strip
;
1180 ExtensionTabUtil::GetTabStripModel(web_contents
, &tab_strip
, &tab_index
);
1182 scoped_refptr
<TabsDuplicateFunction
> duplicate_tab_function(
1183 new TabsDuplicateFunction());
1184 scoped_refptr
<Extension
> empty_extension(test_util::CreateEmptyExtension());
1185 duplicate_tab_function
->set_extension(empty_extension
.get());
1186 duplicate_tab_function
->set_has_callback(true);
1188 scoped_ptr
<base::DictionaryValue
> duplicate_result(utils::ToDictionary(
1189 utils::RunFunctionAndReturnSingleResult(
1190 duplicate_tab_function
.get(), base::StringPrintf("[%u]", tab_id
),
1193 int duplicate_tab_id
= GetTabId(duplicate_result
.get());
1194 int duplicate_tab_window_id
= GetTabWindowId(duplicate_result
.get());
1195 int duplicate_tab_index
=
1196 api_test_utils::GetInteger(duplicate_result
.get(), "index");
1197 EXPECT_EQ(base::Value::TYPE_DICTIONARY
, duplicate_result
->GetType());
1198 // Duplicate tab id should be different from the original tab id.
1199 EXPECT_NE(tab_id
, duplicate_tab_id
);
1200 EXPECT_EQ(window_id
, duplicate_tab_window_id
);
1201 EXPECT_EQ(tab_index
+ 1, duplicate_tab_index
);
1202 // The test empty extension has no permissions, therefore |duplicate_result|
1203 // should not contain url, title, and faviconUrl in the function result.
1204 EXPECT_FALSE(utils::HasPrivacySensitiveFields(duplicate_result
.get()));
1207 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, NoTabsEventOnDevTools
) {
1208 extensions::ResultCatcher catcher
;
1209 ExtensionTestMessageListener
listener("ready", true);
1211 LoadExtension(test_data_dir_
.AppendASCII("api_test/tabs/no_events")));
1212 ASSERT_TRUE(listener
.WaitUntilSatisfied());
1214 DevToolsWindow
* devtools
= DevToolsWindowTesting::OpenDevToolsWindowSync(
1215 browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
1217 listener
.Reply("stop");
1219 ASSERT_TRUE(catcher
.GetNextResult());
1221 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools
);
1224 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, NoTabsAppWindow
) {
1225 extensions::ResultCatcher catcher
;
1226 ExtensionTestMessageListener
listener("ready", true);
1228 LoadExtension(test_data_dir_
.AppendASCII("api_test/tabs/no_events")));
1229 ASSERT_TRUE(listener
.WaitUntilSatisfied());
1231 AppWindow
* app_window
= CreateTestAppWindow(
1232 "{\"outerBounds\": "
1233 "{\"width\": 300, \"height\": 300,"
1234 " \"minWidth\": 200, \"minHeight\": 200,"
1235 " \"maxWidth\": 400, \"maxHeight\": 400}}");
1237 listener
.Reply("stop");
1239 ASSERT_TRUE(catcher
.GetNextResult());
1241 CloseAppWindow(app_window
);
1244 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, FilteredEvents
) {
1245 extensions::ResultCatcher catcher
;
1246 ExtensionTestMessageListener
listener("ready", true);
1248 LoadExtension(test_data_dir_
.AppendASCII("api_test/windows/events")));
1249 ASSERT_TRUE(listener
.WaitUntilSatisfied());
1251 AppWindow
* app_window
= CreateTestAppWindow(
1252 "{\"outerBounds\": "
1253 "{\"width\": 300, \"height\": 300,"
1254 " \"minWidth\": 200, \"minHeight\": 200,"
1255 " \"maxWidth\": 400, \"maxHeight\": 400}}");
1257 Browser
* browser_window
= new Browser(Browser::CreateParams(
1258 browser()->profile(), browser()->host_desktop_type()));
1259 AddBlankTabAndShow(browser_window
);
1261 DevToolsWindow
* devtools_window
=
1262 DevToolsWindowTesting::OpenDevToolsWindowSync(
1263 browser()->tab_strip_model()->GetWebContentsAt(0),
1264 false /* is_docked */);
1266 chrome::CloseWindow(browser_window
);
1267 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools_window
);
1268 CloseAppWindow(app_window
);
1270 // TODO(llandwerlin): It seems creating an app window on MacOSX
1271 // won't create an activation event whereas it does on all other
1272 // platform. Disable focus event tests for now.
1273 #if defined(OS_MACOSX)
1276 listener
.Reply("focus");
1279 ASSERT_TRUE(catcher
.GetNextResult());
1282 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest
, ExecuteScriptOnDevTools
) {
1283 scoped_ptr
<base::DictionaryValue
> test_extension_value(
1284 api_test_utils::ParseDictionary(
1285 "{\"name\": \"Test\", \"version\": \"1.0\", \"permissions\": "
1287 scoped_refptr
<Extension
> extension(
1288 api_test_utils::CreateExtension(test_extension_value
.get()));
1290 DevToolsWindow
* devtools
= DevToolsWindowTesting::OpenDevToolsWindowSync(
1291 browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
1293 scoped_refptr
<TabsExecuteScriptFunction
> function
=
1294 new TabsExecuteScriptFunction();
1295 function
->set_extension(extension
.get());
1297 EXPECT_TRUE(base::MatchPattern(
1298 utils::RunFunctionAndReturnError(
1299 function
.get(), base::StringPrintf("[%u, {\"code\": \"true\"}]",
1300 api::windows::WINDOW_ID_CURRENT
),
1301 DevToolsWindowTesting::Get(devtools
)->browser()),
1302 manifest_errors::kCannotAccessPage
));
1304 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools
);
1307 // Tester class for the tabs.zoom* api functions.
1308 class ExtensionTabsZoomTest
: public ExtensionTabsTest
{
1310 void SetUpOnMainThread() override
;
1312 // Runs chrome.tabs.setZoom().
1313 bool RunSetZoom(int tab_id
, double zoom_factor
);
1315 // Runs chrome.tabs.getZoom().
1316 testing::AssertionResult
RunGetZoom(int tab_id
, double* zoom_factor
);
1318 // Runs chrome.tabs.setZoomSettings().
1319 bool RunSetZoomSettings(int tab_id
, const char* mode
, const char* scope
);
1321 // Runs chrome.tabs.getZoomSettings().
1322 testing::AssertionResult
RunGetZoomSettings(int tab_id
,
1324 std::string
* scope
);
1326 // Runs chrome.tabs.getZoomSettings() and returns default zoom.
1327 testing::AssertionResult
RunGetDefaultZoom(int tab_id
,
1328 double* default_zoom_factor
);
1330 // Runs chrome.tabs.setZoom(), expecting an error.
1331 std::string
RunSetZoomExpectError(int tab_id
,
1332 double zoom_factor
);
1334 // Runs chrome.tabs.setZoomSettings(), expecting an error.
1335 std::string
RunSetZoomSettingsExpectError(int tab_id
,
1339 content::WebContents
* OpenUrlAndWaitForLoad(const GURL
& url
);
1342 scoped_refptr
<Extension
> extension_
;
1345 void ExtensionTabsZoomTest::SetUpOnMainThread() {
1346 ExtensionTabsTest::SetUpOnMainThread();
1347 extension_
= test_util::CreateEmptyExtension();
1350 bool ExtensionTabsZoomTest::RunSetZoom(int tab_id
, double zoom_factor
) {
1351 scoped_refptr
<TabsSetZoomFunction
> set_zoom_function(
1352 new TabsSetZoomFunction());
1353 set_zoom_function
->set_extension(extension_
.get());
1354 set_zoom_function
->set_has_callback(true);
1356 return utils::RunFunction(
1357 set_zoom_function
.get(),
1358 base::StringPrintf("[%u, %lf]", tab_id
, zoom_factor
), browser(),
1359 extension_function_test_utils::NONE
);
1362 testing::AssertionResult
ExtensionTabsZoomTest::RunGetZoom(
1364 double* zoom_factor
) {
1365 scoped_refptr
<TabsGetZoomFunction
> get_zoom_function(
1366 new TabsGetZoomFunction());
1367 get_zoom_function
->set_extension(extension_
.get());
1368 get_zoom_function
->set_has_callback(true);
1370 scoped_ptr
<base::Value
> get_zoom_result(
1371 utils::RunFunctionAndReturnSingleResult(
1372 get_zoom_function
.get(),
1373 base::StringPrintf("[%u]", tab_id
),
1376 if (!get_zoom_result
)
1377 return testing::AssertionFailure() << "no result";
1378 if (!get_zoom_result
->GetAsDouble(zoom_factor
))
1379 return testing::AssertionFailure() << "result was not a double";
1381 return testing::AssertionSuccess();
1384 bool ExtensionTabsZoomTest::RunSetZoomSettings(int tab_id
,
1386 const char* scope
) {
1387 scoped_refptr
<TabsSetZoomSettingsFunction
> set_zoom_settings_function(
1388 new TabsSetZoomSettingsFunction());
1389 set_zoom_settings_function
->set_extension(extension_
.get());
1393 args
= base::StringPrintf("[%u, {\"mode\": \"%s\", \"scope\": \"%s\"}]",
1394 tab_id
, mode
, scope
);
1396 args
= base::StringPrintf("[%u, {\"mode\": \"%s\"}]", tab_id
, mode
);
1399 return utils::RunFunction(set_zoom_settings_function
.get(),
1402 extension_function_test_utils::NONE
);
1405 testing::AssertionResult
ExtensionTabsZoomTest::RunGetZoomSettings(
1408 std::string
* scope
) {
1411 scoped_refptr
<TabsGetZoomSettingsFunction
> get_zoom_settings_function(
1412 new TabsGetZoomSettingsFunction());
1413 get_zoom_settings_function
->set_extension(extension_
.get());
1414 get_zoom_settings_function
->set_has_callback(true);
1416 scoped_ptr
<base::DictionaryValue
> get_zoom_settings_result(
1417 utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
1418 get_zoom_settings_function
.get(),
1419 base::StringPrintf("[%u]", tab_id
),
1422 if (!get_zoom_settings_result
)
1423 return testing::AssertionFailure() << "no result";
1425 *mode
= api_test_utils::GetString(get_zoom_settings_result
.get(), "mode");
1426 *scope
= api_test_utils::GetString(get_zoom_settings_result
.get(), "scope");
1428 return testing::AssertionSuccess();
1431 testing::AssertionResult
ExtensionTabsZoomTest::RunGetDefaultZoom(
1433 double* default_zoom_factor
) {
1434 DCHECK(default_zoom_factor
);
1435 scoped_refptr
<TabsGetZoomSettingsFunction
> get_zoom_settings_function(
1436 new TabsGetZoomSettingsFunction());
1437 get_zoom_settings_function
->set_extension(extension_
.get());
1438 get_zoom_settings_function
->set_has_callback(true);
1440 scoped_ptr
<base::DictionaryValue
> get_zoom_settings_result(
1441 utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
1442 get_zoom_settings_function
.get(),
1443 base::StringPrintf("[%u]", tab_id
),
1446 if (!get_zoom_settings_result
)
1447 return testing::AssertionFailure() << "no result";
1449 if (!get_zoom_settings_result
->GetDouble("defaultZoomFactor",
1450 default_zoom_factor
)) {
1451 return testing::AssertionFailure()
1452 << "default zoom factor not found in result";
1455 return testing::AssertionSuccess();
1458 std::string
ExtensionTabsZoomTest::RunSetZoomExpectError(int tab_id
,
1459 double zoom_factor
) {
1460 scoped_refptr
<TabsSetZoomFunction
> set_zoom_function(
1461 new TabsSetZoomFunction());
1462 set_zoom_function
->set_extension(extension_
.get());
1463 set_zoom_function
->set_has_callback(true);
1465 return utils::RunFunctionAndReturnError(
1466 set_zoom_function
.get(),
1467 base::StringPrintf("[%u, %lf]", tab_id
, zoom_factor
),
1471 std::string
ExtensionTabsZoomTest::RunSetZoomSettingsExpectError(
1474 const char* scope
) {
1475 scoped_refptr
<TabsSetZoomSettingsFunction
> set_zoom_settings_function(
1476 new TabsSetZoomSettingsFunction());
1477 set_zoom_settings_function
->set_extension(extension_
.get());
1479 return utils::RunFunctionAndReturnError(set_zoom_settings_function
.get(),
1481 "[%u, {\"mode\": \"%s\", "
1482 "\"scope\": \"%s\"}]",
1489 content::WebContents
* ExtensionTabsZoomTest::OpenUrlAndWaitForLoad(
1491 ui_test_utils::NavigateToURLWithDisposition(
1495 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION
);
1496 return browser()->tab_strip_model()->GetActiveWebContents();
1501 double GetZoomLevel(const content::WebContents
* web_contents
) {
1502 return ui_zoom::ZoomController::FromWebContents(web_contents
)->GetZoomLevel();
1505 content::OpenURLParams
GetOpenParams(const char* url
) {
1506 return content::OpenURLParams(GURL(url
),
1507 content::Referrer(),
1509 ui::PAGE_TRANSITION_LINK
,
1515 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest
, SetAndGetZoom
) {
1516 content::OpenURLParams
params(GetOpenParams(url::kAboutBlankURL
));
1517 content::WebContents
* web_contents
= OpenUrlAndWaitForLoad(params
.url
);
1518 int tab_id
= ExtensionTabUtil::GetTabId(web_contents
);
1520 // Test default values before we set anything.
1521 double zoom_factor
= -1;
1522 EXPECT_TRUE(RunGetZoom(tab_id
, &zoom_factor
));
1523 EXPECT_EQ(1.0, zoom_factor
);
1525 // Test chrome.tabs.setZoom().
1526 const double kZoomLevel
= 0.8;
1527 EXPECT_TRUE(RunSetZoom(tab_id
, kZoomLevel
));
1528 EXPECT_EQ(kZoomLevel
,
1529 content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents
)));
1531 // Test chrome.tabs.getZoom().
1533 EXPECT_TRUE(RunGetZoom(tab_id
, &zoom_factor
));
1534 EXPECT_EQ(kZoomLevel
, zoom_factor
);
1537 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest
, GetDefaultZoom
) {
1538 content::OpenURLParams
params(GetOpenParams(url::kAboutBlankURL
));
1539 content::WebContents
* web_contents
= OpenUrlAndWaitForLoad(params
.url
);
1540 int tab_id
= ExtensionTabUtil::GetTabId(web_contents
);
1542 ui_zoom::ZoomController
* zoom_controller
=
1543 ui_zoom::ZoomController::FromWebContents(web_contents
);
1544 double default_zoom_factor
= -1.0;
1545 EXPECT_TRUE(RunGetDefaultZoom(tab_id
, &default_zoom_factor
));
1546 EXPECT_TRUE(content::ZoomValuesEqual(
1547 zoom_controller
->GetDefaultZoomLevel(),
1548 content::ZoomFactorToZoomLevel(default_zoom_factor
)));
1550 // Change the default zoom level and verify GetDefaultZoom returns the
1552 content::StoragePartition
* partition
=
1553 content::BrowserContext::GetStoragePartition(
1554 web_contents
->GetBrowserContext(), web_contents
->GetSiteInstance());
1555 ChromeZoomLevelPrefs
* zoom_prefs
=
1556 static_cast<ChromeZoomLevelPrefs
*>(partition
->GetZoomLevelDelegate());
1558 double default_zoom_level
= zoom_controller
->GetDefaultZoomLevel();
1559 zoom_prefs
->SetDefaultZoomLevelPref(default_zoom_level
+ 0.5);
1560 default_zoom_factor
= -1.0;
1561 EXPECT_TRUE(RunGetDefaultZoom(tab_id
, &default_zoom_factor
));
1562 EXPECT_TRUE(content::ZoomValuesEqual(
1563 default_zoom_level
+ 0.5,
1564 content::ZoomFactorToZoomLevel(default_zoom_factor
)));
1567 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest
, SetToDefaultZoom
) {
1568 content::OpenURLParams
params(GetOpenParams(url::kAboutBlankURL
));
1569 content::WebContents
* web_contents
= OpenUrlAndWaitForLoad(params
.url
);
1570 int tab_id
= ExtensionTabUtil::GetTabId(web_contents
);
1572 ui_zoom::ZoomController
* zoom_controller
=
1573 ui_zoom::ZoomController::FromWebContents(web_contents
);
1574 double default_zoom_level
= zoom_controller
->GetDefaultZoomLevel();
1575 double new_default_zoom_level
= default_zoom_level
+ 0.42;
1577 content::StoragePartition
* partition
=
1578 content::BrowserContext::GetStoragePartition(
1579 web_contents
->GetBrowserContext(), web_contents
->GetSiteInstance());
1580 ChromeZoomLevelPrefs
* zoom_prefs
=
1581 static_cast<ChromeZoomLevelPrefs
*>(partition
->GetZoomLevelDelegate());
1583 zoom_prefs
->SetDefaultZoomLevelPref(new_default_zoom_level
);
1585 double observed_zoom_factor
= -1.0;
1586 EXPECT_TRUE(RunSetZoom(tab_id
, 0.0));
1587 EXPECT_TRUE(RunGetZoom(tab_id
, &observed_zoom_factor
));
1588 EXPECT_TRUE(content::ZoomValuesEqual(
1589 new_default_zoom_level
,
1590 content::ZoomFactorToZoomLevel(observed_zoom_factor
)));
1593 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest
, ZoomSettings
) {
1594 // In this test we need two URLs that (1) represent real pages (i.e. they
1595 // load without causing an error page load), (2) have different domains, and
1596 // (3) are zoomable by the extension API (this last condition rules out
1597 // chrome:// urls). We achieve this by noting that about:blank meets these
1598 // requirements, allowing us to spin up a spawned http server on localhost to
1599 // get the other domain.
1600 net::SpawnedTestServer
http_server(
1601 net::SpawnedTestServer::TYPE_HTTP
,
1602 net::SpawnedTestServer::kLocalhost
,
1603 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1604 ASSERT_TRUE(http_server
.Start());
1606 GURL url_A
= http_server
.GetURL("files/simple.html");
1607 GURL
url_B("about:blank");
1609 // Tabs A1 and A2 are navigated to the same origin, while B is navigated
1610 // to a different one.
1611 content::WebContents
* web_contents_A1
= OpenUrlAndWaitForLoad(url_A
);
1612 content::WebContents
* web_contents_A2
= OpenUrlAndWaitForLoad(url_A
);
1613 content::WebContents
* web_contents_B
= OpenUrlAndWaitForLoad(url_B
);
1615 int tab_id_A1
= ExtensionTabUtil::GetTabId(web_contents_A1
);
1616 int tab_id_A2
= ExtensionTabUtil::GetTabId(web_contents_A2
);
1617 int tab_id_B
= ExtensionTabUtil::GetTabId(web_contents_B
);
1620 1.f
, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1
)));
1622 1.f
, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A2
)));
1624 1.f
, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_B
)));
1626 // Test per-origin automatic zoom settings.
1627 EXPECT_TRUE(RunSetZoom(tab_id_B
, 1.f
));
1628 EXPECT_TRUE(RunSetZoom(tab_id_A2
, 1.1f
));
1630 1.1f
, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1
)));
1632 1.1f
, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A2
)));
1633 EXPECT_FLOAT_EQ(1.f
,
1634 content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_B
)));
1636 // Test per-tab automatic zoom settings.
1637 EXPECT_TRUE(RunSetZoomSettings(tab_id_A1
, "automatic", "per-tab"));
1638 EXPECT_TRUE(RunSetZoom(tab_id_A1
, 1.2f
));
1640 1.2f
, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1
)));
1642 1.1f
, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A2
)));
1644 // Test 'manual' mode.
1645 EXPECT_TRUE(RunSetZoomSettings(tab_id_A1
, "manual", nullptr));
1646 EXPECT_TRUE(RunSetZoom(tab_id_A1
, 1.3f
));
1648 1.3f
, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1
)));
1650 1.1f
, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A2
)));
1652 // Test 'disabled' mode, which will reset A1's zoom to 1.f.
1653 EXPECT_TRUE(RunSetZoomSettings(tab_id_A1
, "disabled", nullptr));
1654 std::string error
= RunSetZoomExpectError(tab_id_A1
, 1.4f
);
1655 EXPECT_TRUE(base::MatchPattern(error
, keys::kCannotZoomDisabledTabError
));
1657 1.f
, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1
)));
1658 // We should still be able to zoom A2 though.
1659 EXPECT_TRUE(RunSetZoom(tab_id_A2
, 1.4f
));
1661 1.4f
, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A2
)));
1664 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest
, PerTabResetsOnNavigation
) {
1665 net::SpawnedTestServer
http_server(
1666 net::SpawnedTestServer::TYPE_HTTP
,
1667 net::SpawnedTestServer::kLocalhost
,
1668 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1669 ASSERT_TRUE(http_server
.Start());
1671 GURL url_A
= http_server
.GetURL("files/simple.html");
1672 GURL
url_B("about:blank");
1674 content::WebContents
* web_contents
= OpenUrlAndWaitForLoad(url_A
);
1675 int tab_id
= ExtensionTabUtil::GetTabId(web_contents
);
1676 EXPECT_TRUE(RunSetZoomSettings(tab_id
, "automatic", "per-tab"));
1680 EXPECT_TRUE(RunGetZoomSettings(tab_id
, &mode
, &scope
));
1681 EXPECT_EQ("automatic", mode
);
1682 EXPECT_EQ("per-tab", scope
);
1684 // Navigation of tab should reset mode to per-origin.
1685 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url_B
,
1687 EXPECT_TRUE(RunGetZoomSettings(tab_id
, &mode
, &scope
));
1688 EXPECT_EQ("automatic", mode
);
1689 EXPECT_EQ("per-origin", scope
);
1692 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest
, GetZoomSettings
) {
1693 content::OpenURLParams
params(GetOpenParams(url::kAboutBlankURL
));
1694 content::WebContents
* web_contents
= OpenUrlAndWaitForLoad(params
.url
);
1695 int tab_id
= ExtensionTabUtil::GetTabId(web_contents
);
1700 EXPECT_TRUE(RunGetZoomSettings(tab_id
, &mode
, &scope
));
1701 EXPECT_EQ("automatic", mode
);
1702 EXPECT_EQ("per-origin", scope
);
1704 EXPECT_TRUE(RunSetZoomSettings(tab_id
, "automatic", "per-tab"));
1705 EXPECT_TRUE(RunGetZoomSettings(tab_id
, &mode
, &scope
));
1707 EXPECT_EQ("automatic", mode
);
1708 EXPECT_EQ("per-tab", scope
);
1711 RunSetZoomSettingsExpectError(tab_id
, "manual", "per-origin");
1712 EXPECT_TRUE(base::MatchPattern(error
, keys::kPerOriginOnlyInAutomaticError
));
1714 RunSetZoomSettingsExpectError(tab_id
, "disabled", "per-origin");
1715 EXPECT_TRUE(base::MatchPattern(error
, keys::kPerOriginOnlyInAutomaticError
));
1718 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest
, CannotZoomInvalidTab
) {
1719 content::OpenURLParams
params(GetOpenParams(url::kAboutBlankURL
));
1720 content::WebContents
* web_contents
= OpenUrlAndWaitForLoad(params
.url
);
1721 int tab_id
= ExtensionTabUtil::GetTabId(web_contents
);
1723 int bogus_id
= tab_id
+ 100;
1724 std::string error
= RunSetZoomExpectError(bogus_id
, 3.14159);
1725 EXPECT_TRUE(base::MatchPattern(error
, keys::kTabNotFoundError
));
1727 error
= RunSetZoomSettingsExpectError(bogus_id
, "manual", "per-tab");
1728 EXPECT_TRUE(base::MatchPattern(error
, keys::kTabNotFoundError
));
1730 const char kNewTestTabArgs
[] = "chrome://version";
1731 params
= GetOpenParams(kNewTestTabArgs
);
1732 web_contents
= browser()->OpenURL(params
);
1733 tab_id
= ExtensionTabUtil::GetTabId(web_contents
);
1735 // Test chrome.tabs.setZoom().
1736 error
= RunSetZoomExpectError(tab_id
, 3.14159);
1738 base::MatchPattern(error
, manifest_errors::kCannotAccessChromeUrl
));
1740 // chrome.tabs.setZoomSettings().
1741 error
= RunSetZoomSettingsExpectError(tab_id
, "manual", "per-tab");
1743 base::MatchPattern(error
, manifest_errors::kCannotAccessChromeUrl
));
1746 } // namespace extensions