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