Home | History | Annotate | Download | only in extensions
      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