• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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.
4 
5 
6 #include <string>
7 
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/string_util.h"
12 #include "base/strings/stringprintf.h"
13 #include "base/values.h"
14 #include "chrome/browser/extensions/api/tabs/tabs_api.h"
15 #include "chrome/browser/extensions/api/tabs/tabs_constants.h"
16 #include "chrome/browser/extensions/extension_function_test_utils.h"
17 #include "chrome/browser/extensions/extension_tab_util.h"
18 #include "chrome/browser/prefs/incognito_mode_prefs.h"
19 #include "chrome/browser/profiles/profile.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_commands.h"
22 #include "chrome/browser/ui/browser_window.h"
23 #include "chrome/test/base/in_process_browser_test.h"
24 #include "chrome/test/base/ui_test_utils.h"
25 #include "content/public/common/url_constants.h"
26 #include "ui/gfx/rect.h"
27 
28 namespace extensions {
29 
30 namespace keys = tabs_constants;
31 namespace utils = extension_function_test_utils;
32 
33 namespace {
34 
35 class ExtensionTabsTest : public InProcessBrowserTest {
36 };
37 
38 }
39 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,GetWindow)40 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, GetWindow) {
41   int window_id = ExtensionTabUtil::GetWindowId(browser());
42 
43   // Invalid window ID error.
44   scoped_refptr<WindowsGetFunction> function = new WindowsGetFunction();
45   scoped_refptr<Extension> extension(utils::CreateEmptyExtension());
46   function->set_extension(extension.get());
47   EXPECT_TRUE(MatchPattern(
48       utils::RunFunctionAndReturnError(
49           function.get(),
50           base::StringPrintf("[%u]", window_id + 1),
51           browser()),
52       keys::kWindowNotFoundError));
53 
54   // Basic window details.
55   gfx::Rect bounds;
56   if (browser()->window()->IsMinimized())
57     bounds = browser()->window()->GetRestoredBounds();
58   else
59     bounds = browser()->window()->GetBounds();
60 
61   function = new WindowsGetFunction();
62   function->set_extension(extension.get());
63   scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
64       utils::RunFunctionAndReturnSingleResult(
65           function.get(),
66           base::StringPrintf("[%u]", window_id),
67           browser())));
68   EXPECT_EQ(window_id, utils::GetInteger(result.get(), "id"));
69   EXPECT_FALSE(utils::GetBoolean(result.get(), "incognito"));
70   EXPECT_EQ("normal", utils::GetString(result.get(), "type"));
71   EXPECT_EQ(bounds.x(), utils::GetInteger(result.get(), "left"));
72   EXPECT_EQ(bounds.y(), utils::GetInteger(result.get(), "top"));
73   EXPECT_EQ(bounds.width(), utils::GetInteger(result.get(), "width"));
74   EXPECT_EQ(bounds.height(), utils::GetInteger(result.get(), "height"));
75 
76   // With "populate" enabled.
77   function = new WindowsGetFunction();
78   function->set_extension(extension.get());
79   result.reset(utils::ToDictionary(
80       utils::RunFunctionAndReturnSingleResult(
81           function.get(),
82           base::StringPrintf("[%u, {\"populate\": true}]", window_id),
83           browser())));
84 
85   EXPECT_EQ(window_id, utils::GetInteger(result.get(), "id"));
86   // "populate" was enabled so tabs should be populated.
87   base::ListValue* tabs = NULL;
88   EXPECT_TRUE(result.get()->GetList(keys::kTabsKey, &tabs));
89 
90   // TODO(aa): Can't assume window is focused. On mac, calling Activate() from a
91   // browser test doesn't seem to do anything, so can't test the opposite
92   // either.
93   EXPECT_EQ(browser()->window()->IsActive(),
94             utils::GetBoolean(result.get(), "focused"));
95 
96   // TODO(aa): Minimized and maximized dimensions. Is there a way to set
97   // minimize/maximize programmatically?
98 
99   // Popup.
100   Browser* popup_browser = new Browser(
101       Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(),
102                             browser()->host_desktop_type()));
103   function = new WindowsGetFunction();
104   function->set_extension(extension.get());
105   result.reset(utils::ToDictionary(
106       utils::RunFunctionAndReturnSingleResult(
107           function.get(),
108           base::StringPrintf(
109               "[%u]", ExtensionTabUtil::GetWindowId(popup_browser)),
110           browser())));
111   EXPECT_EQ("popup", utils::GetString(result.get(), "type"));
112 
113   // Incognito.
114   Browser* incognito_browser = CreateIncognitoBrowser();
115   int incognito_window_id = ExtensionTabUtil::GetWindowId(incognito_browser);
116 
117   // Without "include_incognito".
118   function = new WindowsGetFunction();
119   function->set_extension(extension.get());
120   EXPECT_TRUE(MatchPattern(
121       utils::RunFunctionAndReturnError(
122           function.get(),
123           base::StringPrintf("[%u]", incognito_window_id),
124           browser()),
125       keys::kWindowNotFoundError));
126 
127   // With "include_incognito".
128   function = new WindowsGetFunction();
129   function->set_extension(extension.get());
130   result.reset(utils::ToDictionary(
131       utils::RunFunctionAndReturnSingleResult(
132           function.get(),
133           base::StringPrintf("[%u]", incognito_window_id),
134           browser(),
135           utils::INCLUDE_INCOGNITO)));
136   EXPECT_TRUE(utils::GetBoolean(result.get(), "incognito"));
137 }
138 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,GetCurrentWindow)139 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, GetCurrentWindow) {
140   int window_id = ExtensionTabUtil::GetWindowId(browser());
141   Browser* new_browser = CreateBrowser(browser()->profile());
142   int new_id = ExtensionTabUtil::GetWindowId(new_browser);
143 
144   // Get the current window using new_browser.
145   scoped_refptr<WindowsGetCurrentFunction> function =
146       new WindowsGetCurrentFunction();
147   scoped_refptr<Extension> extension(utils::CreateEmptyExtension());
148   function->set_extension(extension.get());
149   scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
150       utils::RunFunctionAndReturnSingleResult(function.get(),
151                                               "[]",
152                                               new_browser)));
153 
154   // The id should match the window id of the browser instance that was passed
155   // to RunFunctionAndReturnSingleResult.
156   EXPECT_EQ(new_id, utils::GetInteger(result.get(), "id"));
157   base::ListValue* tabs = NULL;
158   EXPECT_FALSE(result.get()->GetList(keys::kTabsKey, &tabs));
159 
160   // Get the current window using the old window and make the tabs populated.
161   function = new WindowsGetCurrentFunction();
162   function->set_extension(extension.get());
163   result.reset(utils::ToDictionary(
164       utils::RunFunctionAndReturnSingleResult(function.get(),
165                                               "[{\"populate\": true}]",
166                                               browser())));
167 
168   // The id should match the window id of the browser instance that was passed
169   // to RunFunctionAndReturnSingleResult.
170   EXPECT_EQ(window_id, utils::GetInteger(result.get(), "id"));
171   // "populate" was enabled so tabs should be populated.
172   EXPECT_TRUE(result.get()->GetList(keys::kTabsKey, &tabs));
173 }
174 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,GetAllWindows)175 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, GetAllWindows) {
176   const size_t NUM_WINDOWS = 5;
177   std::set<int> window_ids;
178   std::set<int> result_ids;
179   window_ids.insert(ExtensionTabUtil::GetWindowId(browser()));
180 
181   for (size_t i = 0; i < NUM_WINDOWS - 1; ++i) {
182     Browser* new_browser = CreateBrowser(browser()->profile());
183     window_ids.insert(ExtensionTabUtil::GetWindowId(new_browser));
184   }
185 
186   scoped_refptr<WindowsGetAllFunction> function = new WindowsGetAllFunction();
187   scoped_refptr<Extension> extension(utils::CreateEmptyExtension());
188   function->set_extension(extension.get());
189   scoped_ptr<base::ListValue> result(utils::ToList(
190       utils::RunFunctionAndReturnSingleResult(function.get(),
191                                               "[]",
192                                               browser())));
193 
194   base::ListValue* windows = result.get();
195   EXPECT_EQ(NUM_WINDOWS, windows->GetSize());
196   for (size_t i = 0; i < NUM_WINDOWS; ++i) {
197     base::DictionaryValue* result_window = NULL;
198     EXPECT_TRUE(windows->GetDictionary(i, &result_window));
199     result_ids.insert(utils::GetInteger(result_window, "id"));
200 
201     // "populate" was not passed in so tabs are not populated.
202     base::ListValue* tabs = NULL;
203     EXPECT_FALSE(result_window->GetList(keys::kTabsKey, &tabs));
204   }
205   // The returned ids should contain all the current browser instance ids.
206   EXPECT_EQ(window_ids, result_ids);
207 
208   result_ids.clear();
209   function = new WindowsGetAllFunction();
210   function->set_extension(extension.get());
211   result.reset(utils::ToList(
212       utils::RunFunctionAndReturnSingleResult(function.get(),
213                                               "[{\"populate\": true}]",
214                                               browser())));
215 
216   windows = result.get();
217   EXPECT_EQ(NUM_WINDOWS, windows->GetSize());
218   for (size_t i = 0; i < windows->GetSize(); ++i) {
219     base::DictionaryValue* result_window = NULL;
220     EXPECT_TRUE(windows->GetDictionary(i, &result_window));
221     result_ids.insert(utils::GetInteger(result_window, "id"));
222 
223     // "populate" was enabled so tabs should be populated.
224     base::ListValue* tabs = NULL;
225     EXPECT_TRUE(result_window->GetList(keys::kTabsKey, &tabs));
226   }
227   // The returned ids should contain all the current browser instance ids.
228   EXPECT_EQ(window_ids, result_ids);
229 }
230 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,UpdateNoPermissions)231 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, UpdateNoPermissions) {
232   // The test empty extension has no permissions, therefore it should not get
233   // tab data in the function result.
234   scoped_refptr<TabsUpdateFunction> update_tab_function(
235       new TabsUpdateFunction());
236   scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension());
237   update_tab_function->set_extension(empty_extension.get());
238   // Without a callback the function will not generate a result.
239   update_tab_function->set_has_callback(true);
240 
241   scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
242       utils::RunFunctionAndReturnSingleResult(
243           update_tab_function.get(),
244           "[null, {\"url\": \"about:blank\", \"pinned\": true}]",
245           browser())));
246   // The url is stripped since the extension does not have tab permissions.
247   EXPECT_FALSE(result->HasKey("url"));
248   EXPECT_TRUE(utils::GetBoolean(result.get(), "pinned"));
249 }
250 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,DefaultToIncognitoWhenItIsForced)251 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,
252                        DefaultToIncognitoWhenItIsForced) {
253   static const char kArgsWithoutExplicitIncognitoParam[] =
254       "[{\"url\": \"about:blank\"}]";
255   // Force Incognito mode.
256   IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
257                                       IncognitoModePrefs::FORCED);
258   // Run without an explicit "incognito" param.
259   scoped_refptr<WindowsCreateFunction> function(new WindowsCreateFunction());
260   scoped_refptr<Extension> extension(utils::CreateEmptyExtension());
261   function->set_extension(extension.get());
262   scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
263       utils::RunFunctionAndReturnSingleResult(
264           function.get(),
265           kArgsWithoutExplicitIncognitoParam,
266           browser(),
267           utils::INCLUDE_INCOGNITO)));
268 
269   // Make sure it is a new(different) window.
270   EXPECT_NE(ExtensionTabUtil::GetWindowId(browser()),
271             utils::GetInteger(result.get(), "id"));
272   // ... and it is incognito.
273   EXPECT_TRUE(utils::GetBoolean(result.get(), "incognito"));
274 
275   // Now try creating a window from incognito window.
276   Browser* incognito_browser = CreateIncognitoBrowser();
277   // Run without an explicit "incognito" param.
278   function = new WindowsCreateFunction();
279   function->set_extension(extension.get());
280   result.reset(utils::ToDictionary(
281       utils::RunFunctionAndReturnSingleResult(
282           function.get(),
283           kArgsWithoutExplicitIncognitoParam,
284           incognito_browser,
285           utils::INCLUDE_INCOGNITO)));
286   // Make sure it is a new(different) window.
287   EXPECT_NE(ExtensionTabUtil::GetWindowId(incognito_browser),
288             utils::GetInteger(result.get(), "id"));
289   // ... and it is incognito.
290   EXPECT_TRUE(utils::GetBoolean(result.get(), "incognito"));
291 }
292 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,DefaultToIncognitoWhenItIsForcedAndNoArgs)293 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,
294                        DefaultToIncognitoWhenItIsForcedAndNoArgs) {
295   static const char kEmptyArgs[] = "[]";
296   // Force Incognito mode.
297   IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
298                                       IncognitoModePrefs::FORCED);
299   // Run without an explicit "incognito" param.
300   scoped_refptr<WindowsCreateFunction> function = new WindowsCreateFunction();
301   scoped_refptr<Extension> extension(utils::CreateEmptyExtension());
302   function->set_extension(extension.get());
303   scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
304       utils::RunFunctionAndReturnSingleResult(function.get(),
305                                               kEmptyArgs,
306                                               browser(),
307                                               utils::INCLUDE_INCOGNITO)));
308 
309   // Make sure it is a new(different) window.
310   EXPECT_NE(ExtensionTabUtil::GetWindowId(browser()),
311             utils::GetInteger(result.get(), "id"));
312   // ... and it is incognito.
313   EXPECT_TRUE(utils::GetBoolean(result.get(), "incognito"));
314 
315   // Now try creating a window from incognito window.
316   Browser* incognito_browser = CreateIncognitoBrowser();
317   // Run without an explicit "incognito" param.
318   function = new WindowsCreateFunction();
319   function->set_extension(extension.get());
320   result.reset(utils::ToDictionary(
321       utils::RunFunctionAndReturnSingleResult(function.get(),
322                                               kEmptyArgs,
323                                               incognito_browser,
324                                               utils::INCLUDE_INCOGNITO)));
325   // Make sure it is a new(different) window.
326   EXPECT_NE(ExtensionTabUtil::GetWindowId(incognito_browser),
327             utils::GetInteger(result.get(), "id"));
328   // ... and it is incognito.
329   EXPECT_TRUE(utils::GetBoolean(result.get(), "incognito"));
330 }
331 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,DontCreateNormalWindowWhenIncognitoForced)332 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,
333                        DontCreateNormalWindowWhenIncognitoForced) {
334   static const char kArgsWithExplicitIncognitoParam[] =
335       "[{\"url\": \"about:blank\", \"incognito\": false }]";
336   // Force Incognito mode.
337   IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
338                                       IncognitoModePrefs::FORCED);
339 
340   // Run with an explicit "incognito" param.
341   scoped_refptr<WindowsCreateFunction> function = new WindowsCreateFunction();
342   scoped_refptr<Extension> extension(utils::CreateEmptyExtension());
343   function->set_extension(extension.get());
344   EXPECT_TRUE(MatchPattern(
345       utils::RunFunctionAndReturnError(function.get(),
346                                        kArgsWithExplicitIncognitoParam,
347                                        browser()),
348       keys::kIncognitoModeIsForced));
349 
350   // Now try opening a normal window from incognito window.
351   Browser* incognito_browser = CreateIncognitoBrowser();
352   // Run with an explicit "incognito" param.
353   function = new WindowsCreateFunction();
354   function->set_extension(extension.get());
355   EXPECT_TRUE(MatchPattern(
356       utils::RunFunctionAndReturnError(function.get(),
357                                        kArgsWithExplicitIncognitoParam,
358                                        incognito_browser),
359       keys::kIncognitoModeIsForced));
360 }
361 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,DontCreateIncognitoWindowWhenIncognitoDisabled)362 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,
363                        DontCreateIncognitoWindowWhenIncognitoDisabled) {
364   static const char kArgs[] =
365       "[{\"url\": \"about:blank\", \"incognito\": true }]";
366 
367   Browser* incognito_browser = CreateIncognitoBrowser();
368   // Disable Incognito mode.
369   IncognitoModePrefs::SetAvailability(browser()->profile()->GetPrefs(),
370                                       IncognitoModePrefs::DISABLED);
371   // Run in normal window.
372   scoped_refptr<WindowsCreateFunction> function = new WindowsCreateFunction();
373   scoped_refptr<Extension> extension(utils::CreateEmptyExtension());
374   function->set_extension(extension.get());
375   EXPECT_TRUE(MatchPattern(
376       utils::RunFunctionAndReturnError(function.get(),
377                                        kArgs,
378                                        browser()),
379       keys::kIncognitoModeIsDisabled));
380 
381   // Run in incognito window.
382   function = new WindowsCreateFunction();
383   function->set_extension(extension.get());
384   EXPECT_TRUE(MatchPattern(
385       utils::RunFunctionAndReturnError(function.get(),
386                                        kArgs,
387                                        incognito_browser),
388       keys::kIncognitoModeIsDisabled));
389 }
390 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,QueryCurrentWindowTabs)391 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, QueryCurrentWindowTabs) {
392   const size_t kExtraWindows = 3;
393   for (size_t i = 0; i < kExtraWindows; ++i)
394     CreateBrowser(browser()->profile());
395 
396   GURL url(url::kAboutBlankURL);
397   AddTabAtIndexToBrowser(browser(), 0, url, content::PAGE_TRANSITION_LINK);
398   int window_id = ExtensionTabUtil::GetWindowId(browser());
399 
400   // Get tabs in the 'current' window called from non-focused browser.
401   scoped_refptr<TabsQueryFunction> function = new TabsQueryFunction();
402   function->set_extension(utils::CreateEmptyExtension().get());
403   scoped_ptr<base::ListValue> result(utils::ToList(
404       utils::RunFunctionAndReturnSingleResult(function.get(),
405                                               "[{\"currentWindow\":true}]",
406                                               browser())));
407 
408   base::ListValue* result_tabs = result.get();
409   // We should have one initial tab and one added tab.
410   EXPECT_EQ(2u, result_tabs->GetSize());
411   for (size_t i = 0; i < result_tabs->GetSize(); ++i) {
412     base::DictionaryValue* result_tab = NULL;
413     EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
414     EXPECT_EQ(window_id, utils::GetInteger(result_tab, keys::kWindowIdKey));
415   }
416 
417   // Get tabs NOT in the 'current' window called from non-focused browser.
418   function = new TabsQueryFunction();
419   function->set_extension(utils::CreateEmptyExtension().get());
420   result.reset(utils::ToList(
421       utils::RunFunctionAndReturnSingleResult(function.get(),
422                                               "[{\"currentWindow\":false}]",
423                                               browser())));
424 
425   result_tabs = result.get();
426   // We should have one tab for each extra window.
427   EXPECT_EQ(kExtraWindows, result_tabs->GetSize());
428   for (size_t i = 0; i < kExtraWindows; ++i) {
429     base::DictionaryValue* result_tab = NULL;
430     EXPECT_TRUE(result_tabs->GetDictionary(i, &result_tab));
431     EXPECT_NE(window_id, utils::GetInteger(result_tab, keys::kWindowIdKey));
432   }
433 }
434 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,DontCreateTabInClosingPopupWindow)435 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DontCreateTabInClosingPopupWindow) {
436   // Test creates new popup window, closes it right away and then tries to open
437   // a new tab in it. Tab should not be opened in the popup window, but in a
438   // tabbed browser window.
439   Browser* popup_browser = new Browser(
440       Browser::CreateParams(Browser::TYPE_POPUP, browser()->profile(),
441                             browser()->host_desktop_type()));
442   int window_id = ExtensionTabUtil::GetWindowId(popup_browser);
443   chrome::CloseWindow(popup_browser);
444 
445   scoped_refptr<TabsCreateFunction> create_tab_function(
446       new TabsCreateFunction());
447   create_tab_function->set_extension(utils::CreateEmptyExtension().get());
448   // Without a callback the function will not generate a result.
449   create_tab_function->set_has_callback(true);
450 
451   static const char kNewBlankTabArgs[] =
452       "[{\"url\": \"about:blank\", \"windowId\": %u}]";
453 
454   scoped_ptr<base::DictionaryValue> result(utils::ToDictionary(
455       utils::RunFunctionAndReturnSingleResult(
456           create_tab_function.get(),
457           base::StringPrintf(kNewBlankTabArgs, window_id),
458           browser())));
459 
460   EXPECT_NE(window_id, utils::GetInteger(result.get(), "windowId"));
461 }
462 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,InvalidUpdateWindowState)463 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, InvalidUpdateWindowState) {
464   int window_id = ExtensionTabUtil::GetWindowId(browser());
465 
466   static const char kArgsMinimizedWithFocus[] =
467       "[%u, {\"state\": \"minimized\", \"focused\": true}]";
468   scoped_refptr<WindowsUpdateFunction> function = new WindowsUpdateFunction();
469   scoped_refptr<Extension> extension(utils::CreateEmptyExtension());
470   function->set_extension(extension.get());
471   EXPECT_TRUE(MatchPattern(
472       utils::RunFunctionAndReturnError(
473           function.get(),
474           base::StringPrintf(kArgsMinimizedWithFocus, window_id),
475           browser()),
476       keys::kInvalidWindowStateError));
477 
478   static const char kArgsMaximizedWithoutFocus[] =
479       "[%u, {\"state\": \"maximized\", \"focused\": false}]";
480   function = new WindowsUpdateFunction();
481   function->set_extension(extension.get());
482   EXPECT_TRUE(MatchPattern(
483       utils::RunFunctionAndReturnError(
484           function.get(),
485           base::StringPrintf(kArgsMaximizedWithoutFocus, window_id),
486           browser()),
487       keys::kInvalidWindowStateError));
488 
489   static const char kArgsMinimizedWithBounds[] =
490       "[%u, {\"state\": \"minimized\", \"width\": 500}]";
491   function = new WindowsUpdateFunction();
492   function->set_extension(extension.get());
493   EXPECT_TRUE(MatchPattern(
494       utils::RunFunctionAndReturnError(
495           function.get(),
496           base::StringPrintf(kArgsMinimizedWithBounds, window_id),
497           browser()),
498       keys::kInvalidWindowStateError));
499 
500   static const char kArgsMaximizedWithBounds[] =
501       "[%u, {\"state\": \"maximized\", \"width\": 500}]";
502   function = new WindowsUpdateFunction();
503   function->set_extension(extension.get());
504   EXPECT_TRUE(MatchPattern(
505       utils::RunFunctionAndReturnError(
506           function.get(),
507           base::StringPrintf(kArgsMaximizedWithBounds, window_id),
508           browser()),
509       keys::kInvalidWindowStateError));
510 }
511 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,DuplicateTab)512 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DuplicateTab) {
513   content::OpenURLParams params(GURL(url::kAboutBlankURL),
514                                 content::Referrer(),
515                                 NEW_FOREGROUND_TAB,
516                                 content::PAGE_TRANSITION_LINK,
517                                 false);
518   content::WebContents* web_contents = browser()->OpenURL(params);
519   int tab_id = ExtensionTabUtil::GetTabId(web_contents);
520   int window_id = ExtensionTabUtil::GetWindowIdOfTab(web_contents);
521   int tab_index = -1;
522   TabStripModel* tab_strip;
523   ExtensionTabUtil::GetTabStripModel(web_contents, &tab_strip, &tab_index);
524 
525   scoped_refptr<TabsDuplicateFunction> duplicate_tab_function(
526       new TabsDuplicateFunction());
527   scoped_ptr<base::DictionaryValue> test_extension_value(
528       utils::ParseDictionary(
529       "{\"name\": \"Test\", \"version\": \"1.0\", \"permissions\": [\"tabs\"]}"
530       ));
531   scoped_refptr<Extension> empty_tab_extension(
532       utils::CreateExtension(test_extension_value.get()));
533   duplicate_tab_function->set_extension(empty_tab_extension.get());
534   duplicate_tab_function->set_has_callback(true);
535 
536   scoped_ptr<base::DictionaryValue> duplicate_result(utils::ToDictionary(
537       utils::RunFunctionAndReturnSingleResult(
538           duplicate_tab_function.get(), base::StringPrintf("[%u]", tab_id),
539           browser())));
540 
541   int duplicate_tab_id = utils::GetInteger(duplicate_result.get(), "id");
542   int duplicate_tab_window_id = utils::GetInteger(duplicate_result.get(),
543                                                   "windowId");
544   int duplicate_tab_index = utils::GetInteger(duplicate_result.get(), "index");
545   EXPECT_EQ(base::Value::TYPE_DICTIONARY, duplicate_result->GetType());
546   // Duplicate tab id should be different from the original tab id.
547   EXPECT_NE(tab_id, duplicate_tab_id);
548   EXPECT_EQ(window_id, duplicate_tab_window_id);
549   EXPECT_EQ(tab_index + 1, duplicate_tab_index);
550   // The test empty tab extension has tabs permissions, therefore
551   // |duplicate_result| should contain url, title, and faviconUrl
552   // in the function result.
553   EXPECT_TRUE(utils::HasPrivacySensitiveFields(duplicate_result.get()));
554 }
555 
IN_PROC_BROWSER_TEST_F(ExtensionTabsTest,DuplicateTabNoPermission)556 IN_PROC_BROWSER_TEST_F(ExtensionTabsTest, DuplicateTabNoPermission) {
557   content::OpenURLParams params(GURL(url::kAboutBlankURL),
558                                 content::Referrer(),
559                                 NEW_FOREGROUND_TAB,
560                                 content::PAGE_TRANSITION_LINK,
561                                 false);
562   content::WebContents* web_contents = browser()->OpenURL(params);
563   int tab_id = ExtensionTabUtil::GetTabId(web_contents);
564   int window_id = ExtensionTabUtil::GetWindowIdOfTab(web_contents);
565   int tab_index = -1;
566   TabStripModel* tab_strip;
567   ExtensionTabUtil::GetTabStripModel(web_contents, &tab_strip, &tab_index);
568 
569   scoped_refptr<TabsDuplicateFunction> duplicate_tab_function(
570       new TabsDuplicateFunction());
571   scoped_refptr<Extension> empty_extension(utils::CreateEmptyExtension());
572   duplicate_tab_function->set_extension(empty_extension.get());
573   duplicate_tab_function->set_has_callback(true);
574 
575   scoped_ptr<base::DictionaryValue> duplicate_result(utils::ToDictionary(
576       utils::RunFunctionAndReturnSingleResult(
577           duplicate_tab_function.get(), base::StringPrintf("[%u]", tab_id),
578           browser())));
579 
580   int duplicate_tab_id = utils::GetInteger(duplicate_result.get(), "id");
581   int duplicate_tab_window_id = utils::GetInteger(duplicate_result.get(),
582                                                   "windowId");
583   int duplicate_tab_index = utils::GetInteger(duplicate_result.get(), "index");
584   EXPECT_EQ(base::Value::TYPE_DICTIONARY, duplicate_result->GetType());
585   // Duplicate tab id should be different from the original tab id.
586   EXPECT_NE(tab_id, duplicate_tab_id);
587   EXPECT_EQ(window_id, duplicate_tab_window_id);
588   EXPECT_EQ(tab_index + 1, duplicate_tab_index);
589   // The test empty extension has no permissions, therefore |duplicate_result|
590   // should not contain url, title, and faviconUrl in the function result.
591   EXPECT_FALSE(utils::HasPrivacySensitiveFields(duplicate_result.get()));
592 }
593 
594 }  // namespace extensions
595