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 #include "base/command_line.h" 6 #include "base/files/file_path.h" 7 #include "base/strings/utf_string_conversions.h" 8 #include "chrome/browser/bookmarks/bookmark_model.h" 9 #include "chrome/browser/bookmarks/bookmark_model_factory.h" 10 #include "chrome/browser/bookmarks/bookmark_test_helpers.h" 11 #include "chrome/browser/bookmarks/bookmark_utils.h" 12 #include "chrome/browser/chrome_notification_types.h" 13 #include "chrome/browser/extensions/browser_action_test_util.h" 14 #include "chrome/browser/extensions/extension_apitest.h" 15 #include "chrome/browser/extensions/extension_host.h" 16 #include "chrome/browser/extensions/extension_service.h" 17 #include "chrome/browser/extensions/extension_system.h" 18 #include "chrome/browser/extensions/extension_test_message_listener.h" 19 #include "chrome/browser/extensions/lazy_background_page_test_util.h" 20 #include "chrome/browser/profiles/profile.h" 21 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h" 22 #include "chrome/browser/ui/browser.h" 23 #include "chrome/browser/ui/browser_window.h" 24 #include "chrome/browser/ui/omnibox/location_bar.h" 25 #include "chrome/browser/ui/tabs/tab_strip_model.h" 26 #include "chrome/common/url_constants.h" 27 #include "chrome/test/base/ui_test_utils.h" 28 #include "content/public/browser/notification_service.h" 29 #include "content/public/browser/web_contents.h" 30 #include "content/public/test/browser_test_utils.h" 31 #include "extensions/common/extension.h" 32 #include "extensions/common/switches.h" 33 #include "net/dns/mock_host_resolver.h" 34 #include "net/test/embedded_test_server/embedded_test_server.h" 35 #include "url/gurl.h" 36 37 using extensions::Extension; 38 39 namespace { 40 41 // This unfortunate bit of silliness is necessary when loading an extension in 42 // incognito. The goal is to load the extension, enable incognito, then wait 43 // for both background pages to load and close. The problem is that enabling 44 // incognito involves reloading the extension - and the background pages may 45 // have already loaded once before then. So we wait until the extension is 46 // unloaded before listening to the background page notifications. 47 class LoadedIncognitoObserver : public content::NotificationObserver { 48 public: 49 explicit LoadedIncognitoObserver(Profile* profile) : profile_(profile) { 50 registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED, 51 content::Source<Profile>(profile)); 52 } 53 54 void Wait() { 55 ASSERT_TRUE(original_complete_.get()); 56 original_complete_->Wait(); 57 incognito_complete_->Wait(); 58 } 59 60 private: 61 62 virtual void Observe( 63 int type, 64 const content::NotificationSource& source, 65 const content::NotificationDetails& details) OVERRIDE { 66 original_complete_.reset(new LazyBackgroundObserver(profile_)); 67 incognito_complete_.reset( 68 new LazyBackgroundObserver(profile_->GetOffTheRecordProfile())); 69 } 70 71 Profile* profile_; 72 content::NotificationRegistrar registrar_; 73 scoped_ptr<LazyBackgroundObserver> original_complete_; 74 scoped_ptr<LazyBackgroundObserver> incognito_complete_; 75 }; 76 77 } // namespace 78 79 class LazyBackgroundPageApiTest : public ExtensionApiTest { 80 public: 81 LazyBackgroundPageApiTest() {} 82 virtual ~LazyBackgroundPageApiTest() {} 83 84 virtual void SetUpCommandLine(CommandLine* command_line) OVERRIDE { 85 ExtensionApiTest::SetUpCommandLine(command_line); 86 // Set shorter delays to prevent test timeouts. 87 command_line->AppendSwitchASCII( 88 extensions::switches::kEventPageIdleTime, "1000"); 89 command_line->AppendSwitchASCII( 90 extensions::switches::kEventPageSuspendingTime, "1000"); 91 } 92 93 // Loads the extension, which temporarily starts the lazy background page 94 // to dispatch the onInstalled event. We wait until it shuts down again. 95 const Extension* LoadExtensionAndWait(const std::string& test_name) { 96 LazyBackgroundObserver page_complete; 97 base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). 98 AppendASCII(test_name); 99 const Extension* extension = LoadExtension(extdir); 100 if (extension) 101 page_complete.Wait(); 102 return extension; 103 } 104 105 // Returns true if the lazy background page for the extension with 106 // |extension_id| is still running. 107 bool IsBackgroundPageAlive(const std::string& extension_id) { 108 extensions::ProcessManager* pm = extensions::ExtensionSystem::Get( 109 browser()->profile())->process_manager(); 110 return pm->GetBackgroundHostForExtension(extension_id); 111 } 112 113 private: 114 DISALLOW_COPY_AND_ASSIGN(LazyBackgroundPageApiTest); 115 }; 116 117 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, BrowserActionCreateTab) { 118 ASSERT_TRUE(LoadExtensionAndWait("browser_action_create_tab")); 119 120 // Lazy Background Page doesn't exist yet. 121 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 122 int num_tabs_before = browser()->tab_strip_model()->count(); 123 124 // Observe background page being created and closed after 125 // the browser action is clicked. 126 LazyBackgroundObserver page_complete; 127 BrowserActionTestUtil(browser()).Press(0); 128 page_complete.Wait(); 129 130 // Background page created a new tab before it closed. 131 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 132 EXPECT_EQ(num_tabs_before + 1, browser()->tab_strip_model()->count()); 133 EXPECT_EQ(std::string(chrome::kChromeUIExtensionsURL), 134 browser()->tab_strip_model()->GetActiveWebContents()-> 135 GetURL().spec()); 136 } 137 138 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, 139 BrowserActionCreateTabAfterCallback) { 140 ASSERT_TRUE(LoadExtensionAndWait("browser_action_with_callback")); 141 142 // Lazy Background Page doesn't exist yet. 143 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 144 int num_tabs_before = browser()->tab_strip_model()->count(); 145 146 // Observe background page being created and closed after 147 // the browser action is clicked. 148 LazyBackgroundObserver page_complete; 149 BrowserActionTestUtil(browser()).Press(0); 150 page_complete.Wait(); 151 152 // Background page is closed after creating a new tab. 153 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 154 EXPECT_EQ(num_tabs_before + 1, browser()->tab_strip_model()->count()); 155 } 156 157 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, BroadcastEvent) { 158 ASSERT_TRUE(StartEmbeddedTestServer()); 159 160 const Extension* extension = LoadExtensionAndWait("broadcast_event"); 161 ASSERT_TRUE(extension); 162 163 // Lazy Background Page doesn't exist yet. 164 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 165 int num_page_actions = browser()->window()->GetLocationBar()-> 166 GetLocationBarForTesting()->PageActionVisibleCount(); 167 168 // Open a tab to a URL that will trigger the page action to show. 169 LazyBackgroundObserver page_complete; 170 content::WindowedNotificationObserver page_action_changed( 171 chrome::NOTIFICATION_EXTENSION_PAGE_ACTION_VISIBILITY_CHANGED, 172 content::NotificationService::AllSources()); 173 ui_test_utils::NavigateToURL( 174 browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); 175 page_complete.Wait(); 176 177 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 178 179 // Page action is shown. 180 page_action_changed.Wait(); 181 EXPECT_EQ(num_page_actions + 1, 182 browser()->window()->GetLocationBar()-> 183 GetLocationBarForTesting()->PageActionVisibleCount()); 184 } 185 186 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, Filters) { 187 ASSERT_TRUE(StartEmbeddedTestServer()); 188 189 const Extension* extension = LoadExtensionAndWait("filters"); 190 ASSERT_TRUE(extension); 191 192 // Lazy Background Page doesn't exist yet. 193 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 194 195 // Open a tab to a URL that will fire a webNavigation event. 196 LazyBackgroundObserver page_complete; 197 ui_test_utils::NavigateToURL( 198 browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); 199 page_complete.Wait(); 200 } 201 202 // Tests that the lazy background page receives the onInstalled event and shuts 203 // down. 204 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, OnInstalled) { 205 ResultCatcher catcher; 206 ASSERT_TRUE(LoadExtensionAndWait("on_installed")); 207 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 208 209 // Lazy Background Page has been shut down. 210 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 211 } 212 213 // Tests that a JavaScript alert keeps the lazy background page alive. 214 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, WaitForDialog) { 215 LazyBackgroundObserver background_observer; 216 base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). 217 AppendASCII("wait_for_dialog"); 218 const Extension* extension = LoadExtension(extdir); 219 ASSERT_TRUE(extension); 220 221 // The test extension opens a dialog on installation. 222 AppModalDialog* dialog = ui_test_utils::WaitForAppModalDialog(); 223 ASSERT_TRUE(dialog); 224 225 // With the dialog open the background page is still alive. 226 EXPECT_TRUE(IsBackgroundPageAlive(extension->id())); 227 228 // Close the dialog. The keep alive count is decremented. 229 extensions::ProcessManager* pm = 230 extensions::ExtensionSystem::Get(browser()->profile())->process_manager(); 231 int previous_keep_alive_count = pm->GetLazyKeepaliveCount(extension); 232 dialog->CloseModalDialog(); 233 EXPECT_EQ(previous_keep_alive_count - 1, 234 pm->GetLazyKeepaliveCount(extension)); 235 236 // The background page closes now that the dialog is gone. 237 background_observer.WaitUntilClosed(); 238 EXPECT_FALSE(IsBackgroundPageAlive(extension->id())); 239 } 240 241 // Tests that the lazy background page stays alive until all visible views are 242 // closed. 243 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, WaitForView) { 244 LazyBackgroundObserver page_complete; 245 ResultCatcher catcher; 246 base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). 247 AppendASCII("wait_for_view"); 248 const Extension* extension = LoadExtension(extdir); 249 ASSERT_TRUE(extension); 250 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 251 252 // The extension should've opened a new tab to an extension page. 253 EXPECT_EQ(extension->GetResourceURL("extension_page.html").spec(), 254 browser()->tab_strip_model()->GetActiveWebContents()-> 255 GetURL().spec()); 256 257 // Lazy Background Page still exists, because the extension created a new tab 258 // to an extension page. 259 EXPECT_TRUE(IsBackgroundPageAlive(last_loaded_extension_id())); 260 261 // Close the new tab. 262 browser()->tab_strip_model()->CloseWebContentsAt( 263 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE); 264 page_complete.Wait(); 265 266 // Lazy Background Page has been shut down. 267 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 268 } 269 270 // Tests that the lazy background page stays alive until all network requests 271 // are complete. 272 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, WaitForRequest) { 273 host_resolver()->AddRule("*", "127.0.0.1"); 274 ASSERT_TRUE(StartEmbeddedTestServer()); 275 276 LazyBackgroundObserver page_complete; 277 ResultCatcher catcher; 278 base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). 279 AppendASCII("wait_for_request"); 280 const Extension* extension = LoadExtension(extdir); 281 ASSERT_TRUE(extension); 282 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 283 284 // Lazy Background Page still exists, because the extension started a request. 285 extensions::ProcessManager* pm = 286 extensions::ExtensionSystem::Get(browser()->profile())->process_manager(); 287 extensions::ExtensionHost* host = 288 pm->GetBackgroundHostForExtension(last_loaded_extension_id()); 289 ASSERT_TRUE(host); 290 291 // Abort the request. 292 bool result = false; 293 EXPECT_TRUE(content::ExecuteScriptAndExtractBool( 294 host->render_view_host(), "abortRequest()", &result)); 295 EXPECT_TRUE(result); 296 page_complete.Wait(); 297 298 // Lazy Background Page has been shut down. 299 EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id())); 300 } 301 302 // Tests that the lazy background page stays alive until all visible views are 303 // closed. 304 // http://crbug.com/175778; test fails frequently on OS X 305 #if defined(OS_MACOSX) 306 #define MAYBE_WaitForNTP DISABLED_WaitForNTP 307 #else 308 #define MAYBE_WaitForNTP WaitForNTP 309 #endif 310 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, MAYBE_WaitForNTP) { 311 LazyBackgroundObserver lazybg; 312 ResultCatcher catcher; 313 base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). 314 AppendASCII("wait_for_ntp"); 315 const Extension* extension = LoadExtension(extdir); 316 ASSERT_TRUE(extension); 317 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 318 319 // The extension should've opened a new tab to an extension page. 320 EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), 321 browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); 322 323 // Lazy Background Page still exists, because the extension created a new tab 324 // to an extension page. 325 EXPECT_TRUE(IsBackgroundPageAlive(last_loaded_extension_id())); 326 327 // Navigate away from the NTP, which should close the event page. 328 ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); 329 lazybg.Wait(); 330 331 // Lazy Background Page has been shut down. 332 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 333 } 334 335 // See crbug.com/248437 336 #if defined(OS_WIN) 337 #define MAYBE_IncognitoSplitMode DISABLED_IncognitoSplitMode 338 #else 339 #define MAYBE_IncognitoSplitMode IncognitoSplitMode 340 #endif 341 342 // Tests that an incognito split mode extension gets 2 lazy background pages, 343 // and they each load and unload at the proper times. 344 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, MAYBE_IncognitoSplitMode) { 345 // Open incognito window. 346 Browser* incognito_browser = ui_test_utils::OpenURLOffTheRecord( 347 browser()->profile(), GURL("about:blank")); 348 349 // Load the extension with incognito enabled. 350 { 351 LoadedIncognitoObserver loaded(browser()->profile()); 352 base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). 353 AppendASCII("incognito_split"); 354 ASSERT_TRUE(LoadExtensionIncognito(extdir)); 355 loaded.Wait(); 356 } 357 358 // Lazy Background Page doesn't exist yet. 359 extensions::ProcessManager* pm = 360 extensions::ExtensionSystem::Get(browser()->profile())->process_manager(); 361 extensions::ProcessManager* pmi = 362 extensions::ExtensionSystem::Get(incognito_browser->profile())-> 363 process_manager(); 364 EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id())); 365 EXPECT_FALSE(pmi->GetBackgroundHostForExtension(last_loaded_extension_id())); 366 367 // Trigger a browserAction event in the original profile and ensure only 368 // the original event page received it (since the event is scoped to the 369 // profile). 370 { 371 ExtensionTestMessageListener listener("waiting", false); 372 ExtensionTestMessageListener listener_incognito("waiting_incognito", false); 373 374 LazyBackgroundObserver page_complete(browser()->profile()); 375 BrowserActionTestUtil(browser()).Press(0); 376 page_complete.Wait(); 377 378 // Only the original event page received the message. 379 EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id())); 380 EXPECT_FALSE( 381 pmi->GetBackgroundHostForExtension(last_loaded_extension_id())); 382 EXPECT_TRUE(listener.was_satisfied()); 383 EXPECT_FALSE(listener_incognito.was_satisfied()); 384 } 385 386 // Trigger a bookmark created event and ensure both pages receive it. 387 { 388 ExtensionTestMessageListener listener("waiting", false); 389 ExtensionTestMessageListener listener_incognito("waiting_incognito", false); 390 391 LazyBackgroundObserver page_complete(browser()->profile()), 392 page2_complete(incognito_browser->profile()); 393 BookmarkModel* bookmark_model = 394 BookmarkModelFactory::GetForProfile(browser()->profile()); 395 test::WaitForBookmarkModelToLoad(bookmark_model); 396 const BookmarkNode* parent = bookmark_model->bookmark_bar_node(); 397 bookmark_model->AddURL( 398 parent, 0, ASCIIToUTF16("Title"), GURL("about:blank")); 399 page_complete.Wait(); 400 page2_complete.Wait(); 401 402 // Both pages received the message. 403 EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id())); 404 EXPECT_FALSE( 405 pmi->GetBackgroundHostForExtension(last_loaded_extension_id())); 406 EXPECT_TRUE(listener.was_satisfied()); 407 EXPECT_TRUE(listener_incognito.was_satisfied()); 408 } 409 } 410 411 // Tests that messages from the content script activate the lazy background 412 // page, and keep it alive until all channels are closed. 413 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, Messaging) { 414 ASSERT_TRUE(StartEmbeddedTestServer()); 415 ASSERT_TRUE(LoadExtensionAndWait("messaging")); 416 417 // Lazy Background Page doesn't exist yet. 418 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 419 EXPECT_EQ(1, browser()->tab_strip_model()->count()); 420 421 // Navigate to a page that opens a message channel to the background page. 422 ResultCatcher catcher; 423 LazyBackgroundObserver lazybg; 424 ui_test_utils::NavigateToURL( 425 browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); 426 lazybg.WaitUntilLoaded(); 427 428 // Background page got the content script's message and is still loaded 429 // until we close the channel. 430 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 431 EXPECT_TRUE(IsBackgroundPageAlive(last_loaded_extension_id())); 432 433 // Navigate away, closing the message channel and therefore the background 434 // page. 435 ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); 436 lazybg.WaitUntilClosed(); 437 438 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 439 } 440 441 // Tests that a KeepaliveImpulse increments the keep alive count, but eventually 442 // times out and background page will still close. 443 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, ImpulseAddsCount) { 444 ASSERT_TRUE(StartEmbeddedTestServer()); 445 const Extension* extension = LoadExtensionAndWait("messaging"); 446 ASSERT_TRUE(extension); 447 448 // Lazy Background Page doesn't exist yet. 449 extensions::ProcessManager* pm = 450 extensions::ExtensionSystem::Get(browser()->profile())->process_manager(); 451 EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id())); 452 EXPECT_EQ(1, browser()->tab_strip_model()->count()); 453 454 // Navigate to a page that opens a message channel to the background page. 455 ResultCatcher catcher; 456 LazyBackgroundObserver lazybg; 457 ui_test_utils::NavigateToURL( 458 browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); 459 lazybg.WaitUntilLoaded(); 460 461 // Add an impulse and the keep alive count increases. 462 int previous_keep_alive_count = pm->GetLazyKeepaliveCount(extension); 463 pm->KeepaliveImpulse(extension); 464 EXPECT_EQ(previous_keep_alive_count + 1, 465 pm->GetLazyKeepaliveCount(extension)); 466 467 // Navigate away, closing the message channel and therefore the background 468 // page after the impulse times out. 469 ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); 470 lazybg.WaitUntilClosed(); 471 472 EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id())); 473 } 474 475 // Tests that the lazy background page receives the unload event when we 476 // close it, and that it can execute simple API calls that don't require an 477 // asynchronous response. 478 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, OnUnload) { 479 ASSERT_TRUE(LoadExtensionAndWait("on_unload")); 480 481 // Lazy Background Page has been shut down. 482 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 483 484 // The browser action has a new title. 485 BrowserActionTestUtil browser_action(browser()); 486 ASSERT_EQ(1, browser_action.NumberOfBrowserActions()); 487 EXPECT_EQ("Success", browser_action.GetTooltip(0)); 488 } 489 490 // Tests that both a regular page and an event page will receive events when 491 // the event page is not loaded. 492 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, EventDispatchToTab) { 493 ResultCatcher catcher; 494 catcher.RestrictToProfile(browser()->profile()); 495 496 const extensions::Extension* extension = 497 LoadExtensionAndWait("event_dispatch_to_tab"); 498 499 ExtensionTestMessageListener page_ready("ready", true); 500 GURL page_url = extension->GetResourceURL("page.html"); 501 ui_test_utils::NavigateToURL(browser(), page_url); 502 EXPECT_TRUE(page_ready.WaitUntilSatisfied()); 503 504 // After the event is sent below, wait for the event page to have received 505 // the event before proceeding with the test. This allows the regular page 506 // to test that the event page received the event, which makes the pass/fail 507 // logic simpler. 508 ExtensionTestMessageListener event_page_ready("ready", true); 509 510 // Send an event by making a bookmark. 511 BookmarkModel* bookmark_model = 512 BookmarkModelFactory::GetForProfile(browser()->profile()); 513 test::WaitForBookmarkModelToLoad(bookmark_model); 514 bookmark_utils::AddIfNotBookmarked( 515 bookmark_model, GURL("http://www.google.com"), UTF8ToUTF16("Google")); 516 517 EXPECT_TRUE(event_page_ready.WaitUntilSatisfied()); 518 519 page_ready.Reply("go"); 520 521 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 522 } 523 524 // Tests that the lazy background page updates the chrome://extensions page 525 // when it is destroyed. 526 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, UpdateExtensionsPage) { 527 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIExtensionsURL)); 528 529 ResultCatcher catcher; 530 base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). 531 AppendASCII("wait_for_view"); 532 const Extension* extension = LoadExtension(extdir); 533 ASSERT_TRUE(extension); 534 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); 535 536 // The extension should've opened a new tab to an extension page. 537 EXPECT_EQ(extension->GetResourceURL("extension_page.html").spec(), 538 browser()->tab_strip_model()->GetActiveWebContents()-> 539 GetURL().spec()); 540 541 // Lazy Background Page still exists, because the extension created a new tab 542 // to an extension page. 543 EXPECT_TRUE(IsBackgroundPageAlive(last_loaded_extension_id())); 544 545 // Close the new tab. 546 LazyBackgroundObserver page_complete; 547 browser()->tab_strip_model()->CloseWebContentsAt( 548 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE); 549 page_complete.WaitUntilClosed(); 550 551 // Lazy Background Page has been shut down. 552 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); 553 554 // Verify that extensions page shows that the lazy background page is 555 // inactive. 556 bool is_inactive; 557 EXPECT_TRUE(content::ExecuteScriptInFrameAndExtractBool( 558 browser()->tab_strip_model()->GetActiveWebContents(), 559 "//iframe[starts-with(@src, 'chrome://extension')]", 560 "var ele = document.querySelectorAll('div.active-views');" 561 "window.domAutomationController.send(" 562 " ele[0].innerHTML.search('(Inactive)') > 0);", 563 &is_inactive)); 564 EXPECT_TRUE(is_inactive); 565 } 566 567 // Tests that the lazy background page will be unloaded if the onSuspend event 568 // handler calls an API function such as chrome.storage.local.set(). 569 // See: http://crbug.com/296834 570 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, OnSuspendUseStorageApi) { 571 EXPECT_TRUE(LoadExtensionAndWait("on_suspend")); 572 } 573 574 // TODO: background page with timer. 575 // TODO: background page that interacts with popup. 576