extension_browsertests_misc.cc revision 21d179b334e59e9a3bfcaed4c4430bef1bc5759d
1// Copyright (c) 2010 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#include "base/file_util.h" 6#include "base/ref_counted.h" 7#include "base/utf_string_conversions.h" 8#include "chrome/browser/browser_list.h" 9#include "chrome/browser/extensions/autoupdate_interceptor.h" 10#include "chrome/browser/extensions/extension_apitest.h" 11#include "chrome/browser/extensions/extension_browsertest.h" 12#include "chrome/browser/extensions/extension_error_reporter.h" 13#include "chrome/browser/extensions/extension_host.h" 14#include "chrome/browser/extensions/extension_process_manager.h" 15#include "chrome/browser/extensions/extension_tabs_module.h" 16#include "chrome/browser/extensions/extension_service.h" 17#include "chrome/browser/extensions/extension_updater.h" 18#include "chrome/browser/profiles/profile.h" 19#include "chrome/browser/renderer_host/render_view_host.h" 20#include "chrome/browser/renderer_host/site_instance.h" 21#include "chrome/browser/tab_contents/tab_contents.h" 22#include "chrome/browser/tabs/tab_strip_model.h" 23#include "chrome/browser/ui/browser.h" 24#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h" 25#include "chrome/common/chrome_paths.h" 26#include "chrome/common/extensions/extension_action.h" 27#include "chrome/common/url_constants.h" 28#include "chrome/test/ui_test_utils.h" 29#include "net/base/mock_host_resolver.h" 30#include "net/base/net_util.h" 31#include "net/test/test_server.h" 32 33#if defined(TOOLKIT_VIEWS) 34#include "chrome/browser/views/frame/browser_view.h" 35#endif 36 37const std::string kSubscribePage = "/subscribe.html"; 38const std::string kFeedPage = "files/feeds/feed.html"; 39const std::string kFeedPageMultiRel = "files/feeds/feed_multi_rel.html"; 40const std::string kNoFeedPage = "files/feeds/no_feed.html"; 41const std::string kValidFeed0 = "files/feeds/feed_script.xml"; 42const std::string kValidFeed1 = "files/feeds/feed1.xml"; 43const std::string kValidFeed2 = "files/feeds/feed2.xml"; 44const std::string kValidFeed3 = "files/feeds/feed3.xml"; 45const std::string kValidFeed4 = "files/feeds/feed4.xml"; 46const std::string kValidFeed5 = "files/feeds/feed5.xml"; 47const std::string kValidFeed6 = "files/feeds/feed6.xml"; 48const std::string kValidFeedNoLinks = "files/feeds/feed_nolinks.xml"; 49const std::string kInvalidFeed1 = "files/feeds/feed_invalid1.xml"; 50const std::string kInvalidFeed2 = "files/feeds/feed_invalid2.xml"; 51const std::string kLocalization = 52 "files/extensions/browsertest/title_localized_pa/simple.html"; 53const std::string kHashPageA = 54 "files/extensions/api_test/page_action/hash_change/test_page_A.html"; 55const std::string kHashPageAHash = kHashPageA + "#asdf"; 56const std::string kHashPageB = 57 "files/extensions/api_test/page_action/hash_change/test_page_B.html"; 58 59// Looks for an ExtensionHost whose URL has the given path component (including 60// leading slash). Also verifies that the expected number of hosts are loaded. 61static ExtensionHost* FindHostWithPath(ExtensionProcessManager* manager, 62 const std::string& path, 63 int expected_hosts) { 64 ExtensionHost* host = NULL; 65 int num_hosts = 0; 66 for (ExtensionProcessManager::const_iterator iter = manager->begin(); 67 iter != manager->end(); ++iter) { 68 if ((*iter)->GetURL().path() == path) { 69 EXPECT_FALSE(host); 70 host = *iter; 71 } 72 num_hosts++; 73 } 74 EXPECT_EQ(expected_hosts, num_hosts); 75 return host; 76} 77 78// Tests that extension resources can be loaded from origins which the 79// extension specifies in permissions but not from others. 80IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, OriginPrivileges) { 81 host_resolver()->AddRule("*", "127.0.0.1"); 82 ASSERT_TRUE(test_server()->Start()); 83 ASSERT_TRUE(LoadExtension(test_data_dir_ 84 .AppendASCII("origin_privileges").AppendASCII("extension"))); 85 86 GURL origin_privileges_index( 87 test_server()->GetURL("files/extensions/origin_privileges/index.html")); 88 89 std::string host_a("a.com"); 90 GURL::Replacements make_host_a_com; 91 make_host_a_com.SetHostStr(host_a); 92 93 std::string host_b("b.com"); 94 GURL::Replacements make_host_b_com; 95 make_host_b_com.SetHostStr(host_b); 96 97 // A web host that has permission. 98 ui_test_utils::NavigateToURL( 99 browser(), origin_privileges_index.ReplaceComponents(make_host_a_com)); 100 std::string result; 101 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 102 browser()->GetSelectedTabContents()->render_view_host(), L"", 103 L"window.domAutomationController.send(document.title)", 104 &result)); 105 EXPECT_EQ(result, "Loaded"); 106 107 // A web host that does not have permission. 108 ui_test_utils::NavigateToURL( 109 browser(), origin_privileges_index.ReplaceComponents(make_host_b_com)); 110 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 111 browser()->GetSelectedTabContents()->render_view_host(), L"", 112 L"window.domAutomationController.send(document.title)", 113 &result)); 114 EXPECT_EQ(result, "Image failed to load"); 115 116 // A data URL. Data URLs should always be able to load chrome-extension:// 117 // resources. 118 std::string file_source; 119 ASSERT_TRUE(file_util::ReadFileToString( 120 test_data_dir_.AppendASCII("origin_privileges") 121 .AppendASCII("index.html"), &file_source)); 122 ui_test_utils::NavigateToURL(browser(), 123 GURL(std::string("data:text/html;charset=utf-8,") + file_source)); 124 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 125 browser()->GetSelectedTabContents()->render_view_host(), L"", 126 L"window.domAutomationController.send(document.title)", 127 &result)); 128 EXPECT_EQ(result, "Loaded"); 129 130 // A different extension. Extensions should always be able to load each 131 // other's resources. 132 ASSERT_TRUE(LoadExtension(test_data_dir_ 133 .AppendASCII("origin_privileges").AppendASCII("extension2"))); 134 ui_test_utils::NavigateToURL( 135 browser(), 136 GURL("chrome-extension://pbkkcbgdkliohhfaeefcijaghglkahja/index.html")); 137 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 138 browser()->GetSelectedTabContents()->render_view_host(), L"", 139 L"window.domAutomationController.send(document.title)", 140 &result)); 141 EXPECT_EQ(result, "Loaded"); 142} 143 144// Tests that we can load extension pages into the tab area and they can call 145// extension APIs. 146IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, TabContents) { 147 ASSERT_TRUE(LoadExtension( 148 test_data_dir_.AppendASCII("good").AppendASCII("Extensions") 149 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj") 150 .AppendASCII("1.0.0.0"))); 151 152 ui_test_utils::NavigateToURL( 153 browser(), 154 GURL("chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/page.html")); 155 156 bool result = false; 157 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 158 browser()->GetSelectedTabContents()->render_view_host(), L"", 159 L"testTabsAPI()", &result)); 160 EXPECT_TRUE(result); 161 162 // There was a bug where we would crash if we navigated to a page in the same 163 // extension because no new render view was getting created, so we would not 164 // do some setup. 165 ui_test_utils::NavigateToURL( 166 browser(), 167 GURL("chrome-extension://behllobkkfkfnphdnhnkndlbkcpglgmj/page.html")); 168 result = false; 169 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 170 browser()->GetSelectedTabContents()->render_view_host(), L"", 171 L"testTabsAPI()", &result)); 172 EXPECT_TRUE(result); 173} 174 175// Tests that GPU-related WebKit preferences are set for extension background 176// pages. See http://crbug.com/64512. 177IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, WebKitPrefsBackgroundPage) { 178 ASSERT_TRUE(LoadExtension( 179 test_data_dir_.AppendASCII("good").AppendASCII("Extensions") 180 .AppendASCII("behllobkkfkfnphdnhnkndlbkcpglgmj") 181 .AppendASCII("1.0.0.0"))); 182 183 ExtensionProcessManager* manager = 184 browser()->profile()->GetExtensionProcessManager(); 185 ExtensionHost* host = FindHostWithPath(manager, "/backgroundpage.html", 1); 186 WebPreferences prefs = host->GetWebkitPrefs(); 187 ASSERT_FALSE(prefs.experimental_webgl_enabled); 188 ASSERT_FALSE(prefs.accelerated_compositing_enabled); 189 ASSERT_FALSE(prefs.accelerated_2d_canvas_enabled); 190} 191 192// Tests that we can load page actions in the Omnibox. 193IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, PageAction) { 194 ASSERT_TRUE(test_server()->Start()); 195 196 // This page action will not show an icon, since it doesn't specify one but 197 // is included here to test for a crash (http://crbug.com/25562). 198 ASSERT_TRUE(LoadExtension( 199 test_data_dir_.AppendASCII("browsertest") 200 .AppendASCII("crash_25562"))); 201 202 ASSERT_TRUE(LoadExtension( 203 test_data_dir_.AppendASCII("subscribe_page_action"))); 204 205 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(0)); 206 207 // Navigate to the feed page. 208 GURL feed_url = test_server()->GetURL(kFeedPage); 209 ui_test_utils::NavigateToURL(browser(), feed_url); 210 // We should now have one page action ready to go in the LocationBar. 211 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1)); 212 213 // Navigate to a page with no feed. 214 GURL no_feed = test_server()->GetURL(kNoFeedPage); 215 ui_test_utils::NavigateToURL(browser(), no_feed); 216 // Make sure the page action goes away. 217 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(0)); 218} 219 220// Tests that we don't lose the page action icon on in-page navigations. 221IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, PageActionInPageNavigation) { 222 ASSERT_TRUE(test_server()->Start()); 223 224 FilePath extension_path(test_data_dir_.AppendASCII("api_test") 225 .AppendASCII("page_action") 226 .AppendASCII("hash_change")); 227 ASSERT_TRUE(LoadExtension(extension_path)); 228 229 // Page action should become visible when we navigate here. 230 GURL feed_url = test_server()->GetURL(kHashPageA); 231 ui_test_utils::NavigateToURL(browser(), feed_url); 232 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1)); 233 234 // In-page navigation, page action should remain. 235 feed_url = test_server()->GetURL(kHashPageAHash); 236 ui_test_utils::NavigateToURL(browser(), feed_url); 237 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1)); 238 239 // Not an in-page navigation, page action should go away. 240 feed_url = test_server()->GetURL(kHashPageB); 241 ui_test_utils::NavigateToURL(browser(), feed_url); 242 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(0)); 243} 244 245// Tests that the location bar forgets about unloaded page actions. 246IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, UnloadPageAction) { 247 ASSERT_TRUE(test_server()->Start()); 248 249 FilePath extension_path(test_data_dir_.AppendASCII("subscribe_page_action")); 250 ASSERT_TRUE(LoadExtension(extension_path)); 251 252 // Navigation prompts the location bar to load page actions. 253 GURL feed_url = test_server()->GetURL(kFeedPage); 254 ui_test_utils::NavigateToURL(browser(), feed_url); 255 ASSERT_TRUE(WaitForPageActionCountChangeTo(1)); 256 257 UnloadExtension(last_loaded_extension_id_); 258 259 // Make sure the page action goes away when it's unloaded. 260 ASSERT_TRUE(WaitForPageActionCountChangeTo(0)); 261} 262 263// Flaky crash on Mac debug. http://crbug.com/45079 264#if defined(OS_MACOSX) 265#define PageActionRefreshCrash PageActionRefreshCrash 266#endif 267// Tests that we can load page actions in the Omnibox. 268IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, PageActionRefreshCrash) { 269 base::TimeTicks start_time = base::TimeTicks::Now(); 270 271 ExtensionService* service = browser()->profile()->GetExtensionService(); 272 273 size_t size_before = service->extensions()->size(); 274 275 FilePath base_path = test_data_dir_.AppendASCII("browsertest") 276 .AppendASCII("crash_44415"); 277 // Load extension A. 278 ASSERT_TRUE(LoadExtension(base_path.AppendASCII("ExtA"))); 279 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1)); 280 ASSERT_EQ(size_before + 1, service->extensions()->size()); 281 const Extension* extensionA = service->extensions()->at(size_before); 282 283 LOG(INFO) << "Load extension A done : " 284 << (base::TimeTicks::Now() - start_time).InMilliseconds() 285 << " ms" << std::flush; 286 287 // Load extension B. 288 ASSERT_TRUE(LoadExtension(base_path.AppendASCII("ExtB"))); 289 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(2)); 290 ASSERT_EQ(size_before + 2, service->extensions()->size()); 291 const Extension* extensionB = service->extensions()->at(size_before + 1); 292 293 LOG(INFO) << "Load extension B done : " 294 << (base::TimeTicks::Now() - start_time).InMilliseconds() 295 << " ms" << std::flush; 296 297 ReloadExtension(extensionA->id()); 298 // ExtensionA has changed, so refetch it. 299 ASSERT_EQ(size_before + 2, service->extensions()->size()); 300 extensionA = service->extensions()->at(size_before + 1); 301 302 LOG(INFO) << "Reload extension A done: " 303 << (base::TimeTicks::Now() - start_time).InMilliseconds() 304 << " ms" << std::flush; 305 306 ReloadExtension(extensionB->id()); 307 308 LOG(INFO) << "Reload extension B done: " 309 << (base::TimeTicks::Now() - start_time).InMilliseconds() 310 << " ms" << std::flush; 311 312 // This is where it would crash, before http://crbug.com/44415 was fixed. 313 ReloadExtension(extensionA->id()); 314 315 LOG(INFO) << "Test completed : " 316 << (base::TimeTicks::Now() - start_time).InMilliseconds() 317 << " ms" << std::flush; 318} 319 320// Makes sure that the RSS detects RSS feed links, even when rel tag contains 321// more than just "alternate". 322IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, RSSMultiRelLink) { 323 ASSERT_TRUE(test_server()->Start()); 324 325 ASSERT_TRUE(LoadExtension( 326 test_data_dir_.AppendASCII("subscribe_page_action"))); 327 328 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(0)); 329 330 // Navigate to the feed page. 331 GURL feed_url = test_server()->GetURL(kFeedPageMultiRel); 332 ui_test_utils::NavigateToURL(browser(), feed_url); 333 // We should now have one page action ready to go in the LocationBar. 334 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1)); 335} 336 337// Tests that tooltips of a browser action icon can be specified using UTF8. 338// See http://crbug.com/25349. 339IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, TitleLocalizationBrowserAction) { 340 ExtensionService* service = browser()->profile()->GetExtensionService(); 341 const size_t size_before = service->extensions()->size(); 342 FilePath extension_path(test_data_dir_.AppendASCII("browsertest") 343 .AppendASCII("title_localized")); 344 ASSERT_TRUE(LoadExtension(extension_path)); 345 346 ASSERT_EQ(size_before + 1, service->extensions()->size()); 347 const Extension* extension = service->extensions()->at(size_before); 348 349 EXPECT_STREQ(WideToUTF8(L"Hreggvi\u00F0ur: l10n browser action").c_str(), 350 extension->description().c_str()); 351 EXPECT_STREQ(WideToUTF8(L"Hreggvi\u00F0ur is my name").c_str(), 352 extension->name().c_str()); 353 int tab_id = ExtensionTabUtil::GetTabId(browser()->GetSelectedTabContents()); 354 EXPECT_STREQ(WideToUTF8(L"Hreggvi\u00F0ur").c_str(), 355 extension->browser_action()->GetTitle(tab_id).c_str()); 356} 357 358// Tests that tooltips of a page action icon can be specified using UTF8. 359// See http://crbug.com/25349. 360IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, TitleLocalizationPageAction) { 361 ASSERT_TRUE(test_server()->Start()); 362 363 ExtensionService* service = browser()->profile()->GetExtensionService(); 364 const size_t size_before = service->extensions()->size(); 365 366 FilePath extension_path(test_data_dir_.AppendASCII("browsertest") 367 .AppendASCII("title_localized_pa")); 368 ASSERT_TRUE(LoadExtension(extension_path)); 369 370 // Any navigation prompts the location bar to load the page action. 371 GURL url = test_server()->GetURL(kLocalization); 372 ui_test_utils::NavigateToURL(browser(), url); 373 ASSERT_TRUE(WaitForPageActionVisibilityChangeTo(1)); 374 375 ASSERT_EQ(size_before + 1, service->extensions()->size()); 376 const Extension* extension = service->extensions()->at(size_before); 377 378 EXPECT_STREQ(WideToUTF8(L"Hreggvi\u00F0ur: l10n page action").c_str(), 379 extension->description().c_str()); 380 EXPECT_STREQ(WideToUTF8(L"Hreggvi\u00F0ur is my name").c_str(), 381 extension->name().c_str()); 382 int tab_id = ExtensionTabUtil::GetTabId(browser()->GetSelectedTabContents()); 383 EXPECT_STREQ(WideToUTF8(L"Hreggvi\u00F0ur").c_str(), 384 extension->page_action()->GetTitle(tab_id).c_str()); 385} 386 387GURL GetFeedUrl(net::TestServer* server, const std::string& feed_page, 388 bool direct_url, std::string extension_id) { 389 GURL feed_url = server->GetURL(feed_page); 390 if (direct_url) { 391 // We navigate directly to the subscribe page for feeds where the feed 392 // sniffing won't work, in other words, as is the case for malformed feeds. 393 return GURL(std::string(chrome::kExtensionScheme) + 394 chrome::kStandardSchemeSeparator + 395 extension_id + std::string(kSubscribePage) + std::string("?") + 396 feed_url.spec() + std::string("&synchronous")); 397 } else { 398 // Navigate to the feed content (which will cause the extension to try to 399 // sniff the type and display the subscribe page in another tab. 400 return GURL(feed_url.spec()); 401 } 402} 403 404static const wchar_t* jscript_feed_title = 405 L"window.domAutomationController.send(" 406 L" document.getElementById('title') ? " 407 L" document.getElementById('title').textContent : " 408 L" \"element 'title' not found\"" 409 L");"; 410static const wchar_t* jscript_anchor = 411 L"window.domAutomationController.send(" 412 L" document.getElementById('anchor_0') ? " 413 L" document.getElementById('anchor_0').textContent : " 414 L" \"element 'anchor_0' not found\"" 415 L");"; 416static const wchar_t* jscript_desc = 417 L"window.domAutomationController.send(" 418 L" document.getElementById('desc_0') ? " 419 L" document.getElementById('desc_0').textContent : " 420 L" \"element 'desc_0' not found\"" 421 L");"; 422static const wchar_t* jscript_error = 423 L"window.domAutomationController.send(" 424 L" document.getElementById('error') ? " 425 L" document.getElementById('error').textContent : " 426 L" \"No error\"" 427 L");"; 428 429bool ValidatePageElement(TabContents* tab, 430 const std::wstring& frame, 431 const std::wstring& javascript, 432 const std::string& expected_value) { 433 std::string returned_value; 434 std::string error; 435 436 if (!ui_test_utils::ExecuteJavaScriptAndExtractString( 437 tab->render_view_host(), 438 frame, 439 javascript, &returned_value)) 440 return false; 441 442 EXPECT_STREQ(expected_value.c_str(), returned_value.c_str()); 443 return expected_value == returned_value; 444} 445 446// Navigates to a feed page and, if |sniff_xml_type| is set, wait for the 447// extension to kick in, detect the feed and redirect to a feed preview page. 448// |sniff_xml_type| is generally set to true if the feed is sniffable and false 449// for invalid feeds. 450void NavigateToFeedAndValidate(net::TestServer* server, 451 const std::string& url, 452 Browser* browser, 453 bool sniff_xml_type, 454 const std::string& expected_feed_title, 455 const std::string& expected_item_title, 456 const std::string& expected_item_desc, 457 const std::string& expected_error) { 458 if (sniff_xml_type) { 459 // TODO(finnur): Implement this is a non-flaky way. 460 } 461 462 ExtensionService* service = browser->profile()->GetExtensionService(); 463 const Extension* extension = service->extensions()->back(); 464 std::string id = extension->id(); 465 466 // Navigate to the subscribe page directly. 467 ui_test_utils::NavigateToURL(browser, GetFeedUrl(server, url, true, id)); 468 469 TabContents* tab = browser->GetSelectedTabContents(); 470 ASSERT_TRUE(ValidatePageElement(tab, 471 L"", 472 jscript_feed_title, 473 expected_feed_title)); 474 ASSERT_TRUE(ValidatePageElement(tab, 475 L"//html/body/div/iframe[1]", 476 jscript_anchor, 477 expected_item_title)); 478 ASSERT_TRUE(ValidatePageElement(tab, 479 L"//html/body/div/iframe[1]", 480 jscript_desc, 481 expected_item_desc)); 482 ASSERT_TRUE(ValidatePageElement(tab, 483 L"//html/body/div/iframe[1]", 484 jscript_error, 485 expected_error)); 486} 487 488IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed1) { 489 ASSERT_TRUE(test_server()->Start()); 490 491 ASSERT_TRUE(LoadExtension( 492 test_data_dir_.AppendASCII("subscribe_page_action"))); 493 494 NavigateToFeedAndValidate(test_server(), kValidFeed1, browser(), true, 495 "Feed for MyFeedTitle", 496 "Title 1", 497 "Desc", 498 "No error"); 499} 500 501IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed2) { 502 ASSERT_TRUE(test_server()->Start()); 503 504 ASSERT_TRUE(LoadExtension( 505 test_data_dir_.AppendASCII("subscribe_page_action"))); 506 507 NavigateToFeedAndValidate(test_server(), kValidFeed2, browser(), true, 508 "Feed for MyFeed2", 509 "My item title1", 510 "This is a summary.", 511 "No error"); 512} 513 514IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed3) { 515 ASSERT_TRUE(test_server()->Start()); 516 517 ASSERT_TRUE(LoadExtension( 518 test_data_dir_.AppendASCII("subscribe_page_action"))); 519 520 NavigateToFeedAndValidate(test_server(), kValidFeed3, browser(), true, 521 "Feed for Google Code buglist rss feed", 522 "My dear title", 523 "My dear content", 524 "No error"); 525} 526 527IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed4) { 528 ASSERT_TRUE(test_server()->Start()); 529 530 ASSERT_TRUE(LoadExtension( 531 test_data_dir_.AppendASCII("subscribe_page_action"))); 532 533 NavigateToFeedAndValidate(test_server(), kValidFeed4, browser(), true, 534 "Feed for Title chars <script> %23 stop", 535 "Title chars %23 stop", 536 "My dear content %23 stop", 537 "No error"); 538} 539 540IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed0) { 541 ASSERT_TRUE(test_server()->Start()); 542 543 ASSERT_TRUE(LoadExtension( 544 test_data_dir_.AppendASCII("subscribe_page_action"))); 545 546 // Try a feed with a link with an onclick handler (before r27440 this would 547 // trigger a NOTREACHED). 548 NavigateToFeedAndValidate(test_server(), kValidFeed0, browser(), true, 549 "Feed for MyFeedTitle", 550 "Title 1", 551 "Desc VIDEO", 552 "No error"); 553} 554 555IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed5) { 556 ASSERT_TRUE(test_server()->Start()); 557 558 ASSERT_TRUE(LoadExtension( 559 test_data_dir_.AppendASCII("subscribe_page_action"))); 560 561 // Feed with valid but mostly empty xml. 562 NavigateToFeedAndValidate(test_server(), kValidFeed5, browser(), true, 563 "Feed for Unknown feed name", 564 "element 'anchor_0' not found", 565 "element 'desc_0' not found", 566 "This feed contains no entries."); 567} 568 569IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeed6) { 570 ASSERT_TRUE(test_server()->Start()); 571 572 ASSERT_TRUE(LoadExtension( 573 test_data_dir_.AppendASCII("subscribe_page_action"))); 574 575 // Feed that is technically invalid but still parseable. 576 NavigateToFeedAndValidate(test_server(), kValidFeed6, browser(), true, 577 "Feed for MyFeedTitle", 578 "Title 1", 579 "Desc", 580 "No error"); 581} 582 583IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedInvalidFeed1) { 584 ASSERT_TRUE(test_server()->Start()); 585 586 ASSERT_TRUE(LoadExtension( 587 test_data_dir_.AppendASCII("subscribe_page_action"))); 588 589 // Try an empty feed. 590 NavigateToFeedAndValidate(test_server(), kInvalidFeed1, browser(), false, 591 "Feed for Unknown feed name", 592 "element 'anchor_0' not found", 593 "element 'desc_0' not found", 594 "This feed contains no entries."); 595} 596 597IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedInvalidFeed2) { 598 ASSERT_TRUE(test_server()->Start()); 599 600 ASSERT_TRUE(LoadExtension( 601 test_data_dir_.AppendASCII("subscribe_page_action"))); 602 603 // Try a garbage feed. 604 NavigateToFeedAndValidate(test_server(), kInvalidFeed2, browser(), false, 605 "Feed for Unknown feed name", 606 "element 'anchor_0' not found", 607 "element 'desc_0' not found", 608 "This feed contains no entries."); 609} 610 611IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedInvalidFeed3) { 612 ASSERT_TRUE(test_server()->Start()); 613 614 ASSERT_TRUE(LoadExtension( 615 test_data_dir_.AppendASCII("subscribe_page_action"))); 616 617 // Try a feed that doesn't exist. 618 NavigateToFeedAndValidate(test_server(), "foo.xml", browser(), false, 619 "Feed for Unknown feed name", 620 "element 'anchor_0' not found", 621 "element 'desc_0' not found", 622 "This feed contains no entries."); 623} 624 625IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, ParseFeedValidFeedNoLinks) { 626 ASSERT_TRUE(test_server()->Start()); 627 628 ASSERT_TRUE(LoadExtension( 629 test_data_dir_.AppendASCII("subscribe_page_action"))); 630 631 // Valid feed but containing no links. 632 NavigateToFeedAndValidate(test_server(), kValidFeedNoLinks, browser(), true, 633 "Feed for MyFeedTitle", 634 "Title with no link", 635 "Desc", 636 "No error"); 637} 638 639// Tests that an error raised during an async function still fires 640// the callback, but sets chrome.extension.lastError. 641IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, LastError) { 642 ASSERT_TRUE(LoadExtension( 643 test_data_dir_.AppendASCII("browsertest").AppendASCII("last_error"))); 644 645 // Get the ExtensionHost that is hosting our toolstrip page. 646 ExtensionProcessManager* manager = 647 browser()->profile()->GetExtensionProcessManager(); 648 ExtensionHost* host = FindHostWithPath(manager, "/bg.html", 1); 649 650 bool result = false; 651 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 652 host->render_view_host(), L"", L"testLastError()", &result)); 653 EXPECT_TRUE(result); 654} 655 656// Helper function for common code shared by the 3 WindowOpen tests below. 657static void WindowOpenHelper(Browser* browser, const GURL& start_url, 658 const std::string& newtab_url, 659 TabContents** newtab_result) { 660 ui_test_utils::NavigateToURL(browser, start_url); 661 662 ASSERT_TRUE(ui_test_utils::ExecuteJavaScript( 663 browser->GetSelectedTabContents()->render_view_host(), L"", 664 L"window.open('" + UTF8ToWide(newtab_url) + L"');")); 665 666 // Now the active tab in last active window should be the new tab. 667 Browser* last_active_browser = BrowserList::GetLastActive(); 668 EXPECT_TRUE(last_active_browser); 669 TabContents* newtab = last_active_browser->GetSelectedTabContents(); 670 EXPECT_TRUE(newtab); 671 GURL expected_url = start_url.Resolve(newtab_url); 672 if (!newtab->controller().GetLastCommittedEntry() || 673 newtab->controller().GetLastCommittedEntry()->url() != expected_url) 674 ui_test_utils::WaitForNavigation(&newtab->controller()); 675 EXPECT_EQ(expected_url, 676 newtab->controller().GetLastCommittedEntry()->url()); 677 if (newtab_result) 678 *newtab_result = newtab; 679} 680 681// Tests that an extension page can call window.open to an extension URL and 682// the new window has extension privileges. 683IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, WindowOpenExtension) { 684 ASSERT_TRUE(LoadExtension( 685 test_data_dir_.AppendASCII("uitest").AppendASCII("window_open"))); 686 687 TabContents* newtab; 688 ASSERT_NO_FATAL_FAILURE(WindowOpenHelper( 689 browser(), 690 GURL(std::string("chrome-extension://") + last_loaded_extension_id_ + 691 "/test.html"), 692 "newtab.html", &newtab)); 693 694 bool result = false; 695 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 696 newtab->render_view_host(), L"", L"testExtensionApi()", &result)); 697 EXPECT_TRUE(result); 698} 699 700// Tests that if an extension page calls window.open to an invalid extension 701// URL, the browser doesn't crash. 702IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, WindowOpenInvalidExtension) { 703 ASSERT_TRUE(LoadExtension( 704 test_data_dir_.AppendASCII("uitest").AppendASCII("window_open"))); 705 706 ASSERT_NO_FATAL_FAILURE(WindowOpenHelper( 707 browser(), 708 GURL(std::string("chrome-extension://") + last_loaded_extension_id_ + 709 "/test.html"), 710 "chrome-extension://thisissurelynotavalidextensionid/newtab.html", NULL)); 711 712 // If we got to this point, we didn't crash, so we're good. 713} 714 715// Tests that calling window.open from the newtab page to an extension URL 716// gives the new window extension privileges - even though the opening page 717// does not have extension privileges, we break the script connection, so 718// there is no privilege leak. 719IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, WindowOpenNoPrivileges) { 720 ASSERT_TRUE(LoadExtension( 721 test_data_dir_.AppendASCII("uitest").AppendASCII("window_open"))); 722 723 TabContents* newtab; 724 ASSERT_NO_FATAL_FAILURE(WindowOpenHelper( 725 browser(), 726 GURL("about:blank"), 727 std::string("chrome-extension://") + last_loaded_extension_id_ + 728 "/newtab.html", 729 &newtab)); 730 731 // Extension API should succeed. 732 bool result = false; 733 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 734 newtab->render_view_host(), L"", L"testExtensionApi()", &result)); 735 EXPECT_TRUE(result); 736} 737 738#if defined(OS_WIN) 739#define MAYBE_PluginLoadUnload PluginLoadUnload 740#elif defined(OS_LINUX) 741// http://crbug.com/47598 742#define MAYBE_PluginLoadUnload DISABLED_PluginLoadUnload 743#else 744// TODO(mpcomplete): http://crbug.com/29900 need cross platform plugin support. 745#define MAYBE_PluginLoadUnload DISABLED_PluginLoadUnload 746#endif 747 748// Tests that a renderer's plugin list is properly updated when we load and 749// unload an extension that contains a plugin. 750IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, MAYBE_PluginLoadUnload) { 751 FilePath extension_dir = 752 test_data_dir_.AppendASCII("uitest").AppendASCII("plugins"); 753 754 ui_test_utils::NavigateToURL(browser(), 755 net::FilePathToFileURL(extension_dir.AppendASCII("test.html"))); 756 TabContents* tab = browser()->GetSelectedTabContents(); 757 758 // With no extensions, the plugin should not be loaded. 759 bool result = false; 760 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 761 tab->render_view_host(), L"", L"testPluginWorks()", &result)); 762 EXPECT_FALSE(result); 763 764 ExtensionService* service = browser()->profile()->GetExtensionService(); 765 const size_t size_before = service->extensions()->size(); 766 ASSERT_TRUE(LoadExtension(extension_dir)); 767 EXPECT_EQ(size_before + 1, service->extensions()->size()); 768 // Now the plugin should be in the cache, but we have to reload the page for 769 // it to work. 770 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 771 tab->render_view_host(), L"", L"testPluginWorks()", &result)); 772 EXPECT_FALSE(result); 773 browser()->Reload(CURRENT_TAB); 774 ui_test_utils::WaitForNavigationInCurrentTab(browser()); 775 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 776 tab->render_view_host(), L"", L"testPluginWorks()", &result)); 777 EXPECT_TRUE(result); 778 779 EXPECT_EQ(size_before + 1, service->extensions()->size()); 780 UnloadExtension(service->extensions()->at(size_before)->id()); 781 EXPECT_EQ(size_before, service->extensions()->size()); 782 783 // Now the plugin should be unloaded, and the page should be broken. 784 785 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 786 tab->render_view_host(), L"", L"testPluginWorks()", &result)); 787 EXPECT_FALSE(result); 788 789 // If we reload the extension and page, it should work again. 790 791 ASSERT_TRUE(LoadExtension(extension_dir)); 792 EXPECT_EQ(size_before + 1, service->extensions()->size()); 793 browser()->Reload(CURRENT_TAB); 794 ui_test_utils::WaitForNavigationInCurrentTab(browser()); 795 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractBool( 796 tab->render_view_host(), L"", L"testPluginWorks()", &result)); 797 EXPECT_TRUE(result); 798} 799 800// Used to simulate a click on the first button named 'Options'. 801static const wchar_t* jscript_click_option_button = 802 L"(function() { " 803 L" var button = document.evaluate(\"//button[text()='Options']\"," 804 L" document, null, XPathResult.UNORDERED_NODE_SNAPSHOT_TYPE," 805 L" null).snapshotItem(0);" 806 L" button.click();" 807 L"})();"; 808 809// Test that an extension with an options page makes an 'Options' button appear 810// on chrome://extensions, and that clicking the button opens a new tab with the 811// extension's options page. 812// Disabled. See http://crbug.com/26948 for details. 813IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, DISABLED_OptionsPage) { 814 // Install an extension with an options page. 815 ASSERT_TRUE(InstallExtension(test_data_dir_.AppendASCII("options.crx"), 1)); 816 ExtensionService* service = browser()->profile()->GetExtensionService(); 817 const ExtensionList* extensions = service->extensions(); 818 ASSERT_EQ(1u, extensions->size()); 819 const Extension* extension = extensions->at(0); 820 821 // Go to the chrome://extensions page and click the Options button. 822 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIExtensionsURL)); 823 TabStripModel* tab_strip = browser()->tabstrip_model(); 824 ASSERT_TRUE(ui_test_utils::ExecuteJavaScript( 825 browser()->GetSelectedTabContents()->render_view_host(), L"", 826 jscript_click_option_button)); 827 828 // If the options page hasn't already come up, wait for it. 829 if (tab_strip->count() == 1) { 830 ui_test_utils::WaitForNewTab(browser()); 831 } 832 ASSERT_EQ(2, tab_strip->count()); 833 834 EXPECT_EQ(extension->GetResourceURL("options.html"), 835 tab_strip->GetTabContentsAt(1)->tab_contents()->GetURL()); 836} 837 838// Test window.chrome.app.isInstalled . 839IN_PROC_BROWSER_TEST_F(ExtensionBrowserTest, PropertyAppIsInstalled) { 840 std::string app_host("app.com"); 841 std::string nonapp_host("nonapp.com"); 842 843 host_resolver()->AddRule(app_host, "127.0.0.1"); 844 host_resolver()->AddRule(nonapp_host, "127.0.0.1"); 845 ASSERT_TRUE(test_server()->Start()); 846 847 GURL test_file_url(test_server()->GetURL("extensions/test_file.html")); 848 GURL::Replacements replace_host; 849 850 replace_host.SetHostStr(app_host); 851 GURL app_url(test_file_url.ReplaceComponents(replace_host)); 852 853 replace_host.SetHostStr(nonapp_host); 854 GURL non_app_url(test_file_url.ReplaceComponents(replace_host)); 855 856 857 // Load an app which includes app.com in its extent. 858 ASSERT_TRUE(LoadExtension( 859 test_data_dir_.AppendASCII("app_dot_com_app"))); 860 861 862 // Test that a non-app page has chrome.app.isInstalled = false. 863 ui_test_utils::NavigateToURL(browser(), non_app_url); 864 std::wstring get_app_is_installed = 865 L"window.domAutomationController.send(" 866 L" JSON.stringify(window.chrome.app.isInstalled));"; 867 std::string result; 868 ASSERT_TRUE( 869 ui_test_utils::ExecuteJavaScriptAndExtractString( 870 browser()->GetSelectedTabContents()->render_view_host(), 871 L"", 872 get_app_is_installed.c_str(), 873 &result)); 874 EXPECT_EQ("false", result); 875 876 877 // Check that an app page has chrome.app.isInstalled = true. 878 ui_test_utils::NavigateToURL(browser(), app_url); 879 ASSERT_TRUE( 880 ui_test_utils::ExecuteJavaScriptAndExtractString( 881 browser()->GetSelectedTabContents()->render_view_host(), 882 L"", 883 get_app_is_installed.c_str(), 884 &result)); 885 EXPECT_EQ("true", result); 886 887 888 // Test that trying to set window.chrome.app.isInstalled throws 889 // an exception. 890 ASSERT_TRUE(ui_test_utils::ExecuteJavaScriptAndExtractString( 891 browser()->GetSelectedTabContents()->render_view_host(), 892 L"", 893 L"window.domAutomationController.send(" 894 L" function() {" 895 L" try {" 896 L" window.chrome.app.isInstalled = false;" 897 L" return 'BAD: Should have thrown by now...';" 898 L" } catch (e) {" 899 L" return 'GOOD: Saw expected error.';" 900 L" }" 901 L" }()" 902 L");", 903 &result)); 904 EXPECT_EQ("GOOD: Saw expected error.", result); 905} 906