1 // Copyright 2015 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.
7 #include "base/auto_reset.h"
8 #include "base/run_loop.h"
9 #include "base/scoped_observer.h"
10 #include "base/strings/string_util.h"
11 #include "base/strings/stringprintf.h"
12 #include "chrome/browser/extensions/extension_browsertest.h"
13 #include "chrome/browser/extensions/test_extension_dir.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/test/base/ui_test_utils.h"
16 #include "content/public/test/browser_test_utils.h"
17 #include "extensions/browser/process_manager.h"
18 #include "extensions/browser/process_manager_observer.h"
19 #include "extensions/common/extension.h"
20 #include "extensions/test/background_page_watcher.h"
21 #include "extensions/test/extension_test_message_listener.h"
22 #include "net/dns/mock_host_resolver.h"
23 #include "net/test/embedded_test_server/embedded_test_server.h"
25 namespace extensions
{
30 // This uses single quotes for brevity, which will be replaced by double quotes
31 // when installing the extension.
33 // Expects a single string replacement of the "background" property, including
34 // trailing comma, or nothing if there is no background page.
35 const char* kManifestJson
=
38 " 'content_scripts': [{\n"
39 " 'js': ['content_script.js'],\n"
40 " 'matches': ['<all_urls>'],\n"
41 " 'run_at': 'document_start'\n"
43 " 'manifest_version': 2,\n"
44 " 'name': 'wake_event_page_apitest',\n"
50 // This content script just wakes the event page whenever it runs, then sends a
51 // chrome.test message with the result.
53 // Note: The wake-event-page function is exposed to content scripts via the
54 // chrome.test API for testing purposes only. In production its intended use
55 // case is from workers.
56 const char* kContentScriptJs
=
57 "chrome.test.getWakeEventPage()(function(success) {\n"
58 " chrome.test.sendMessage(success ? 'success' : 'failure');\n"
61 class WakeEventPageTest
: public ExtensionBrowserTest
{
63 WakeEventPageTest() {}
66 enum BackgroundPageConfiguration
{ EVENT
, PERSISTENT
, NONE
};
68 void RunTest(bool expect_success
,
69 BackgroundPageConfiguration bg_config
,
72 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
74 GURL web_url
= embedded_test_server()->GetURL("example.com", "/empty.html");
75 host_resolver()->AddRule(web_url
.host(), "127.0.0.1");
77 TestExtensionDir extension_dir
;
79 std::string manifest_json
;
83 base::StringPrintf(kManifestJson
,
85 " 'persistent': false,\n"
86 " 'scripts': ['background.js']\n"
91 base::StringPrintf(kManifestJson
,
93 " 'persistent': true,\n"
94 " 'scripts': ['background.js']\n"
98 manifest_json
= base::StringPrintf(kManifestJson
, "");
101 base::ReplaceChars(manifest_json
, "'", "\"", &manifest_json
);
102 extension_dir
.WriteManifest(manifest_json
);
103 // Empty background page. Closing/opening it is driven by this test.
104 extension_dir
.WriteFile(FILE_PATH_LITERAL("background.js"), "");
105 extension_dir
.WriteFile(FILE_PATH_LITERAL("content_script.js"),
109 // Install the extension, then close its background page if desired..
110 const Extension
* extension
= LoadExtension(extension_dir
.unpacked_path());
113 // Regardless of |will_be_open|, we haven't closed the background page yet,
114 // so it should always open if it exists.
115 if (bg_config
!= NONE
)
116 BackgroundPageWatcher(process_manager(), extension
).WaitForOpen();
119 GetBackgroundPage(extension
->id())->Close();
120 BackgroundPageWatcher(process_manager(), extension
).WaitForClose();
121 EXPECT_FALSE(GetBackgroundPage(extension
->id()));
124 // Start a content script to wake up the background page, if it's closed.
126 ExtensionTestMessageListener
listener(false /* will_reply */);
127 ui_test_utils::NavigateToURL(browser(), web_url
);
128 ASSERT_TRUE(listener
.WaitUntilSatisfied());
129 EXPECT_EQ(expect_success
? "success" : "failure", listener
.message());
132 EXPECT_EQ(will_be_open
, GetBackgroundPage(extension
->id()) != nullptr);
134 // Run the content script again. The background page will be awaken iff
135 // |will_be_open| is true, but if not, this is a harmless no-op.
137 ExtensionTestMessageListener
listener(false /* will_reply */);
138 ui_test_utils::NavigateToURL(browser(), web_url
);
139 ASSERT_TRUE(listener
.WaitUntilSatisfied());
140 EXPECT_EQ(expect_success
? "success" : "failure", listener
.message());
143 EXPECT_EQ(will_be_open
, GetBackgroundPage(extension
->id()) != nullptr);
147 ExtensionHost
* GetBackgroundPage(const std::string
& extension_id
) {
148 return process_manager()->GetBackgroundHostForExtension(extension_id
);
151 ProcessManager
* process_manager() { return ProcessManager::Get(profile()); }
153 DISALLOW_COPY_AND_ASSIGN(WakeEventPageTest
);
156 IN_PROC_BROWSER_TEST_F(WakeEventPageTest
, ClosedEventPage
) {
157 RunTest(true /* expect_success */, EVENT
, true /* should_close */,
158 true /* will_be_open */);
161 IN_PROC_BROWSER_TEST_F(WakeEventPageTest
, OpenEventPage
) {
162 RunTest(true /* expect_success */, EVENT
, false /* should_close */,
163 true /* will_be_open */);
166 IN_PROC_BROWSER_TEST_F(WakeEventPageTest
, ClosedPersistentBackgroundPage
) {
167 // Note: this is an odd test, because persistent background pages aren't
168 // supposed to close. Extensions can close them with window.close() but why
169 // would they do that? Test it anyway.
170 RunTest(false /* expect_success */, PERSISTENT
, true /* should_close */,
171 false /* will_be_open */);
174 IN_PROC_BROWSER_TEST_F(WakeEventPageTest
, OpenPersistentBackgroundPage
) {
175 RunTest(true /* expect_success */, PERSISTENT
, false /* should_close */,
176 true /* will_be_open */);
179 IN_PROC_BROWSER_TEST_F(WakeEventPageTest
, NoBackgroundPage
) {
180 RunTest(false /* expect_success */, NONE
, false /* should_close */,
181 false /* will_be_open */);
185 } // namespace extensions