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 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 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 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 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 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 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 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 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 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 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 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 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 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