Disable view source for Developer Tools.
[chromium-blink-merge.git] / chrome / browser / extensions / lazy_background_page_apitest.cc
blob10943ccee9cd814e9b2bbbe2e4afb5522cd55069
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.
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"
37 using extensions::Extension;
39 namespace {
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));
54 void Wait() {
55 ASSERT_TRUE(original_complete_.get());
56 original_complete_->Wait();
57 incognito_complete_->Wait();
60 private:
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()));
71 Profile* profile_;
72 content::NotificationRegistrar registrar_;
73 scoped_ptr<LazyBackgroundObserver> original_complete_;
74 scoped_ptr<LazyBackgroundObserver> incognito_complete_;
77 } // namespace
79 class LazyBackgroundPageApiTest : public ExtensionApiTest {
80 public:
81 LazyBackgroundPageApiTest() {}
82 virtual ~LazyBackgroundPageApiTest() {}
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");
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;
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);
113 private:
114 DISALLOW_COPY_AND_ASSIGN(LazyBackgroundPageApiTest);
117 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, BrowserActionCreateTab) {
118 ASSERT_TRUE(LoadExtensionAndWait("browser_action_create_tab"));
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();
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();
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());
138 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,
139 BrowserActionCreateTabAfterCallback) {
140 ASSERT_TRUE(LoadExtensionAndWait("browser_action_with_callback"));
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();
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();
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());
157 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, BroadcastEvent) {
158 ASSERT_TRUE(StartEmbeddedTestServer());
160 const Extension* extension = LoadExtensionAndWait("broadcast_event");
161 ASSERT_TRUE(extension);
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();
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();
177 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id()));
179 // Page action is shown.
180 page_action_changed.Wait();
181 EXPECT_EQ(num_page_actions + 1,
182 browser()->window()->GetLocationBar()->
183 GetLocationBarForTesting()->PageActionVisibleCount());
186 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, Filters) {
187 ASSERT_TRUE(StartEmbeddedTestServer());
189 const Extension* extension = LoadExtensionAndWait("filters");
190 ASSERT_TRUE(extension);
192 // Lazy Background Page doesn't exist yet.
193 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id()));
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();
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();
209 // Lazy Background Page has been shut down.
210 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id()));
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);
221 // The test extension opens a dialog on installation.
222 AppModalDialog* dialog = ui_test_utils::WaitForAppModalDialog();
223 ASSERT_TRUE(dialog);
225 // With the dialog open the background page is still alive.
226 EXPECT_TRUE(IsBackgroundPageAlive(extension->id()));
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));
236 // The background page closes now that the dialog is gone.
237 background_observer.WaitUntilClosed();
238 EXPECT_FALSE(IsBackgroundPageAlive(extension->id()));
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();
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());
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()));
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();
266 // Lazy Background Page has been shut down.
267 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id()));
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());
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();
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);
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();
298 // Lazy Background Page has been shut down.
299 EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
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();
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());
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()));
327 // Navigate away from the NTP, which should close the event page.
328 ui_test_utils::NavigateToURL(browser(), GURL("about:blank"));
329 lazybg.Wait();
331 // Lazy Background Page has been shut down.
332 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id()));
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
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"));
349 // Load the extension with incognito enabled.
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();
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()));
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).
371 ExtensionTestMessageListener listener("waiting", false);
372 ExtensionTestMessageListener listener_incognito("waiting_incognito", false);
374 LazyBackgroundObserver page_complete(browser()->profile());
375 BrowserActionTestUtil(browser()).Press(0);
376 page_complete.Wait();
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());
386 // Trigger a bookmark created event and ensure both pages receive it.
388 ExtensionTestMessageListener listener("waiting", false);
389 ExtensionTestMessageListener listener_incognito("waiting_incognito", false);
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, base::ASCIIToUTF16("Title"), GURL("about:blank"));
399 page_complete.Wait();
400 page2_complete.Wait();
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());
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"));
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());
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();
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()));
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();
438 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id()));
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);
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());
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();
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));
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();
472 EXPECT_FALSE(pm->GetBackgroundHostForExtension(last_loaded_extension_id()));
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"));
481 // Lazy Background Page has been shut down.
482 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id()));
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));
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());
496 const extensions::Extension* extension =
497 LoadExtensionAndWait("event_dispatch_to_tab");
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());
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);
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(bookmark_model,
515 GURL("http://www.google.com"),
516 base::UTF8ToUTF16("Google"));
518 EXPECT_TRUE(event_page_ready.WaitUntilSatisfied());
520 page_ready.Reply("go");
522 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
525 // Tests that the lazy background page updates the chrome://extensions page
526 // when it is destroyed.
527 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, UpdateExtensionsPage) {
528 ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIExtensionsURL));
530 ResultCatcher catcher;
531 base::FilePath extdir = test_data_dir_.AppendASCII("lazy_background_page").
532 AppendASCII("wait_for_view");
533 const Extension* extension = LoadExtension(extdir);
534 ASSERT_TRUE(extension);
535 EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
537 // The extension should've opened a new tab to an extension page.
538 EXPECT_EQ(extension->GetResourceURL("extension_page.html").spec(),
539 browser()->tab_strip_model()->GetActiveWebContents()->
540 GetURL().spec());
542 // Lazy Background Page still exists, because the extension created a new tab
543 // to an extension page.
544 EXPECT_TRUE(IsBackgroundPageAlive(last_loaded_extension_id()));
546 // Close the new tab.
547 LazyBackgroundObserver page_complete;
548 browser()->tab_strip_model()->CloseWebContentsAt(
549 browser()->tab_strip_model()->active_index(), TabStripModel::CLOSE_NONE);
550 page_complete.WaitUntilClosed();
552 // Lazy Background Page has been shut down.
553 EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id()));
555 // Verify that extensions page shows that the lazy background page is
556 // inactive.
557 bool is_inactive;
558 EXPECT_TRUE(content::ExecuteScriptInFrameAndExtractBool(
559 browser()->tab_strip_model()->GetActiveWebContents(),
560 "//iframe[starts-with(@src, 'chrome://extension')]",
561 "var ele = document.querySelectorAll('div.active-views');"
562 "window.domAutomationController.send("
563 " ele[0].innerHTML.search('(Inactive)') > 0);",
564 &is_inactive));
565 EXPECT_TRUE(is_inactive);
568 // Tests that the lazy background page will be unloaded if the onSuspend event
569 // handler calls an API function such as chrome.storage.local.set().
570 // See: http://crbug.com/296834
571 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, OnSuspendUseStorageApi) {
572 EXPECT_TRUE(LoadExtensionAndWait("on_suspend"));
575 // TODO: background page with timer.
576 // TODO: background page that interacts with popup.