Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / extensions / api / tabs / tabs_test.cc
blob43cd585052945e121495535e2cad9a138c12ec1b
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/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;
55 namespace {
56 using ExtensionTabsTest = PlatformAppBrowserTest;
58 class ExtensionWindowCreateTest : public InProcessBrowserTest {
59 public:
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;
73 if (tab)
74 tab->GetInteger(keys::kIdKey, &id);
75 return id;
78 int GetTabWindowId(base::DictionaryValue* tab) {
79 int id = kUndefinedId;
80 if (tab)
81 tab->GetInteger(keys::kWindowIdKey, &id);
82 return id;
85 int GetWindowId(base::DictionaryValue* window) {
86 int id = kUndefinedId;
87 if (window)
88 window->GetInteger(keys::kIdKey, &id);
89 return id;
92 } // namespace
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.
107 gfx::Rect bounds;
108 if (browser()->window()->IsMinimized())
109 bounds = browser()->window()->GetRestoredBounds();
110 else
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(
117 function.get(),
118 base::StringPrintf("[%u]", window_id),
119 browser())));
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(
134 function.get(),
135 base::StringPrintf("[%u, {\"populate\": true}]", window_id),
136 browser())));
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
149 // either.
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?
156 // Popup.
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(
164 function.get(),
165 base::StringPrintf(
166 "[%u]", ExtensionTabUtil::GetWindowId(popup_browser)),
167 browser())));
168 EXPECT_EQ("popup", api_test_utils::GetString(result.get(), "type"));
170 // Incognito.
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),
180 browser()),
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(
188 function.get(),
189 base::StringPrintf("[%u]", incognito_window_id),
190 browser(),
191 utils::INCLUDE_INCOGNITO)));
192 EXPECT_TRUE(api_test_utils::GetBoolean(result.get(), "incognito"));
194 // DevTools window.
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(
201 function.get(),
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(),
223 "[]",
224 new_browser)));
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}]",
238 browser())));
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
264 // to true.
265 AppWindow* app_window = CreateTestAppWindow("{}");
267 // Undocked DevTools window should not be accessible, unless allWindowTypes is
268 // set to true.
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(),
277 "[]",
278 browser())));
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);
294 result_ids.clear();
295 function = new WindowsGetAllFunction();
296 function->set_extension(extension.get());
297 result.reset(utils::ToList(
298 utils::RunFunctionAndReturnSingleResult(function.get(),
299 "[{\"populate\": true}]",
300 browser())));
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(
348 function.get(),
349 "[{\"windowTypes\": [\"app\", \"devtools\", \"normal\", \"panel\", "
350 "\"popup\"]}]",
351 browser())));
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);
368 result_ids.clear();
369 function = new WindowsGetAllFunction();
370 function->set_extension(extension.get());
371 result.reset(utils::ToList(utils::RunFunctionAndReturnSingleResult(
372 function.get(),
373 "[{\"populate\": true, \"windowTypes\": [\"app\", \"devtools\", "
374 "\"normal\", \"panel\", \"popup\"]}]",
375 browser())));
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}]",
411 browser())));
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(
430 function.get(),
431 kArgsWithoutExplicitIncognitoParam,
432 browser(),
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(
448 function.get(),
449 kArgsWithoutExplicitIncognitoParam,
450 incognito_browser,
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(),
471 kEmptyArgs,
472 browser(),
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(),
488 kEmptyArgs,
489 incognito_browser,
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}]",
566 browser())));
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}]",
583 browser())));
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(),
613 "[{}]",
614 browser())));
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),
653 browser())));
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(
668 function.get(),
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(
678 function.get(),
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(
688 function.get(),
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(
698 function.get(),
699 base::StringPrintf(kArgsMaximizedWithBounds, window_id), browser()),
700 keys::kInvalidWindowStateError));
703 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, UpdateAppWindowSizeConstraint) {
704 AppWindow* app_window = CreateTestAppWindow(
705 "{\"outerBounds\": "
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(
715 get_function.get(),
716 base::StringPrintf("[%u, {\"windowTypes\": [\"app\"]}]",
717 app_window->session_id().id()),
718 browser())));
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
724 // respected.
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()),
731 browser())));
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
737 // respected.
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()),
744 browser())));
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(
761 get_function.get(),
762 base::StringPrintf(
763 "[%u, {\"windowTypes\": [\"devtools\"]}]",
764 ExtensionTabUtil::GetWindowId(
765 DevToolsWindowTesting::Get(devtools)->browser())),
766 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),
780 browser())));
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 {
793 public:
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);
807 private:
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 {
812 public:
813 AppWindowActivatedWaiter(AppWindow* app_window,
814 content::BrowserContext* browser_context)
815 : app_window_(app_window),
816 browser_context_(browser_context),
817 waiting_(false) {
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()) {
827 waiting_ = true;
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();
836 waiting_ = false;
840 private:
841 AppWindow* app_window_;
842 content::BrowserContext* browser_context_;
843 bool waiting_;
846 // A helper class to wait for an views::Widget to become activated.
847 class WidgetActivatedWaiter : public views::WidgetObserver {
848 public:
849 explicit WidgetActivatedWaiter(views::Widget* widget)
850 : widget_(widget), waiting_(false) {
851 widget_->AddObserver(this);
853 ~WidgetActivatedWaiter() override { widget_->RemoveObserver(this); }
855 void ActivateAndWait() {
856 widget_->Activate();
857 if (!widget_->IsActive()) {
858 waiting_ = true;
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();
868 waiting_ = false;
872 private:
873 views::Widget* widget_;
874 bool waiting_;
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(
900 bool as_popup) {
901 Browser* new_browser;
902 if (as_popup)
903 new_browser = new Browser(
904 Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(),
905 browser()->host_desktop_type()));
906 else
907 new_browser = new Browser(Browser::CreateParams(
908 browser()->profile(), browser()->host_desktop_type()));
909 AddBlankTabAndShow(new_browser);
910 return 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))
917 return -2;
918 const base::Value* tab = NULL;
919 if (!tabs->Get(0, &tab))
920 return -2;
921 const base::DictionaryValue* tab_dict = NULL;
922 if (!tab->GetAsDictionary(&tab_dict))
923 return -2;
924 int tab_id = 0;
925 if (!tab_dict->GetInteger(keys::kIdKey, &tab_id))
926 return -2;
927 return 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(
955 "{\"outerBounds\": "
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(
1015 function.get(),
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());
1061 std::string error;
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());
1069 #endif
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(),
1080 window_id, &error);
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));
1099 EXPECT_TRUE(
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));
1111 EXPECT_TRUE(
1112 base::MatchPattern(RunCreateWindowExpectError(
1113 "[{\"state\": \"minimized\", \"width\": 500}]"),
1114 keys::kInvalidWindowStateError));
1115 EXPECT_TRUE(
1116 base::MatchPattern(RunCreateWindowExpectError(
1117 "[{\"state\": \"maximized\", \"width\": 500}]"),
1118 keys::kInvalidWindowStateError));
1119 EXPECT_TRUE(
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(),
1128 NEW_FOREGROUND_TAB,
1129 ui::PAGE_TRANSITION_LINK,
1130 false);
1131 content::WebContents* web_contents = browser()->OpenURL(params);
1132 int tab_id = ExtensionTabUtil::GetTabId(web_contents);
1133 int window_id = ExtensionTabUtil::GetWindowIdOfTab(web_contents);
1134 int tab_index = -1;
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\": "
1143 "[\"tabs\"]}"));
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),
1152 browser())));
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(),
1172 NEW_FOREGROUND_TAB,
1173 ui::PAGE_TRANSITION_LINK,
1174 false);
1175 content::WebContents* web_contents = browser()->OpenURL(params);
1176 int tab_id = ExtensionTabUtil::GetTabId(web_contents);
1177 int window_id = ExtensionTabUtil::GetWindowIdOfTab(web_contents);
1178 int tab_index = -1;
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),
1191 browser())));
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);
1210 ASSERT_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);
1227 ASSERT_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);
1247 ASSERT_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)
1274 listener.Reply("");
1275 #else
1276 listener.Reply("focus");
1277 #endif
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\": "
1286 "[\"tabs\"]}"));
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 {
1309 public:
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,
1323 std::string* mode,
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,
1336 const char* mode,
1337 const char* scope);
1339 content::WebContents* OpenUrlAndWaitForLoad(const GURL& url);
1341 private:
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(
1363 int tab_id,
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),
1374 browser()));
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,
1385 const char* mode,
1386 const char* scope) {
1387 scoped_refptr<TabsSetZoomSettingsFunction> set_zoom_settings_function(
1388 new TabsSetZoomSettingsFunction());
1389 set_zoom_settings_function->set_extension(extension_.get());
1391 std::string args;
1392 if (scope) {
1393 args = base::StringPrintf("[%u, {\"mode\": \"%s\", \"scope\": \"%s\"}]",
1394 tab_id, mode, scope);
1395 } else {
1396 args = base::StringPrintf("[%u, {\"mode\": \"%s\"}]", tab_id, mode);
1399 return utils::RunFunction(set_zoom_settings_function.get(),
1400 args,
1401 browser(),
1402 extension_function_test_utils::NONE);
1405 testing::AssertionResult ExtensionTabsZoomTest::RunGetZoomSettings(
1406 int tab_id,
1407 std::string* mode,
1408 std::string* scope) {
1409 DCHECK(mode);
1410 DCHECK(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),
1420 browser())));
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(
1432 int tab_id,
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),
1444 browser())));
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),
1468 browser());
1471 std::string ExtensionTabsZoomTest::RunSetZoomSettingsExpectError(
1472 int tab_id,
1473 const char* mode,
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(),
1480 base::StringPrintf(
1481 "[%u, {\"mode\": \"%s\", "
1482 "\"scope\": \"%s\"}]",
1483 tab_id,
1484 mode,
1485 scope),
1486 browser());
1489 content::WebContents* ExtensionTabsZoomTest::OpenUrlAndWaitForLoad(
1490 const GURL& url) {
1491 ui_test_utils::NavigateToURLWithDisposition(
1492 browser(),
1493 url,
1494 NEW_FOREGROUND_TAB,
1495 ui_test_utils::BROWSER_TEST_WAIT_FOR_NAVIGATION);
1496 return browser()->tab_strip_model()->GetActiveWebContents();
1499 namespace {
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(),
1508 NEW_FOREGROUND_TAB,
1509 ui::PAGE_TRANSITION_LINK,
1510 false);
1513 } // namespace
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().
1532 zoom_factor = -1;
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
1551 // correct value.
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);
1619 ASSERT_FLOAT_EQ(
1620 1.f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1)));
1621 ASSERT_FLOAT_EQ(
1622 1.f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A2)));
1623 ASSERT_FLOAT_EQ(
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));
1629 EXPECT_FLOAT_EQ(
1630 1.1f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1)));
1631 EXPECT_FLOAT_EQ(
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));
1639 EXPECT_FLOAT_EQ(
1640 1.2f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1)));
1641 EXPECT_FLOAT_EQ(
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));
1647 EXPECT_FLOAT_EQ(
1648 1.3f, content::ZoomLevelToZoomFactor(GetZoomLevel(web_contents_A1)));
1649 EXPECT_FLOAT_EQ(
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));
1656 EXPECT_FLOAT_EQ(
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));
1660 EXPECT_FLOAT_EQ(
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"));
1678 std::string mode;
1679 std::string scope;
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);
1697 std::string mode;
1698 std::string scope;
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);
1710 std::string error =
1711 RunSetZoomSettingsExpectError(tab_id, "manual", "per-origin");
1712 EXPECT_TRUE(base::MatchPattern(error, keys::kPerOriginOnlyInAutomaticError));
1713 error =
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);
1737 EXPECT_TRUE(
1738 base::MatchPattern(error, manifest_errors::kCannotAccessChromeUrl));
1740 // chrome.tabs.setZoomSettings().
1741 error = RunSetZoomSettingsExpectError(tab_id, "manual", "per-tab");
1742 EXPECT_TRUE(
1743 base::MatchPattern(error, manifest_errors::kCannotAccessChromeUrl));
1746 } // namespace extensions