• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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_factory.h"
9 #include "chrome/browser/chrome_notification_types.h"
10 #include "chrome/browser/extensions/browser_action_test_util.h"
11 #include "chrome/browser/extensions/extension_apitest.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/extension_test_message_listener.h"
14 #include "chrome/browser/extensions/lazy_background_page_test_util.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/ui/app_modal_dialogs/app_modal_dialog.h"
17 #include "chrome/browser/ui/browser.h"
18 #include "chrome/browser/ui/browser_window.h"
19 #include "chrome/browser/ui/omnibox/location_bar.h"
20 #include "chrome/browser/ui/tabs/tab_strip_model.h"
21 #include "chrome/common/url_constants.h"
22 #include "chrome/test/base/ui_test_utils.h"
23 #include "components/bookmarks/browser/bookmark_model.h"
24 #include "components/bookmarks/browser/bookmark_utils.h"
25 #include "components/bookmarks/test/bookmark_test_helpers.h"
26 #include "content/public/browser/notification_service.h"
27 #include "content/public/browser/web_contents.h"
28 #include "content/public/test/browser_test_utils.h"
29 #include "extensions/browser/extension_host.h"
30 #include "extensions/browser/extension_system.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:
LoadedIncognitoObserver(Profile * profile)49   explicit LoadedIncognitoObserver(Profile* profile) : profile_(profile) {
50     registrar_.Add(this, chrome::NOTIFICATION_EXTENSION_UNLOADED_DEPRECATED,
51                    content::Source<Profile>(profile));
52   }
53 
Wait()54   void Wait() {
55     ASSERT_TRUE(original_complete_.get());
56     original_complete_->Wait();
57     incognito_complete_->Wait();
58   }
59 
60  private:
61 
Observe(int type,const content::NotificationSource & source,const content::NotificationDetails & details)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:
LazyBackgroundPageApiTest()81   LazyBackgroundPageApiTest() {}
~LazyBackgroundPageApiTest()82   virtual ~LazyBackgroundPageApiTest() {}
83 
SetUpCommandLine(CommandLine * command_line)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.
LoadExtensionAndWait(const std::string & test_name)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.
IsBackgroundPageAlive(const std::string & extension_id)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 
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,BrowserActionCreateTab)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 
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,BrowserActionCreateTabAfterCallback)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 
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,BroadcastEvent)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 
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,Filters)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.
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,OnInstalled)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.
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,WaitForDialog)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.
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,WaitForView)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.
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,WaitForRequest)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
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,MAYBE_WaitForNTP)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.
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,MAYBE_IncognitoSplitMode)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, base::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.
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,Messaging)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.
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,ImpulseAddsCount)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.
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,OnUnload)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.
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,EventDispatchToTab)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(bookmark_model,
515                                      GURL("http://www.google.com"),
516                                      base::UTF8ToUTF16("Google"));
517 
518   EXPECT_TRUE(event_page_ready.WaitUntilSatisfied());
519 
520   page_ready.Reply("go");
521 
522   EXPECT_TRUE(catcher.GetNextResult()) << catcher.message();
523 }
524 
525 // Tests that the lazy background page updates the chrome://extensions page
526 // when it is destroyed.
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,UpdateExtensionsPage)527 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, UpdateExtensionsPage) {
528   ui_test_utils::NavigateToURL(browser(), GURL(chrome::kChromeUIExtensionsURL));
529 
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();
536 
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());
541 
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()));
545 
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();
551 
552   // Lazy Background Page has been shut down.
553   EXPECT_FALSE(IsBackgroundPageAlive(last_loaded_extension_id()));
554 
555   // Verify that extensions page shows that the lazy background page is
556   // inactive.
557   content::RenderFrameHost* frame = content::FrameMatchingPredicate(
558       browser()->tab_strip_model()->GetActiveWebContents(),
559       base::Bind(&content::FrameHasSourceUrl,
560                  GURL(chrome::kChromeUIExtensionsFrameURL)));
561   bool is_inactive;
562   EXPECT_TRUE(content::ExecuteScriptAndExtractBool(
563       frame,
564       "var ele = document.querySelectorAll('div.active-views');"
565       "window.domAutomationController.send("
566       "    ele[0].innerHTML.search('(Inactive)') > 0);",
567       &is_inactive));
568   EXPECT_TRUE(is_inactive);
569 }
570 
571 // Tests that the lazy background page will be unloaded if the onSuspend event
572 // handler calls an API function such as chrome.storage.local.set().
573 // See: http://crbug.com/296834
IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest,OnSuspendUseStorageApi)574 IN_PROC_BROWSER_TEST_F(LazyBackgroundPageApiTest, OnSuspendUseStorageApi) {
575   EXPECT_TRUE(LoadExtensionAndWait("on_suspend"));
576 }
577 
578 // TODO: background page with timer.
579 // TODO: background page that interacts with popup.
580