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