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