| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include <stddef.h> |
| |
| #include "base/command_line.h" |
| #include "base/files/file_path.h" |
| #include "base/macros.h" |
| #include "base/path_service.h" |
| #include "base/scoped_observer.h" |
| #include "base/strings/utf_string_conversions.h" |
| #include "base/threading/thread_restrictions.h" |
| #include "build/build_config.h" |
| #include "chrome/browser/bookmarks/bookmark_model_factory.h" |
| #include "chrome/browser/extensions/extension_action_test_util.h" |
| #include "chrome/browser/extensions/extension_apitest.h" |
| #include "chrome/browser/extensions/lazy_background_page_test_util.h" |
| #include "chrome/browser/profiles/profile.h" |
| #include "chrome/browser/ui/browser.h" |
| #include "chrome/browser/ui/browser_window.h" |
| #include "chrome/browser/ui/extensions/browser_action_test_util.h" |
| #include "chrome/browser/ui/location_bar/location_bar.h" |
| #include "chrome/browser/ui/tabs/tab_strip_model.h" |
| #include "chrome/common/chrome_features.h" |
| #include "chrome/common/chrome_paths.h" |
| #include "chrome/common/chrome_switches.h" |
| #include "chrome/common/extensions/api/tabs.h" |
| #include "chrome/common/url_constants.h" |
| #include "chrome/test/base/ui_test_utils.h" |
| #include "components/app_modal/javascript_app_modal_dialog.h" |
| #include "components/bookmarks/browser/bookmark_model.h" |
| #include "components/bookmarks/browser/bookmark_utils.h" |
| #include "components/bookmarks/test/bookmark_test_helpers.h" |
| #include "components/nacl/common/buildflags.h" |
| #include "content/public/browser/web_contents.h" |
| #include "content/public/test/browser_test_utils.h" |
| #include "content/public/test/test_utils.h" |
| #include "extensions/browser/event_router.h" |
| #include "extensions/browser/extension_host.h" |
| #include "extensions/browser/extension_registry.h" |
| #include "extensions/browser/extension_registry_observer.h" |
| #include "extensions/browser/process_manager.h" |
| #include "extensions/common/extension.h" |
| #include "extensions/common/switches.h" |
| #include "extensions/test/extension_test_message_listener.h" |
| #include "extensions/test/result_catcher.h" |
| #include "net/dns/mock_host_resolver.h" |
| #include "net/test/embedded_test_server/embedded_test_server.h" |
| #include "testing/gtest/include/gtest/gtest.h" |
| #include "url/gurl.h" |
| |
| using bookmarks::BookmarkModel; |
| using bookmarks::BookmarkNode; |
| |
| namespace extensions { |
| |
| namespace { |
| |
| // This unfortunate bit of silliness is necessary when loading an extension in |
| // incognito. The goal is to load the extension, enable incognito, then wait |
| // for both background pages to load and close. The problem is that enabling |
| // incognito involves reloading the extension - and the background pages may |
| // have already loaded once before then. So we wait until the extension is |
| // unloaded before listening to the background page notifications. |
| class LoadedIncognitoObserver : public ExtensionRegistryObserver { |
| public: |
| explicit LoadedIncognitoObserver(Profile* profile) |
| : profile_(profile), extension_registry_observer_(this) { |
| extension_registry_observer_.Add(ExtensionRegistry::Get(profile_)); |
| } |
| |
| void Wait() { |
| ASSERT_TRUE(original_complete_.get()); |
| original_complete_->Wait(); |
| incognito_complete_->Wait(); |
| } |
| |
| private: |
| void OnExtensionUnloaded(content::BrowserContext* browser_context, |
| const Extension* extension, |
| UnloadedExtensionReason reason) override { |
| original_complete_.reset(new LazyBackgroundObserver(profile_)); |
| incognito_complete_.reset( |
| new LazyBackgroundObserver(profile_->GetOffTheRecordProfile())); |
| } |
| |
| Profile* profile_; |
| ScopedObserver<ExtensionRegistry, ExtensionRegistryObserver> |
| extension_registry_observer_; |
| std::unique_ptr<LazyBackgroundObserver> original_complete_; |
| std::unique_ptr<LazyBackgroundObserver> incognito_complete_; |
| }; |
| |
| } // namespace |
| |
| class LazyBackgroundPageApiTest : public ExtensionApiTest { |
| public: |
| LazyBackgroundPageApiTest() {} |
| ~LazyBackgroundPageApiTest() override {} |
| |
| void SetUpInProcessBrowserTestFixture() override { |
| ExtensionApiTest::SetUpInProcessBrowserTestFixture(); |
| // Set shorter delays to prevent test timeouts. |
| ProcessManager::SetEventPageIdleTimeForTesting(1); |
| ProcessManager::SetEventPageSuspendingTimeForTesting(1); |
| } |
| |
| void SetUpCommandLine(base::CommandLine* command_line) override { |
| ExtensionApiTest::SetUpCommandLine(command_line); |
| // Disable background network activity as it can suddenly bring the Lazy |
| // Background Page alive. |
| command_line->AppendSwitch(::switches::kDisableBackgroundNetworking); |
| command_line->AppendSwitch(::switches::kNoProxyServer); |
| } |
| |
| void SetUpOnMainThread() override { |
| ExtensionApiTest::SetUpOnMainThread(); |
| host_resolver()->AddRule("*", "127.0.0.1"); |
| } |
| |
| // Loads the extension, which temporarily starts the lazy background page |
| // to dispatch the onInstalled event. We wait until it shuts down again. |
| const Extension* LoadExtensionAndWait(const std::string& test_name) { |
| LazyBackgroundObserver page_complete; |
| base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). |
| AppendASCII(test_name); |
| const Extension* extension = LoadExtension(extdir); |
| if (extension) |
| page_complete.Wait(); |
| return extension; |
| } |
| |
| // Returns true if the lazy background page for the extension with |
| // |extension_id| is still running. |
| bool IsBackgroundPageAlive(const std::string& extension_id) { |
| ProcessManager* pm = ProcessManager::Get(browser()->profile()); |
| return pm->GetBackgroundHostForExtension(extension_id); |
| } |
| |
| private: |
| DISALLOW_COPY_AND_ASSIGN(LazyBackgroundPageApiTest); |
| }; |
| |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, BrowserActionCreateTab) { |
| ASSERT_TRUE(LoadExtensionAndWait("browser_action_create_tab")); |
| |
| // Lazy Background Page doesn't exist yet. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| int num_tabs_before = browser()->tab_strip_model()->count(); |
| |
| // Observe background page being created and closed after |
| // the browser action is clicked. |
| LazyBackgroundObserver page_complete; |
| BrowserActionTestUtil::Create(browser())->Press(0); |
| page_complete.Wait(); |
| |
| // Background page created a new tab before it closed. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| EXPECT_EQ(num_tabs_before + 1, browser()->tab_strip_model()->count()); |
| EXPECT_EQ(std::string(chrome::kChromeUIExtensionsURL), |
| browser()->tab_strip_model()->GetActiveWebContents()-> |
| GetURL().spec()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, |
| BrowserActionCreateTabAfterCallback) { |
| ASSERT_TRUE(LoadExtensionAndWait("browser_action_with_callback")); |
| |
| // Lazy Background Page doesn't exist yet. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| int num_tabs_before = browser()->tab_strip_model()->count(); |
| |
| // Observe background page being created and closed after |
| // the browser action is clicked. |
| LazyBackgroundObserver page_complete; |
| BrowserActionTestUtil::Create(browser())->Press(0); |
| page_complete.Wait(); |
| |
| // Background page is closed after creating a new tab. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| EXPECT_EQ(num_tabs_before + 1, browser()->tab_strip_model()->count()); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, BroadcastEvent) { |
| ASSERT_TRUE(StartEmbeddedTestServer()); |
| |
| const Extension* extension = LoadExtensionAndWait("broadcast_event"); |
| ASSERT_TRUE(extension); |
| |
| // Lazy Background Page doesn't exist yet. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| EXPECT_EQ(0u, extension_action_test_util::GetVisiblePageActionCount( |
| browser()->tab_strip_model()->GetActiveWebContents())); |
| |
| // Open a tab to a URL that will trigger the page action to show. |
| LazyBackgroundObserver page_complete; |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); |
| page_complete.Wait(); |
| |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| |
| // Page action is shown. |
| WaitForPageActionVisibilityChangeTo(1); |
| EXPECT_EQ(1u, extension_action_test_util::GetVisiblePageActionCount( |
| browser()->tab_strip_model()->GetActiveWebContents())); |
| } |
| |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, Filters) { |
| ASSERT_TRUE(StartEmbeddedTestServer()); |
| |
| const Extension* extension = LoadExtensionAndWait("filters"); |
| ASSERT_TRUE(extension); |
| |
| // Lazy Background Page doesn't exist yet. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| |
| // Open a tab to a URL that will fire a webNavigation event. |
| LazyBackgroundObserver page_complete; |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); |
| page_complete.Wait(); |
| } |
| |
| // Tests that the lazy background page receives the onInstalled event and shuts |
| // down. |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, OnInstalled) { |
| ResultCatcher catcher; |
| ASSERT_TRUE(LoadExtensionAndWait("on_installed")); |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| |
| // Lazy Background Page has been shut down. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| } |
| |
| // Tests that a JavaScript alert keeps the lazy background page alive. |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, WaitForDialog) { |
| LazyBackgroundObserver background_observer; |
| base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). |
| AppendASCII("wait_for_dialog"); |
| const Extension* extension = LoadExtension(extdir); |
| ASSERT_TRUE(extension); |
| |
| // The test extension opens a dialog on installation. |
| app_modal::JavaScriptAppModalDialog* dialog = |
| ui_test_utils::WaitForAppModalDialog(); |
| ASSERT_TRUE(dialog); |
| |
| // With the dialog open the background page is still alive. |
| EXPECT_TRUE(IsBackgroundPageAlive(extension->id())); |
| |
| // Close the dialog. The keep alive count is decremented. |
| ProcessManager* pm = ProcessManager::Get(browser()->profile()); |
| int previous_keep_alive_count = pm->GetLazyKeepaliveCount(extension); |
| dialog->CloseModalDialog(); |
| EXPECT_EQ(previous_keep_alive_count - 1, |
| pm->GetLazyKeepaliveCount(extension)); |
| |
| // The background page closes now that the dialog is gone. |
| background_observer.WaitUntilClosed(); |
| EXPECT_FALSE(IsBackgroundPageAlive(extension->id())); |
| } |
| |
| // Tests that the lazy background page stays alive until all visible views are |
| // closed. |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, WaitForView) { |
| LazyBackgroundObserver page_complete; |
| ResultCatcher catcher; |
| base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). |
| AppendASCII("wait_for_view"); |
| const Extension* extension = LoadExtension(extdir); |
| ASSERT_TRUE(extension); |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| |
| // The extension should've opened a new tab to an extension page. |
| EXPECT_EQ(extension->GetResourceURL("extension_page.html").spec(), |
| browser()->tab_strip_model()->GetActiveWebContents()-> |
| GetURL().spec()); |
| |
| // Lazy Background Page still exists, because the extension created a new tab |
| // to an extension page. |
| EXPECT_TRUE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| |
| // Close the new tab. |
| browser()->tab_strip_model()->CloseWebContentsAt( |
| browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE); |
| page_complete.Wait(); |
| |
| // Lazy Background Page has been shut down. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| } |
| |
| // Tests that the lazy background page stays alive until all network requests |
| // are complete. |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, WaitForRequest) { |
| ASSERT_TRUE(StartEmbeddedTestServer()); |
| |
| LazyBackgroundObserver page_complete; |
| ResultCatcher catcher; |
| base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). |
| AppendASCII("wait_for_request"); |
| const Extension* extension = LoadExtension(extdir); |
| ASSERT_TRUE(extension); |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| |
| // Lazy Background Page still exists, because the extension started a request. |
| ProcessManager* pm = ProcessManager::Get(browser()->profile()); |
| ExtensionHost* host = |
| pm->GetBackgroundHostForExtension(last_loaded_extension_id()); |
| ASSERT_TRUE(host); |
| |
| // Abort the request. |
| bool result = false; |
| EXPECT_TRUE(content::ExecuteScriptAndExtractBool(host->web_contents(), |
| "abortRequest()", &result)); |
| EXPECT_TRUE(result); |
| page_complete.Wait(); |
| |
| // Lazy Background Page has been shut down. |
| EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id())); |
| } |
| |
| // Tests that the lazy background page stays alive while a NaCl module exists in |
| // its DOM. |
| #if BUILDFLAG(ENABLE_NACL) |
| |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, NaClInBackgroundPage) { |
| { |
| base::FilePath extdir; |
| base::ScopedAllowBlockingForTesting allow_blocking; |
| ASSERT_TRUE(base::PathService::Get(chrome::DIR_GEN_TEST_DATA, &extdir)); |
| extdir = extdir.AppendASCII("ppapi/tests/extensions/load_unload/newlib"); |
| LazyBackgroundObserver page_complete; |
| ASSERT_TRUE(LoadExtension(extdir)); |
| page_complete.Wait(); |
| } |
| |
| // The NaCl module is loaded, and the Lazy Background Page stays alive. |
| { |
| ExtensionTestMessageListener nacl_module_loaded("nacl_module_loaded", |
| false); |
| BrowserActionTestUtil::Create(browser())->Press(0); |
| EXPECT_TRUE(nacl_module_loaded.WaitUntilSatisfied()); |
| content::RunAllTasksUntilIdle(); |
| EXPECT_TRUE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| } |
| |
| // The NaCl module is detached from DOM, and the Lazy Background Page shuts |
| // down. |
| { |
| LazyBackgroundObserver page_complete; |
| BrowserActionTestUtil::Create(browser())->Press(0); |
| page_complete.WaitUntilClosed(); |
| } |
| |
| // The Lazy Background Page has been shut down. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| } |
| |
| // Tests that the lazy background page shuts down when all visible views with |
| // NaCl modules are closed. |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, NaClInView) { |
| // The extension is loaded and should've opened a new tab to an extension |
| // page, and the Lazy Background Page stays alive. |
| { |
| base::FilePath extdir; |
| base::ScopedAllowBlockingForTesting allow_blocking; |
| ASSERT_TRUE(base::PathService::Get(chrome::DIR_GEN_TEST_DATA, &extdir)); |
| extdir = extdir.AppendASCII("ppapi/tests/extensions/popup/newlib"); |
| ResultCatcher catcher; |
| const Extension* extension = LoadExtension(extdir); |
| ASSERT_TRUE(extension); |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| EXPECT_EQ( |
| extension->GetResourceURL("popup.html").spec(), |
| browser()->tab_strip_model()->GetActiveWebContents()->GetURL().spec()); |
| EXPECT_TRUE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| } |
| |
| // Close the new tab. |
| { |
| LazyBackgroundObserver page_complete; |
| browser()->tab_strip_model()->CloseWebContentsAt( |
| browser()->tab_strip_model()->active_index(), |
| TabStripModel::CLOSE_NONE); |
| page_complete.WaitUntilClosed(); |
| } |
| |
| // The Lazy Background Page has been shut down. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| } |
| #endif |
| |
| // Tests that the lazy background page stays alive until all visible views are |
| // closed. |
| // http://crbug.com/175778; test fails frequently on OS X |
| #if defined(OS_MACOSX) |
| #define MAYBE_WaitForNTP DISABLED_WaitForNTP |
| #else |
| #define MAYBE_WaitForNTP WaitForNTP |
| #endif |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, MAYBE_WaitForNTP) { |
| LazyBackgroundObserver lazybg; |
| ResultCatcher catcher; |
| base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). |
| AppendASCII("wait_for_ntp"); |
| const Extension* extension = LoadExtension(extdir); |
| ASSERT_TRUE(extension); |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| |
| // The extension should've opened a new tab to an extension page. |
| EXPECT_EQ(GURL(chrome::kChromeUINewTabURL), |
| browser()->tab_strip_model()->GetActiveWebContents()->GetURL()); |
| |
| // Lazy Background Page still exists, because the extension created a new tab |
| // to an extension page. |
| EXPECT_TRUE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| |
| // Navigate away from the NTP, which should close the event page. |
| ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); |
| lazybg.Wait(); |
| |
| // Lazy Background Page has been shut down. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| } |
| |
| // Tests that an incognito split mode extension gets 2 lazy background pages, |
| // and they each load and unload at the proper times. |
| // See crbug.com/248437 |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, DISABLED_IncognitoSplitMode) { |
| // Open incognito window. |
| Browser* incognito_browser = |
| OpenURLOffTheRecord(browser()->profile(), GURL("about:blank")); |
| |
| // Load the extension with incognito enabled. |
| { |
| LoadedIncognitoObserver loaded(browser()->profile()); |
| base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page"). |
| AppendASCII("incognito_split"); |
| ASSERT_TRUE(LoadExtensionIncognito(extdir)); |
| loaded.Wait(); |
| } |
| |
| // Lazy Background Page doesn't exist yet. |
| ProcessManager* pm = ProcessManager::Get(browser()->profile()); |
| ProcessManager* pmi = ProcessManager::Get(incognito_browser->profile()); |
| EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id())); |
| EXPECT_FALSE(pmi->GetBackgroundHostForExtension(last_loaded_extension_id())); |
| |
| // Trigger a browserAction event in the original profile and ensure only |
| // the original event page received it (since the event is scoped to the |
| // profile). |
| { |
| ExtensionTestMessageListener listener("waiting", false); |
| ExtensionTestMessageListener listener_incognito("waiting_incognito", false); |
| |
| LazyBackgroundObserver page_complete(browser()->profile()); |
| BrowserActionTestUtil::Create(browser())->Press(0); |
| page_complete.Wait(); |
| |
| // Only the original event page received the message. |
| EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id())); |
| EXPECT_FALSE( |
| pmi->GetBackgroundHostForExtension(last_loaded_extension_id())); |
| EXPECT_TRUE(listener.was_satisfied()); |
| EXPECT_FALSE(listener_incognito.was_satisfied()); |
| } |
| |
| // Trigger a bookmark created event and ensure both pages receive it. |
| { |
| ExtensionTestMessageListener listener("waiting", false); |
| ExtensionTestMessageListener listener_incognito("waiting_incognito", false); |
| |
| LazyBackgroundObserver page_complete(browser()->profile()), |
| page2_complete(incognito_browser->profile()); |
| BookmarkModel* bookmark_model = |
| BookmarkModelFactory::GetForBrowserContext(browser()->profile()); |
| bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model); |
| const BookmarkNode* parent = bookmark_model->bookmark_bar_node(); |
| bookmark_model->AddURL( |
| parent, 0, base::ASCIIToUTF16("Title"), GURL("about:blank")); |
| page_complete.Wait(); |
| page2_complete.Wait(); |
| |
| // Both pages received the message. |
| EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id())); |
| EXPECT_FALSE( |
| pmi->GetBackgroundHostForExtension(last_loaded_extension_id())); |
| EXPECT_TRUE(listener.was_satisfied()); |
| EXPECT_TRUE(listener_incognito.was_satisfied()); |
| } |
| } |
| |
| // Tests that messages from the content script activate the lazy background |
| // page, and keep it alive until all channels are closed. |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, Messaging) { |
| ASSERT_TRUE(StartEmbeddedTestServer()); |
| ASSERT_TRUE(LoadExtensionAndWait("messaging")); |
| |
| // Lazy Background Page doesn't exist yet. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| EXPECT_EQ(1, browser()->tab_strip_model()->count()); |
| |
| // Navigate to a page that opens a message channel to the background page. |
| ResultCatcher catcher; |
| LazyBackgroundObserver lazybg; |
| ui_test_utils::NavigateToURL( |
| browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); |
| lazybg.WaitUntilLoaded(); |
| |
| // Background page got the content script's message and is still loaded |
| // until we close the channel. |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| EXPECT_TRUE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| |
| // Navigate away, closing the message channel and therefore the background |
| // page. |
| ui_test_utils::NavigateToURL(browser(), GURL("about:blank")); |
| lazybg.WaitUntilClosed(); |
| |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| } |
| |
| // Tests that the lazy background page receives the unload event when we |
| // close it, and that it can execute simple API calls that don't require an |
| // asynchronous response. |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, OnUnload) { |
| ASSERT_TRUE(LoadExtensionAndWait("on_unload")); |
| |
| // Lazy Background Page has been shut down. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| |
| // The browser action has a new title. |
| auto browser_action = BrowserActionTestUtil::Create(browser()); |
| ASSERT_EQ(1, browser_action->NumberOfBrowserActions()); |
| EXPECT_EQ("Success", browser_action->GetTooltip(0)); |
| } |
| |
| // Tests that both a regular page and an event page will receive events when |
| // the event page is not loaded. |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, EventDispatchToTab) { |
| ResultCatcher catcher; |
| catcher.RestrictToBrowserContext(browser()->profile()); |
| |
| const Extension* extension = LoadExtensionAndWait("event_dispatch_to_tab"); |
| |
| ExtensionTestMessageListener page_ready("ready", true); |
| GURL page_url = extension->GetResourceURL("page.html"); |
| ui_test_utils::NavigateToURL(browser(), page_url); |
| EXPECT_TRUE(page_ready.WaitUntilSatisfied()); |
| |
| // After the event is sent below, wait for the event page to have received |
| // the event before proceeding with the test. This allows the regular page |
| // to test that the event page received the event, which makes the pass/fail |
| // logic simpler. |
| ExtensionTestMessageListener event_page_ready("ready", false); |
| |
| // Send an event by making a bookmark. |
| BookmarkModel* bookmark_model = |
| BookmarkModelFactory::GetForBrowserContext(browser()->profile()); |
| bookmarks::test::WaitForBookmarkModelToLoad(bookmark_model); |
| bookmarks::AddIfNotBookmarked(bookmark_model, |
| GURL("http://www.google.com"), |
| base::UTF8ToUTF16("Google")); |
| |
| EXPECT_TRUE(event_page_ready.WaitUntilSatisfied()); |
| |
| page_ready.Reply("go"); |
| |
| EXPECT_TRUE(catcher.GetNextResult()) << catcher.message(); |
| } |
| |
| // Tests that the lazy background page will be unloaded if the onSuspend event |
| // handler calls an API function such as chrome.storage.local.set(). |
| // See: http://crbug.com/296834 |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, OnSuspendUseStorageApi) { |
| EXPECT_TRUE(LoadExtensionAndWait("on_suspend")); |
| } |
| |
| // TODO: background page with timer. |
| // TODO: background page that interacts with popup. |
| |
| // Ensure that the events page of an extension is properly torn down and the |
| // process does not linger around. |
| // See https://crbug.com/612668. |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, EventProcessCleanup) { |
| ASSERT_TRUE(LoadExtensionAndWait("event_page_with_web_iframe")); |
| |
| // Lazy Background Page doesn't exist anymore. |
| EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id())); |
| } |
| |
| // Tests that lazy listeners persist when the event page is torn down, but |
| // the listeners associated with the process do not. |
| IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, EventListenerCleanup) { |
| EventRouter* event_router = EventRouter::Get(profile()); |
| const char* kEvent = api::tabs::OnUpdated::kEventName; |
| EXPECT_FALSE(event_router->HasLazyEventListenerForTesting(kEvent)); |
| EXPECT_FALSE(event_router->HasNonLazyEventListenerForTesting(kEvent)); |
| |
| // The extension should load and register a listener for the tabs.onUpdated |
| // event. |
| ExtensionTestMessageListener listener("ready", true /* Will reply */); |
| const Extension* extension = LoadExtension( |
| test_data_dir_.AppendASCII("lazy_background_page/event_cleanup")); |
| ASSERT_TRUE(extension); |
| ASSERT_TRUE(listener.WaitUntilSatisfied()); |
| |
| EXPECT_TRUE(IsBackgroundPageAlive(extension->id())); |
| EXPECT_TRUE(event_router->HasLazyEventListenerForTesting(kEvent)); |
| EXPECT_TRUE(event_router->HasNonLazyEventListenerForTesting(kEvent)); |
| |
| // Wait for the background page to spin down. |
| LazyBackgroundObserver background_page_waiter; |
| listener.Reply("good night"); |
| background_page_waiter.WaitUntilClosed(); |
| |
| // Only the lazy listener should remain. |
| EXPECT_FALSE(IsBackgroundPageAlive(extension->id())); |
| EXPECT_TRUE(event_router->HasLazyEventListenerForTesting(kEvent)); |
| EXPECT_FALSE(event_router->HasNonLazyEventListenerForTesting(kEvent)); |
| } |
| |
| } // namespace extensions |