Move MatchPattern to its own header and the base namespace.
[chromium-blink-merge.git] / chrome / browser / extensions / api / tabs / tabs_test.cc
blob48dde2eefeda0ea401541ed93cfe78828146ce3a
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.
6 #include <string>
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/devtools/devtools_window_testing.h"
17 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
18 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
19 #include "chrome/browser/extensions/extension_function_test_utils.h"
20 #include "chrome/browser/extensions/extension_tab_util.h"
21 #include "chrome/browser/prefs/incognito_mode_prefs.h"
22 #include "chrome/browser/profiles/profile.h"
23 #include "chrome/browser/ui/browser.h"
24 #include "chrome/browser/ui/browser_commands.h"
25 #include "chrome/browser/ui/browser_window.h"
26 #include "chrome/browser/ui/tabs/tab_strip_model.h"
27 #include "chrome/browser/ui/zoom/chrome_zoom_level_prefs.h"
28 #include "chrome/test/base/in_process_browser_test.h"
29 #include "chrome/test/base/ui_test_utils.h"
30 #include "content/public/browser/browser_context.h"
31 #include "content/public/browser/storage_partition.h"
32 #include "content/public/common/page_zoom.h"
33 #include "content/public/common/url_constants.h"
34 #include "extensions/browser/api_test_utils.h"
35 #include "extensions/common/manifest_constants.h"
36 #include "extensions/common/test_util.h"
37 #include "net/test/spawned_test_server/spawned_test_server.h"
38 #include "ui/gfx/geometry/rect.h"
40 namespace extensions {
42 namespace keys = tabs_constants;
43 namespace utils = extension_function_test_utils;
45 namespace {
46 using ExtensionTabsTest = InProcessBrowserTest;
48 class ExtensionWindowCreateTest : public InProcessBrowserTest {
49 public:
50 // Runs chrome.windows.create(), expecting an error.
51 std::string RunCreateWindowExpectError(const std::string& args) {
52 scoped_refptr<WindowsCreateFunction> function(new WindowsCreateFunction);
53 function->set_extension(test_util::CreateEmptyExtension().get());
54 return api_test_utils::RunFunctionAndReturnError(function.get(), args,
55 browser()->profile());
59 } // namespace
61 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, GetWindow) {
62 int window_id = ExtensionTabUtil::GetWindowId(browser());
64 // Invalid window ID error.
65 scoped_refptr<WindowsGetFunction> function = new WindowsGetFunction();
66 scoped_refptr<Extension> extension(test_util::CreateEmptyExtension());
67 function->set_extension(extension.get());
68 EXPECT_TRUE(base::MatchPattern(
69 utils::RunFunctionAndReturnError(
70 function.get(), base::StringPrintf("[%u]", window_id + 1), browser()),
71 keys::kWindowNotFoundError));
73 // Basic window details.
74 gfx::Rect bounds;
75 if (browser()->window()->IsMinimized())
76 bounds = browser()->window()->GetRestoredBounds();
77 else
78 bounds = browser()->window()->GetBounds();
80 function = new WindowsGetFunction();
81 function->set_extension(extension.get());
82 scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
83 utils::RunFunctionAndReturnSingleResult(
84 function.get(),
85 base::StringPrintf("[%u]", window_id),
86 browser())));
87 EXPECT_EQ(window_id, api_test_utils::GetInteger(result.get(), "id"));
88 EXPECT_FALSE(api_test_utils::GetBoolean(result.get(), "incognito"));
89 EXPECT_EQ("normal", api_test_utils::GetString(result.get(), "type"));
90 EXPECT_EQ(bounds.x(), api_test_utils::GetInteger(result.get(), "left"));
91 EXPECT_EQ(bounds.y(), api_test_utils::GetInteger(result.get(), "top"));
92 EXPECT_EQ(bounds.width(), api_test_utils::GetInteger(result.get(), "width"));
93 EXPECT_EQ(bounds.height(),
94 api_test_utils::GetInteger(result.get(), "height"));
96 // With "populate" enabled.
97 function = new WindowsGetFunction();
98 function->set_extension(extension.get());
99 result.reset(utils::ToDictionary(
100 utils::RunFunctionAndReturnSingleResult(
101 function.get(),
102 base::StringPrintf("[%u, {\"populate\": true}]", window_id),
103 browser())));
105 EXPECT_EQ(window_id, api_test_utils::GetInteger(result.get(), "id"));
106 // "populate" was enabled so tabs should be populated.
107 base::ListValue* tabs = NULL;
108 EXPECT_TRUE(result.get()->GetList(keys::kTabsKey, &tabs));
110 // TODO(aa): Can't assume window is focused. On mac, calling Activate() from a
111 // browser test doesn't seem to do anything, so can't test the opposite
112 // either.
113 EXPECT_EQ(browser()->window()->IsActive(),
114 api_test_utils::GetBoolean(result.get(), "focused"));
116 // TODO(aa): Minimized and maximized dimensions. Is there a way to set
117 // minimize/maximize programmatically?
119 // Popup.
120 Browser* popup_browser = new Browser(
121 Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(),
122 browser()->host_desktop_type()));
123 function = new WindowsGetFunction();
124 function->set_extension(extension.get());
125 result.reset(utils::ToDictionary(
126 utils::RunFunctionAndReturnSingleResult(
127 function.get(),
128 base::StringPrintf(
129 "[%u]", ExtensionTabUtil::GetWindowId(popup_browser)),
130 browser())));
131 EXPECT_EQ("popup", api_test_utils::GetString(result.get(), "type"));
133 // Incognito.
134 Browser* incognito_browser = CreateIncognitoBrowser();
135 int incognito_window_id = ExtensionTabUtil::GetWindowId(incognito_browser);
137 // Without "include_incognito".
138 function = new WindowsGetFunction();
139 function->set_extension(extension.get());
140 EXPECT_TRUE(base::MatchPattern(
141 utils::RunFunctionAndReturnError(
142 function.get(), base::StringPrintf("[%u]", incognito_window_id),
143 browser()),
144 keys::kWindowNotFoundError));
146 // With "include_incognito".
147 function = new WindowsGetFunction();
148 function->set_extension(extension.get());
149 result.reset(utils::ToDictionary(
150 utils::RunFunctionAndReturnSingleResult(
151 function.get(),
152 base::StringPrintf("[%u]", incognito_window_id),
153 browser(),
154 utils::INCLUDE_INCOGNITO)));
155 EXPECT_TRUE(api_test_utils::GetBoolean(result.get(), "incognito"));
158 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, GetCurrentWindow) {
159 int window_id = ExtensionTabUtil::GetWindowId(browser());
160 Browser* new_browser = CreateBrowser(browser()->profile());
161 int new_id = ExtensionTabUtil::GetWindowId(new_browser);
163 // Get the current window using new_browser.
164 scoped_refptr<WindowsGetCurrentFunction> function =
165 new WindowsGetCurrentFunction();
166 scoped_refptr<Extension> extension(test_util::CreateEmptyExtension());
167 function->set_extension(extension.get());
168 scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
169 utils::RunFunctionAndReturnSingleResult(function.get(),
170 "[]",
171 new_browser)));
173 // The id should match the window id of the browser instance that was passed
174 // to RunFunctionAndReturnSingleResult.
175 EXPECT_EQ(new_id, api_test_utils::GetInteger(result.get(), "id"));
176 base::ListValue* tabs = NULL;
177 EXPECT_FALSE(result.get()->GetList(keys::kTabsKey, &tabs));
179 // Get the current window using the old window and make the tabs populated.
180 function = new WindowsGetCurrentFunction();
181 function->set_extension(extension.get());
182 result.reset(utils::ToDictionary(
183 utils::RunFunctionAndReturnSingleResult(function.get(),
184 "[{\"populate\": true}]",
185 browser())));
187 // The id should match the window id of the browser instance that was passed
188 // to RunFunctionAndReturnSingleResult.
189 EXPECT_EQ(window_id, api_test_utils::GetInteger(result.get(), "id"));
190 // "populate" was enabled so tabs should be populated.
191 EXPECT_TRUE(result.get()->GetList(keys::kTabsKey, &tabs));
194 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, GetAllWindows) {
195 const size_t NUM_WINDOWS = 5;
196 std::set<int> window_ids;
197 std::set<int> result_ids;
198 window_ids.insert(ExtensionTabUtil::GetWindowId(browser()));
200 for (size_t i = 0; i < NUM_WINDOWS - 1; ++i) {
201 Browser* new_browser = CreateBrowser(browser()->profile());
202 window_ids.insert(ExtensionTabUtil::GetWindowId(new_browser));
205 // Undocked DevTools window should not be accessible.
206 DevToolsWindow* devtools = DevToolsWindowTesting::OpenDevToolsWindowSync(
207 browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
209 scoped_refptr<WindowsGetAllFunction> function = new WindowsGetAllFunction();
210 scoped_refptr<Extension> extension(test_util::CreateEmptyExtension());
211 function->set_extension(extension.get());
212 scoped_ptr<base::ListValue> result(utils::ToList(
213 utils::RunFunctionAndReturnSingleResult(function.get(),
214 "[]",
215 browser())));
217 base::ListValue* windows = result.get();
218 EXPECT_EQ(NUM_WINDOWS, windows->GetSize());
219 for (size_t i = 0; i < NUM_WINDOWS; ++i) {
220 base::DictionaryValue* result_window = NULL;
221 EXPECT_TRUE(windows->GetDictionary(i, &result_window));
222 result_ids.insert(api_test_utils::GetInteger(result_window, "id"));
224 // "populate" was not passed in so tabs are not populated.
225 base::ListValue* tabs = NULL;
226 EXPECT_FALSE(result_window->GetList(keys::kTabsKey, &tabs));
228 // The returned ids should contain all the current browser instance ids.
229 EXPECT_EQ(window_ids, result_ids);
231 result_ids.clear();
232 function = new WindowsGetAllFunction();
233 function->set_extension(extension.get());
234 result.reset(utils::ToList(
235 utils::RunFunctionAndReturnSingleResult(function.get(),
236 "[{\"populate\": true}]",
237 browser())));
239 windows = result.get();
240 EXPECT_EQ(NUM_WINDOWS, windows->GetSize());
241 for (size_t i = 0; i < windows->GetSize(); ++i) {
242 base::DictionaryValue* result_window = NULL;
243 EXPECT_TRUE(windows->GetDictionary(i, &result_window));
244 result_ids.insert(api_test_utils::GetInteger(result_window, "id"));
246 // "populate" was enabled so tabs should be populated.
247 base::ListValue* tabs = NULL;
248 EXPECT_TRUE(result_window->GetList(keys::kTabsKey, &tabs));
250 // The returned ids should contain all the current browser instance ids.
251 EXPECT_EQ(window_ids, result_ids);
253 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools);
256 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, UpdateNoPermissions) {
257 // The test empty extension has no permissions, therefore it should not get
258 // tab data in the function result.
259 scoped_refptr<TabsUpdateFunction> update_tab_function(
260 new TabsUpdateFunction());
261 scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
262 update_tab_function->set_extension(empty_extension.get());
263 // Without a callback the function will not generate a result.
264 update_tab_function->set_has_callback(true);
266 scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
267 utils::RunFunctionAndReturnSingleResult(
268 update_tab_function.get(),
269 "[null, {\"url\": \"about:blank\", \"pinned\": true}]",
270 browser())));
271 // The url is stripped since the extension does not have tab permissions.
272 EXPECT_FALSE(result->HasKey("url"));
273 EXPECT_TRUE(api_test_utils::GetBoolean(result.get(), "pinned"));
276 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,
277 DefaultToIncognitoWhenItIsForced) {
278 static const char kArgsWithoutExplicitIncognitoParam[] =
279 "[{\"url\": \"about:blank\"}]";
280 // Force Incognito mode.
281 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
282 IncognitoModePrefs::FORCED);
283 // Run without an explicit "incognito" param.
284 scoped_refptr<WindowsCreateFunction> function(new WindowsCreateFunction());
285 scoped_refptr<Extension> extension(test_util::CreateEmptyExtension());
286 function->set_extension(extension.get());
287 scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
288 utils::RunFunctionAndReturnSingleResult(
289 function.get(),
290 kArgsWithoutExplicitIncognitoParam,
291 browser(),
292 utils::INCLUDE_INCOGNITO)));
294 // Make sure it is a new(different) window.
295 EXPECT_NE(ExtensionTabUtil::GetWindowId(browser()),
296 api_test_utils::GetInteger(result.get(), "id"));
297 // ... and it is incognito.
298 EXPECT_TRUE(api_test_utils::GetBoolean(result.get(), "incognito"));
300 // Now try creating a window from incognito window.
301 Browser* incognito_browser = CreateIncognitoBrowser();
302 // Run without an explicit "incognito" param.
303 function = new WindowsCreateFunction();
304 function->set_extension(extension.get());
305 result.reset(utils::ToDictionary(
306 utils::RunFunctionAndReturnSingleResult(
307 function.get(),
308 kArgsWithoutExplicitIncognitoParam,
309 incognito_browser,
310 utils::INCLUDE_INCOGNITO)));
311 // Make sure it is a new(different) window.
312 EXPECT_NE(ExtensionTabUtil::GetWindowId(incognito_browser),
313 api_test_utils::GetInteger(result.get(), "id"));
314 // ... and it is incognito.
315 EXPECT_TRUE(api_test_utils::GetBoolean(result.get(), "incognito"));
318 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,
319 DefaultToIncognitoWhenItIsForcedAndNoArgs) {
320 static const char kEmptyArgs[] = "[]";
321 // Force Incognito mode.
322 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
323 IncognitoModePrefs::FORCED);
324 // Run without an explicit "incognito" param.
325 scoped_refptr<WindowsCreateFunction> function = new WindowsCreateFunction();
326 scoped_refptr<Extension> extension(test_util::CreateEmptyExtension());
327 function->set_extension(extension.get());
328 scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
329 utils::RunFunctionAndReturnSingleResult(function.get(),
330 kEmptyArgs,
331 browser(),
332 utils::INCLUDE_INCOGNITO)));
334 // Make sure it is a new(different) window.
335 EXPECT_NE(ExtensionTabUtil::GetWindowId(browser()),
336 api_test_utils::GetInteger(result.get(), "id"));
337 // ... and it is incognito.
338 EXPECT_TRUE(api_test_utils::GetBoolean(result.get(), "incognito"));
340 // Now try creating a window from incognito window.
341 Browser* incognito_browser = CreateIncognitoBrowser();
342 // Run without an explicit "incognito" param.
343 function = new WindowsCreateFunction();
344 function->set_extension(extension.get());
345 result.reset(utils::ToDictionary(
346 utils::RunFunctionAndReturnSingleResult(function.get(),
347 kEmptyArgs,
348 incognito_browser,
349 utils::INCLUDE_INCOGNITO)));
350 // Make sure it is a new(different) window.
351 EXPECT_NE(ExtensionTabUtil::GetWindowId(incognito_browser),
352 api_test_utils::GetInteger(result.get(), "id"));
353 // ... and it is incognito.
354 EXPECT_TRUE(api_test_utils::GetBoolean(result.get(), "incognito"));
357 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,
358 DontCreateNormalWindowWhenIncognitoForced) {
359 static const char kArgsWithExplicitIncognitoParam[] =
360 "[{\"url\": \"about:blank\", \"incognito\": false }]";
361 // Force Incognito mode.
362 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
363 IncognitoModePrefs::FORCED);
365 // Run with an explicit "incognito" param.
366 scoped_refptr<WindowsCreateFunction> function = new WindowsCreateFunction();
367 scoped_refptr<Extension> extension(test_util::CreateEmptyExtension());
368 function->set_extension(extension.get());
369 EXPECT_TRUE(base::MatchPattern(
370 utils::RunFunctionAndReturnError(
371 function.get(), kArgsWithExplicitIncognitoParam, browser()),
372 keys::kIncognitoModeIsForced));
374 // Now try opening a normal window from incognito window.
375 Browser* incognito_browser = CreateIncognitoBrowser();
376 // Run with an explicit "incognito" param.
377 function = new WindowsCreateFunction();
378 function->set_extension(extension.get());
379 EXPECT_TRUE(base::MatchPattern(
380 utils::RunFunctionAndReturnError(
381 function.get(), kArgsWithExplicitIncognitoParam, incognito_browser),
382 keys::kIncognitoModeIsForced));
385 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,
386 DontCreateIncognitoWindowWhenIncognitoDisabled) {
387 static const char kArgs[] =
388 "[{\"url\": \"about:blank\", \"incognito\": true }]";
390 Browser* incognito_browser = CreateIncognitoBrowser();
391 // Disable Incognito mode.
392 IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
393 IncognitoModePrefs::DISABLED);
394 // Run in normal window.
395 scoped_refptr<WindowsCreateFunction> function = new WindowsCreateFunction();
396 scoped_refptr<Extension> extension(test_util::CreateEmptyExtension());
397 function->set_extension(extension.get());
398 EXPECT_TRUE(base::MatchPattern(
399 utils::RunFunctionAndReturnError(function.get(), kArgs, browser()),
400 keys::kIncognitoModeIsDisabled));
402 // Run in incognito window.
403 function = new WindowsCreateFunction();
404 function->set_extension(extension.get());
405 EXPECT_TRUE(base::MatchPattern(utils::RunFunctionAndReturnError(
406 function.get(), kArgs, incognito_browser),
407 keys::kIncognitoModeIsDisabled));
410 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, QueryCurrentWindowTabs) {
411 const size_t kExtraWindows = 3;
412 for (size_t i = 0; i < kExtraWindows; ++i)
413 CreateBrowser(browser()->profile());
415 GURL url(url::kAboutBlankURL);
416 AddTabAtIndex(0, url, ui::PAGE_TRANSITION_LINK);
417 int window_id = ExtensionTabUtil::GetWindowId(browser());
419 // Get tabs in the 'current' window called from non-focused browser.
420 scoped_refptr<TabsQueryFunction> function = new TabsQueryFunction();
421 function->set_extension(test_util::CreateEmptyExtension().get());
422 scoped_ptr<base::ListValue> result(utils::ToList(
423 utils::RunFunctionAndReturnSingleResult(function.get(),
424 "[{\"currentWindow\":true}]",
425 browser())));
427 base::ListValue* result_tabs = result.get();
428 // We should have one initial tab and one added tab.
429 EXPECT_EQ(2u, result_tabs->GetSize());
430 for (size_t i = 0; i < result_tabs->GetSize(); ++i) {
431 base::DictionaryValue* result_tab = NULL;
432 EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
433 EXPECT_EQ(window_id,
434 api_test_utils::GetInteger(result_tab, keys::kWindowIdKey));
437 // Get tabs NOT in the 'current' window called from non-focused browser.
438 function = new TabsQueryFunction();
439 function->set_extension(test_util::CreateEmptyExtension().get());
440 result.reset(utils::ToList(
441 utils::RunFunctionAndReturnSingleResult(function.get(),
442 "[{\"currentWindow\":false}]",
443 browser())));
445 result_tabs = result.get();
446 // We should have one tab for each extra window.
447 EXPECT_EQ(kExtraWindows, result_tabs->GetSize());
448 for (size_t i = 0; i < kExtraWindows; ++i) {
449 base::DictionaryValue* result_tab = NULL;
450 EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
451 EXPECT_NE(window_id,
452 api_test_utils::GetInteger(result_tab, keys::kWindowIdKey));
456 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, QueryAllTabsWithDevTools) {
457 const size_t kNumWindows = 3;
458 std::set<int> window_ids;
459 window_ids.insert(ExtensionTabUtil::GetWindowId(browser()));
460 for (size_t i = 0; i < kNumWindows - 1; ++i) {
461 Browser* new_browser = CreateBrowser(browser()->profile());
462 window_ids.insert(ExtensionTabUtil::GetWindowId(new_browser));
465 // Undocked DevTools window should not be accessible.
466 DevToolsWindow* devtools = DevToolsWindowTesting::OpenDevToolsWindowSync(
467 browser()->tab_strip_model()->GetWebContentsAt(0), false /* is_docked */);
469 // Get tabs in the 'current' window called from non-focused browser.
470 scoped_refptr<TabsQueryFunction> function = new TabsQueryFunction();
471 function->set_extension(test_util::CreateEmptyExtension().get());
472 scoped_ptr<base::ListValue> result(utils::ToList(
473 utils::RunFunctionAndReturnSingleResult(function.get(),
474 "[{}]",
475 browser())));
477 std::set<int> result_ids;
478 base::ListValue* result_tabs = result.get();
479 // We should have one tab per browser except for DevTools.
480 EXPECT_EQ(kNumWindows, result_tabs->GetSize());
481 for (size_t i = 0; i < result_tabs->GetSize(); ++i) {
482 base::DictionaryValue* result_tab = NULL;
483 EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
484 result_ids.insert(
485 api_test_utils::GetInteger(result_tab, keys::kWindowIdKey));
487 EXPECT_EQ(window_ids, result_ids);
489 DevToolsWindowTesting::CloseDevToolsWindowSync(devtools);
492 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DontCreateTabInClosingPopupWindow) {
493 // Test creates new popup window, closes it right away and then tries to open
494 // a new tab in it. Tab should not be opened in the popup window, but in a
495 // tabbed browser window.
496 Browser* popup_browser = new Browser(
497 Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(),
498 browser()->host_desktop_type()));
499 int window_id = ExtensionTabUtil::GetWindowId(popup_browser);
500 chrome::CloseWindow(popup_browser);
502 scoped_refptr<TabsCreateFunction> create_tab_function(
503 new TabsCreateFunction());
504 create_tab_function->set_extension(test_util::CreateEmptyExtension().get());
505 // Without a callback the function will not generate a result.
506 create_tab_function->set_has_callback(true);
508 static const char kNewBlankTabArgs[] =
509 "[{\"url\": \"about:blank\", \"windowId\": %u}]";
511 scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
512 utils::RunFunctionAndReturnSingleResult(
513 create_tab_function.get(),
514 base::StringPrintf(kNewBlankTabArgs, window_id),
515 browser())));
517 EXPECT_NE(window_id, api_test_utils::GetInteger(result.get(), "windowId"));
520 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, InvalidUpdateWindowState) {
521 int window_id = ExtensionTabUtil::GetWindowId(browser());
523 static const char kArgsMinimizedWithFocus[] =
524 "[%u, {\"state\": \"minimized\", \"focused\": true}]";
525 scoped_refptr<WindowsUpdateFunction> function = new WindowsUpdateFunction();
526 scoped_refptr<Extension> extension(test_util::CreateEmptyExtension());
527 function->set_extension(extension.get());
528 EXPECT_TRUE(base::MatchPattern(
529 utils::RunFunctionAndReturnError(
530 function.get(),
531 base::StringPrintf(kArgsMinimizedWithFocus, window_id), browser()),
532 keys::kInvalidWindowStateError));
534 static const char kArgsMaximizedWithoutFocus[] =
535 "[%u, {\"state\": \"maximized\", \"focused\": false}]";
536 function = new WindowsUpdateFunction();
537 function->set_extension(extension.get());
538 EXPECT_TRUE(base::MatchPattern(
539 utils::RunFunctionAndReturnError(
540 function.get(),
541 base::StringPrintf(kArgsMaximizedWithoutFocus, window_id), browser()),
542 keys::kInvalidWindowStateError));
544 static const char kArgsMinimizedWithBounds[] =
545 "[%u, {\"state\": \"minimized\", \"width\": 500}]";
546 function = new WindowsUpdateFunction();
547 function->set_extension(extension.get());
548 EXPECT_TRUE(base::MatchPattern(
549 utils::RunFunctionAndReturnError(
550 function.get(),
551 base::StringPrintf(kArgsMinimizedWithBounds, window_id), browser()),
552 keys::kInvalidWindowStateError));
554 static const char kArgsMaximizedWithBounds[] =
555 "[%u, {\"state\": \"maximized\", \"width\": 500}]";
556 function = new WindowsUpdateFunction();
557 function->set_extension(extension.get());
558 EXPECT_TRUE(base::MatchPattern(
559 utils::RunFunctionAndReturnError(
560 function.get(),
561 base::StringPrintf(kArgsMaximizedWithBounds, window_id), browser()),
562 keys::kInvalidWindowStateError));
565 IN_PROC_BROWSER_TEST_F(ExtensionWindowCreateTest, AcceptState) {
566 scoped_refptr<WindowsCreateFunction> function(new WindowsCreateFunction());
567 scoped_refptr<Extension> extension(test_util::CreateEmptyExtension());
568 function->set_extension(extension.get());
570 scoped_ptr<base::DictionaryValue> result(
571 utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
572 function.get(), "[{\"state\": \"minimized\"}]", browser(),
573 utils::INCLUDE_INCOGNITO)));
574 int window_id = api_test_utils::GetInteger(result.get(), "id");
575 std::string error;
576 Browser* new_window = ExtensionTabUtil::GetBrowserFromWindowID(
577 function.get(), window_id, &error);
578 EXPECT_TRUE(error.empty());
579 #if !defined(OS_LINUX) || defined(OS_CHROMEOS)
580 // DesktopWindowTreeHostX11::IsMinimized() relies on an asynchronous update
581 // from the window server.
582 EXPECT_TRUE(new_window->window()->IsMinimized());
583 #endif
585 // TODO(limasdf): Flaky on mac. See http://crbug.com/482433.
586 #if !defined(OS_MACOSX)
587 function = new WindowsCreateFunction();
588 function->set_extension(extension.get());
589 result.reset(utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
590 function.get(), "[{\"state\": \"fullscreen\"}]", browser(),
591 utils::INCLUDE_INCOGNITO)));
592 window_id = api_test_utils::GetInteger(result.get(), "id");
593 new_window = ExtensionTabUtil::GetBrowserFromWindowID(function.get(),
594 window_id, &error);
595 EXPECT_TRUE(error.empty());
596 EXPECT_TRUE(new_window->window()->IsFullscreen());
597 #endif // !defined(OS_MACOSX)
600 IN_PROC_BROWSER_TEST_F(ExtensionWindowCreateTest, ValidateCreateWindowState) {
601 EXPECT_TRUE(base::MatchPattern(
602 RunCreateWindowExpectError(
603 "[{\"state\": \"fullscreen\", \"type\": \"panel\"}]"),
604 keys::kInvalidWindowStateError));
605 EXPECT_TRUE(base::MatchPattern(
606 RunCreateWindowExpectError(
607 "[{\"state\": \"maximized\", \"type\": \"panel\"}]"),
608 keys::kInvalidWindowStateError));
609 EXPECT_TRUE(base::MatchPattern(
610 RunCreateWindowExpectError(
611 "[{\"state\": \"minimized\", \"type\": \"panel\"}]"),
612 keys::kInvalidWindowStateError));
613 EXPECT_TRUE(
614 base::MatchPattern(RunCreateWindowExpectError(
615 "[{\"state\": \"minimized\", \"focused\": true}]"),
616 keys::kInvalidWindowStateError));
617 EXPECT_TRUE(base::MatchPattern(
618 RunCreateWindowExpectError(
619 "[{\"state\": \"maximized\", \"focused\": false}]"),
620 keys::kInvalidWindowStateError));
621 EXPECT_TRUE(base::MatchPattern(
622 RunCreateWindowExpectError(
623 "[{\"state\": \"fullscreen\", \"focused\": false}]"),
624 keys::kInvalidWindowStateError));
625 EXPECT_TRUE(
626 base::MatchPattern(RunCreateWindowExpectError(
627 "[{\"state\": \"minimized\", \"width\": 500}]"),
628 keys::kInvalidWindowStateError));
629 EXPECT_TRUE(
630 base::MatchPattern(RunCreateWindowExpectError(
631 "[{\"state\": \"maximized\", \"width\": 500}]"),
632 keys::kInvalidWindowStateError));
633 EXPECT_TRUE(
634 base::MatchPattern(RunCreateWindowExpectError(
635 "[{\"state\": \"fullscreen\", \"width\": 500}]"),
636 keys::kInvalidWindowStateError));
639 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DuplicateTab) {
640 content::OpenURLParams params(GURL(url::kAboutBlankURL),
641 content::Referrer(),
642 NEW_FOREGROUND_TAB,
643 ui::PAGE_TRANSITION_LINK,
644 false);
645 content::WebContents* web_contents = browser()->OpenURL(params);
646 int tab_id = ExtensionTabUtil::GetTabId(web_contents);
647 int window_id = ExtensionTabUtil::GetWindowIdOfTab(web_contents);
648 int tab_index = -1;
649 TabStripModel* tab_strip;
650 ExtensionTabUtil::GetTabStripModel(web_contents, &tab_strip, &tab_index);
652 scoped_refptr<TabsDuplicateFunction> duplicate_tab_function(
653 new TabsDuplicateFunction());
654 scoped_ptr<base::DictionaryValue> test_extension_value(
655 api_test_utils::ParseDictionary(
656 "{\"name\": \"Test\", \"version\": \"1.0\", \"permissions\": "
657 "[\"tabs\"]}"));
658 scoped_refptr<Extension> empty_tab_extension(
659 api_test_utils::CreateExtension(test_extension_value.get()));
660 duplicate_tab_function->set_extension(empty_tab_extension.get());
661 duplicate_tab_function->set_has_callback(true);
663 scoped_ptr<base::DictionaryValue> duplicate_result(utils::ToDictionary(
664 utils::RunFunctionAndReturnSingleResult(
665 duplicate_tab_function.get(), base::StringPrintf("[%u]", tab_id),
666 browser())));
668 int duplicate_tab_id =
669 api_test_utils::GetInteger(duplicate_result.get(), "id");
670 int duplicate_tab_window_id =
671 api_test_utils::GetInteger(duplicate_result.get(), "windowId");
672 int duplicate_tab_index =
673 api_test_utils::GetInteger(duplicate_result.get(), "index");
674 EXPECT_EQ(base::Value::TYPE_DICTIONARY, duplicate_result->GetType());
675 // Duplicate tab id should be different from the original tab id.
676 EXPECT_NE(tab_id, duplicate_tab_id);
677 EXPECT_EQ(window_id, duplicate_tab_window_id);
678 EXPECT_EQ(tab_index + 1, duplicate_tab_index);
679 // The test empty tab extension has tabs permissions, therefore
680 // |duplicate_result| should contain url, title, and faviconUrl
681 // in the function result.
682 EXPECT_TRUE(utils::HasPrivacySensitiveFields(duplicate_result.get()));
685 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DuplicateTabNoPermission) {
686 content::OpenURLParams params(GURL(url::kAboutBlankURL),
687 content::Referrer(),
688 NEW_FOREGROUND_TAB,
689 ui::PAGE_TRANSITION_LINK,
690 false);
691 content::WebContents* web_contents = browser()->OpenURL(params);
692 int tab_id = ExtensionTabUtil::GetTabId(web_contents);
693 int window_id = ExtensionTabUtil::GetWindowIdOfTab(web_contents);
694 int tab_index = -1;
695 TabStripModel* tab_strip;
696 ExtensionTabUtil::GetTabStripModel(web_contents, &tab_strip, &tab_index);
698 scoped_refptr<TabsDuplicateFunction> duplicate_tab_function(
699 new TabsDuplicateFunction());
700 scoped_refptr<Extension> empty_extension(test_util::CreateEmptyExtension());
701 duplicate_tab_function->set_extension(empty_extension.get());
702 duplicate_tab_function->set_has_callback(true);
704 scoped_ptr<base::DictionaryValue> duplicate_result(utils::ToDictionary(
705 utils::RunFunctionAndReturnSingleResult(
706 duplicate_tab_function.get(), base::StringPrintf("[%u]", tab_id),
707 browser())));
709 int duplicate_tab_id =
710 api_test_utils::GetInteger(duplicate_result.get(), "id");
711 int duplicate_tab_window_id =
712 api_test_utils::GetInteger(duplicate_result.get(), "windowId");
713 int duplicate_tab_index =
714 api_test_utils::GetInteger(duplicate_result.get(), "index");
715 EXPECT_EQ(base::Value::TYPE_DICTIONARY, duplicate_result->GetType());
716 // Duplicate tab id should be different from the original tab id.
717 EXPECT_NE(tab_id, duplicate_tab_id);
718 EXPECT_EQ(window_id, duplicate_tab_window_id);
719 EXPECT_EQ(tab_index + 1, duplicate_tab_index);
720 // The test empty extension has no permissions, therefore |duplicate_result|
721 // should not contain url, title, and faviconUrl in the function result.
722 EXPECT_FALSE(utils::HasPrivacySensitiveFields(duplicate_result.get()));
725 // Tester class for the tabs.zoom* api functions.
726 class ExtensionTabsZoomTest : public ExtensionTabsTest {
727 public:
728 void SetUpOnMainThread() override;
730 // Runs chrome.tabs.setZoom().
731 bool RunSetZoom(int tab_id, double zoom_factor);
733 // Runs chrome.tabs.getZoom().
734 testing::AssertionResult RunGetZoom(int tab_id, double* zoom_factor);
736 // Runs chrome.tabs.setZoomSettings().
737 bool RunSetZoomSettings(int tab_id, const char* mode, const char* scope);
739 // Runs chrome.tabs.getZoomSettings().
740 testing::AssertionResult RunGetZoomSettings(int tab_id,
741 std::string* mode,
742 std::string* scope);
744 // Runs chrome.tabs.getZoomSettings() and returns default zoom.
745 testing::AssertionResult RunGetDefaultZoom(int tab_id,
746 double* default_zoom_factor);
748 // Runs chrome.tabs.setZoom(), expecting an error.
749 std::string RunSetZoomExpectError(int tab_id,
750 double zoom_factor);
752 // Runs chrome.tabs.setZoomSettings(), expecting an error.
753 std::string RunSetZoomSettingsExpectError(int tab_id,
754 const char* mode,
755 const char* scope);
757 content::WebContents* OpenUrlAndWaitForLoad(const GURL& url);
759 private:
760 scoped_refptr<Extension> extension_;
763 void ExtensionTabsZoomTest::SetUpOnMainThread() {
764 ExtensionTabsTest::SetUpOnMainThread();
765 extension_ = test_util::CreateEmptyExtension();
768 bool ExtensionTabsZoomTest::RunSetZoom(int tab_id, double zoom_factor) {
769 scoped_refptr<TabsSetZoomFunction> set_zoom_function(
770 new TabsSetZoomFunction());
771 set_zoom_function->set_extension(extension_.get());
772 set_zoom_function->set_has_callback(true);
774 return utils::RunFunction(
775 set_zoom_function.get(),
776 base::StringPrintf("[%u, %lf]", tab_id, zoom_factor), browser(),
777 extension_function_test_utils::NONE);
780 testing::AssertionResult ExtensionTabsZoomTest::RunGetZoom(
781 int tab_id,
782 double* zoom_factor) {
783 scoped_refptr<TabsGetZoomFunction> get_zoom_function(
784 new TabsGetZoomFunction());
785 get_zoom_function->set_extension(extension_.get());
786 get_zoom_function->set_has_callback(true);
788 scoped_ptr<base::Value> get_zoom_result(
789 utils::RunFunctionAndReturnSingleResult(
790 get_zoom_function.get(),
791 base::StringPrintf("[%u]", tab_id),
792 browser()));
794 if (!get_zoom_result)
795 return testing::AssertionFailure() << "no result";
796 if (!get_zoom_result->GetAsDouble(zoom_factor))
797 return testing::AssertionFailure() << "result was not a double";
799 return testing::AssertionSuccess();
802 bool ExtensionTabsZoomTest::RunSetZoomSettings(int tab_id,
803 const char* mode,
804 const char* scope) {
805 scoped_refptr<TabsSetZoomSettingsFunction> set_zoom_settings_function(
806 new TabsSetZoomSettingsFunction());
807 set_zoom_settings_function->set_extension(extension_.get());
809 std::string args;
810 if (scope) {
811 args = base::StringPrintf("[%u, {\"mode\": \"%s\", \"scope\": \"%s\"}]",
812 tab_id, mode, scope);
813 } else {
814 args = base::StringPrintf("[%u, {\"mode\": \"%s\"}]", tab_id, mode);
817 return utils::RunFunction(set_zoom_settings_function.get(),
818 args,
819 browser(),
820 extension_function_test_utils::NONE);
823 testing::AssertionResult ExtensionTabsZoomTest::RunGetZoomSettings(
824 int tab_id,
825 std::string* mode,
826 std::string* scope) {
827 DCHECK(mode);
828 DCHECK(scope);
829 scoped_refptr<TabsGetZoomSettingsFunction> get_zoom_settings_function(
830 new TabsGetZoomSettingsFunction());
831 get_zoom_settings_function->set_extension(extension_.get());
832 get_zoom_settings_function->set_has_callback(true);
834 scoped_ptr<base::DictionaryValue> get_zoom_settings_result(
835 utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
836 get_zoom_settings_function.get(),
837 base::StringPrintf("[%u]", tab_id),
838 browser())));
840 if (!get_zoom_settings_result)
841 return testing::AssertionFailure() << "no result";
843 *mode = api_test_utils::GetString(get_zoom_settings_result.get(), "mode");
844 *scope = api_test_utils::GetString(get_zoom_settings_result.get(), "scope");
846 return testing::AssertionSuccess();
849 testing::AssertionResult ExtensionTabsZoomTest::RunGetDefaultZoom(
850 int tab_id,
851 double* default_zoom_factor) {
852 DCHECK(default_zoom_factor);
853 scoped_refptr<TabsGetZoomSettingsFunction> get_zoom_settings_function(
854 new TabsGetZoomSettingsFunction());
855 get_zoom_settings_function->set_extension(extension_.get());
856 get_zoom_settings_function->set_has_callback(true);
858 scoped_ptr<base::DictionaryValue> get_zoom_settings_result(
859 utils::ToDictionary(utils::RunFunctionAndReturnSingleResult(
860 get_zoom_settings_function.get(),
861 base::StringPrintf("[%u]", tab_id),
862 browser())));
864 if (!get_zoom_settings_result)
865 return testing::AssertionFailure() << "no result";
867 if (!get_zoom_settings_result->GetDouble("defaultZoomFactor",
868 default_zoom_factor)) {
869 return testing::AssertionFailure()
870 << "default zoom factor not found in result";
873 return testing::AssertionSuccess();
876 std::string ExtensionTabsZoomTest::RunSetZoomExpectError(int tab_id,
877 double zoom_factor) {
878 scoped_refptr<TabsSetZoomFunction> set_zoom_function(
879 new TabsSetZoomFunction());
880 set_zoom_function->set_extension(extension_.get());
881 set_zoom_function->set_has_callback(true);
883 return utils::RunFunctionAndReturnError(
884 set_zoom_function.get(),
885 base::StringPrintf("[%u, %lf]", tab_id, zoom_factor),
886 browser());
889 std::string ExtensionTabsZoomTest::RunSetZoomSettingsExpectError(
890 int tab_id,
891 const char* mode,
892 const char* scope) {
893 scoped_refptr<TabsSetZoomSettingsFunction> set_zoom_settings_function(
894 new TabsSetZoomSettingsFunction());
895 set_zoom_settings_function->set_extension(extension_.get());
897 return utils::RunFunctionAndReturnError(set_zoom_settings_function.get(),
898 base::StringPrintf(
899 "[%u, {\"mode\": \"%s\", "
900 "\"scope\": \"%s\"}]",
901 tab_id,
902 mode,
903 scope),
904 browser());
907 content::WebContents* ExtensionTabsZoomTest::OpenUrlAndWaitForLoad(
908 const GURL& url) {
909 ui_test_utils::NavigateToURLWithDisposition(
910 browser(),
911 url,
912 NEW_FOREGROUND_TAB,
913 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
914 return browser()->tab_strip_model()->GetActiveWebContents();
917 namespace {
919 double GetZoomLevel(const content::WebContents* web_contents) {
920 return ui_zoom::ZoomController::FromWebContents(web_contents)->GetZoomLevel();
923 content::OpenURLParams GetOpenParams(const char* url) {
924 return content::OpenURLParams(GURL(url),
925 content::Referrer(),
926 NEW_FOREGROUND_TAB,
927 ui::PAGE_TRANSITION_LINK,
928 false);
931 } // namespace
933 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest, SetAndGetZoom) {
934 content::OpenURLParams params(GetOpenParams(url::kAboutBlankURL));
935 content::WebContents* web_contents = OpenUrlAndWaitForLoad(params.url);
936 int tab_id = ExtensionTabUtil::GetTabId(web_contents);
938 // Test default values before we set anything.
939 double zoom_factor = -1;
940 EXPECT_TRUE(RunGetZoom(tab_id, &zoom_factor));
941 EXPECT_EQ(1.0, zoom_factor);
943 // Test chrome.tabs.setZoom().
944 const double kZoomLevel = 0.8;
945 EXPECT_TRUE(RunSetZoom(tab_id, kZoomLevel));
946 EXPECT_EQ(kZoomLevel,
947 content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents)));
949 // Test chrome.tabs.getZoom().
950 zoom_factor = -1;
951 EXPECT_TRUE(RunGetZoom(tab_id, &zoom_factor));
952 EXPECT_EQ(kZoomLevel, zoom_factor);
955 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest, GetDefaultZoom) {
956 content::OpenURLParams params(GetOpenParams(url::kAboutBlankURL));
957 content::WebContents* web_contents = OpenUrlAndWaitForLoad(params.url);
958 int tab_id = ExtensionTabUtil::GetTabId(web_contents);
960 ui_zoom::ZoomController* zoom_controller =
961 ui_zoom::ZoomController::FromWebContents(web_contents);
962 double default_zoom_factor = -1.0;
963 EXPECT_TRUE(RunGetDefaultZoom(tab_id, &default_zoom_factor));
964 EXPECT_TRUE(content::ZoomValuesEqual(
965 zoom_controller->GetDefaultZoomLevel(),
966 content::ZoomFactorToZoomLevel(default_zoom_factor)));
968 // Change the default zoom level and verify GetDefaultZoom returns the
969 // correct value.
970 content::StoragePartition* partition =
971 content::BrowserContext::GetStoragePartition(
972 web_contents->GetBrowserContext(), web_contents->GetSiteInstance());
973 chrome::ChromeZoomLevelPrefs* zoom_prefs =
974 static_cast<chrome::ChromeZoomLevelPrefs*>(
975 partition->GetZoomLevelDelegate());
977 double default_zoom_level = zoom_controller->GetDefaultZoomLevel();
978 zoom_prefs->SetDefaultZoomLevelPref(default_zoom_level + 0.5);
979 default_zoom_factor = -1.0;
980 EXPECT_TRUE(RunGetDefaultZoom(tab_id, &default_zoom_factor));
981 EXPECT_TRUE(content::ZoomValuesEqual(
982 default_zoom_level + 0.5,
983 content::ZoomFactorToZoomLevel(default_zoom_factor)));
986 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest, SetToDefaultZoom) {
987 content::OpenURLParams params(GetOpenParams(url::kAboutBlankURL));
988 content::WebContents* web_contents = OpenUrlAndWaitForLoad(params.url);
989 int tab_id = ExtensionTabUtil::GetTabId(web_contents);
991 ui_zoom::ZoomController* zoom_controller =
992 ui_zoom::ZoomController::FromWebContents(web_contents);
993 double default_zoom_level = zoom_controller->GetDefaultZoomLevel();
994 double new_default_zoom_level = default_zoom_level + 0.42;
996 content::StoragePartition* partition =
997 content::BrowserContext::GetStoragePartition(
998 web_contents->GetBrowserContext(), web_contents->GetSiteInstance());
999 chrome::ChromeZoomLevelPrefs* zoom_prefs =
1000 static_cast<chrome::ChromeZoomLevelPrefs*>(
1001 partition->GetZoomLevelDelegate());
1003 zoom_prefs->SetDefaultZoomLevelPref(new_default_zoom_level);
1005 double observed_zoom_factor = -1.0;
1006 EXPECT_TRUE(RunSetZoom(tab_id, 0.0));
1007 EXPECT_TRUE(RunGetZoom(tab_id, &observed_zoom_factor));
1008 EXPECT_TRUE(content::ZoomValuesEqual(
1009 new_default_zoom_level,
1010 content::ZoomFactorToZoomLevel(observed_zoom_factor)));
1013 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest, ZoomSettings) {
1014 // In this test we need two URLs that (1) represent real pages (i.e. they
1015 // load without causing an error page load), (2) have different domains, and
1016 // (3) are zoomable by the extension API (this last condition rules out
1017 // chrome:// urls). We achieve this by noting that about:blank meets these
1018 // requirements, allowing us to spin up a spawned http server on localhost to
1019 // get the other domain.
1020 net::SpawnedTestServer http_server(
1021 net::SpawnedTestServer::TYPE_HTTP,
1022 net::SpawnedTestServer::kLocalhost,
1023 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1024 ASSERT_TRUE(http_server.Start());
1026 GURL url_A = http_server.GetURL("files/simple.html");
1027 GURL url_B("about:blank");
1029 // Tabs A1 and A2 are navigated to the same origin, while B is navigated
1030 // to a different one.
1031 content::WebContents* web_contents_A1 = OpenUrlAndWaitForLoad(url_A);
1032 content::WebContents* web_contents_A2 = OpenUrlAndWaitForLoad(url_A);
1033 content::WebContents* web_contents_B = OpenUrlAndWaitForLoad(url_B);
1035 int tab_id_A1 = ExtensionTabUtil::GetTabId(web_contents_A1);
1036 int tab_id_A2 = ExtensionTabUtil::GetTabId(web_contents_A2);
1037 int tab_id_B = ExtensionTabUtil::GetTabId(web_contents_B);
1039 ASSERT_FLOAT_EQ(
1040 1.f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1)));
1041 ASSERT_FLOAT_EQ(
1042 1.f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A2)));
1043 ASSERT_FLOAT_EQ(
1044 1.f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_B)));
1046 // Test per-origin automatic zoom settings.
1047 EXPECT_TRUE(RunSetZoom(tab_id_B, 1.f));
1048 EXPECT_TRUE(RunSetZoom(tab_id_A2, 1.1f));
1049 EXPECT_FLOAT_EQ(
1050 1.1f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1)));
1051 EXPECT_FLOAT_EQ(
1052 1.1f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A2)));
1053 EXPECT_FLOAT_EQ(1.f,
1054 content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_B)));
1056 // Test per-tab automatic zoom settings.
1057 EXPECT_TRUE(RunSetZoomSettings(tab_id_A1, "automatic", "per-tab"));
1058 EXPECT_TRUE(RunSetZoom(tab_id_A1, 1.2f));
1059 EXPECT_FLOAT_EQ(
1060 1.2f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1)));
1061 EXPECT_FLOAT_EQ(
1062 1.1f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A2)));
1064 // Test 'manual' mode.
1065 EXPECT_TRUE(RunSetZoomSettings(tab_id_A1, "manual", NULL));
1066 EXPECT_TRUE(RunSetZoom(tab_id_A1, 1.3f));
1067 EXPECT_FLOAT_EQ(
1068 1.3f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1)));
1069 EXPECT_FLOAT_EQ(
1070 1.1f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A2)));
1072 // Test 'disabled' mode, which will reset A1's zoom to 1.f.
1073 EXPECT_TRUE(RunSetZoomSettings(tab_id_A1, "disabled", NULL));
1074 std::string error = RunSetZoomExpectError(tab_id_A1, 1.4f);
1075 EXPECT_TRUE(base::MatchPattern(error, keys::kCannotZoomDisabledTabError));
1076 EXPECT_FLOAT_EQ(
1077 1.f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1)));
1078 // We should still be able to zoom A2 though.
1079 EXPECT_TRUE(RunSetZoom(tab_id_A2, 1.4f));
1080 EXPECT_FLOAT_EQ(
1081 1.4f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A2)));
1084 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest, PerTabResetsOnNavigation) {
1085 net::SpawnedTestServer http_server(
1086 net::SpawnedTestServer::TYPE_HTTP,
1087 net::SpawnedTestServer::kLocalhost,
1088 base::FilePath(FILE_PATH_LITERAL("chrome/test/data")));
1089 ASSERT_TRUE(http_server.Start());
1091 GURL url_A = http_server.GetURL("files/simple.html");
1092 GURL url_B("about:blank");
1094 content::WebContents* web_contents = OpenUrlAndWaitForLoad(url_A);
1095 int tab_id = ExtensionTabUtil::GetTabId(web_contents);
1096 EXPECT_TRUE(RunSetZoomSettings(tab_id, "automatic", "per-tab"));
1098 std::string mode;
1099 std::string scope;
1100 EXPECT_TRUE(RunGetZoomSettings(tab_id, &mode, &scope));
1101 EXPECT_EQ("automatic", mode);
1102 EXPECT_EQ("per-tab", scope);
1104 // Navigation of tab should reset mode to per-origin.
1105 ui_test_utils::NavigateToURLBlockUntilNavigationsComplete(browser(), url_B,
1107 EXPECT_TRUE(RunGetZoomSettings(tab_id, &mode, &scope));
1108 EXPECT_EQ("automatic", mode);
1109 EXPECT_EQ("per-origin", scope);
1112 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest, GetZoomSettings) {
1113 content::OpenURLParams params(GetOpenParams(url::kAboutBlankURL));
1114 content::WebContents* web_contents = OpenUrlAndWaitForLoad(params.url);
1115 int tab_id = ExtensionTabUtil::GetTabId(web_contents);
1117 std::string mode;
1118 std::string scope;
1120 EXPECT_TRUE(RunGetZoomSettings(tab_id, &mode, &scope));
1121 EXPECT_EQ("automatic", mode);
1122 EXPECT_EQ("per-origin", scope);
1124 EXPECT_TRUE(RunSetZoomSettings(tab_id, "automatic", "per-tab"));
1125 EXPECT_TRUE(RunGetZoomSettings(tab_id, &mode, &scope));
1127 EXPECT_EQ("automatic", mode);
1128 EXPECT_EQ("per-tab", scope);
1130 std::string error =
1131 RunSetZoomSettingsExpectError(tab_id, "manual", "per-origin");
1132 EXPECT_TRUE(base::MatchPattern(error, keys::kPerOriginOnlyInAutomaticError));
1133 error =
1134 RunSetZoomSettingsExpectError(tab_id, "disabled", "per-origin");
1135 EXPECT_TRUE(base::MatchPattern(error, keys::kPerOriginOnlyInAutomaticError));
1138 IN_PROC_BROWSER_TEST_F(ExtensionTabsZoomTest, CannotZoomInvalidTab) {
1139 content::OpenURLParams params(GetOpenParams(url::kAboutBlankURL));
1140 content::WebContents* web_contents = OpenUrlAndWaitForLoad(params.url);
1141 int tab_id = ExtensionTabUtil::GetTabId(web_contents);
1143 int bogus_id = tab_id + 100;
1144 std::string error = RunSetZoomExpectError(bogus_id, 3.14159);
1145 EXPECT_TRUE(base::MatchPattern(error, keys::kTabNotFoundError));
1147 error = RunSetZoomSettingsExpectError(bogus_id, "manual", "per-tab");
1148 EXPECT_TRUE(base::MatchPattern(error, keys::kTabNotFoundError));
1150 const char kNewTestTabArgs[] = "chrome://version";
1151 params = GetOpenParams(kNewTestTabArgs);
1152 web_contents = browser()->OpenURL(params);
1153 tab_id = ExtensionTabUtil::GetTabId(web_contents);
1155 // Test chrome.tabs.setZoom().
1156 error = RunSetZoomExpectError(tab_id, 3.14159);
1157 EXPECT_TRUE(
1158 base::MatchPattern(error, manifest_errors::kCannotAccessChromeUrl));
1160 // chrome.tabs.setZoomSettings().
1161 error = RunSetZoomSettingsExpectError(tab_id, "manual", "per-tab");
1162 EXPECT_TRUE(
1163 base::MatchPattern(error, manifest_errors::kCannotAccessChromeUrl));
1166 } // namespace extensions