Only grant permissions to new extensions from sync if they have the expected version
[chromium-blink-merge.git] / chrome / browser / extensions / wake_event_page_apitest.cc
blob456155e7eaa528442f38b7be4b95ab34a9e758d2
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.
5 #include <string>
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/extension_test_message_listener.h"
21 #include "net/dns/mock_host_resolver.h"
22 #include "net/test/embedded_test_server/embedded_test_server.h"
24 namespace extensions {
25 namespace {
27 // manifest.json:
29 // This uses single quotes for brevity, which will be replaced by double quotes
30 // when installing the extension.
32 // Expects a single string replacement of the "background" property, including
33 // trailing comma, or nothing if there is no background page.
34 const char* kManifestJson =
35 "{\n"
36 " %s\n"
37 " 'content_scripts': [{\n"
38 " 'js': ['content_script.js'],\n"
39 " 'matches': ['<all_urls>'],\n"
40 " 'run_at': 'document_start'\n"
41 " }],\n"
42 " 'manifest_version': 2,\n"
43 " 'name': 'wake_event_page_apitest',\n"
44 " 'version': '1'\n"
45 "}\n";
47 // content_script.js:
49 // This content script just wakes the event page whenever it runs, then sends a
50 // chrome.test message with the result.
52 // Note: The wake-event-page function is exposed to content scripts via the
53 // chrome.test API for testing purposes only. In production its intended use
54 // case is from workers.
55 const char* kContentScriptJs =
56 "chrome.test.getWakeEventPage()(function(success) {\n"
57 " chrome.test.sendMessage(success ? 'success' : 'failure');\n"
58 "});\n";
60 class BackgroundPageWatcher : public ProcessManagerObserver {
61 public:
62 BackgroundPageWatcher(ProcessManager* process_manager,
63 const Extension* extension)
64 : process_manager_(process_manager),
65 extension_id_(extension->id()),
66 is_waiting_for_open_(false),
67 is_waiting_for_close_(false) {}
69 // Returns when the background page is open. If the background page is
70 // already open, returns immediately.
71 void WaitForOpen() { WaitForOpenState(true); }
73 // Returns when the background page is closed. If the background page is
74 // already closed, returns immediately.
75 void WaitForClose() { WaitForOpenState(false); }
77 private:
78 // Returns when the background page has open state of |wait_for_open|. If the
79 // background page is already in that state, returns immediately.
80 void WaitForOpenState(bool wait_for_open) {
81 if (IsBackgroundPageOpen() == wait_for_open)
82 return;
83 ScopedObserver<ProcessManager, ProcessManagerObserver> observer(this);
84 observer.Add(process_manager_);
85 bool* flag = wait_for_open ? &is_waiting_for_open_ : &is_waiting_for_close_;
86 base::AutoReset<bool> set_flag(flag, true);
87 base::RunLoop run_loop;
88 base::AutoReset<base::Closure> set_quit_run_loop(&quit_run_loop_,
89 run_loop.QuitClosure());
90 CHECK_EQ(wait_for_open, IsBackgroundPageOpen());
93 bool IsBackgroundPageOpen() {
94 return process_manager_->GetBackgroundHostForExtension(extension_id_) !=
95 nullptr;
98 void OnBackgroundHostCreated(ExtensionHost* host) override {
99 if (is_waiting_for_open_ && host->extension()->id() == extension_id_)
100 quit_run_loop_.Run();
103 void OnBackgroundHostClose(const std::string& extension_id) override {
104 if (is_waiting_for_close_ && extension_id == extension_id_)
105 quit_run_loop_.Run();
108 ProcessManager* const process_manager_;
109 const std::string extension_id_;
111 base::Closure quit_run_loop_;
112 bool is_waiting_for_open_;
113 bool is_waiting_for_close_;
115 DISALLOW_COPY_AND_ASSIGN(BackgroundPageWatcher);
118 class WakeEventPageTest : public ExtensionBrowserTest {
119 public:
120 WakeEventPageTest() {}
122 protected:
123 enum BackgroundPageConfiguration { EVENT, PERSISTENT, NONE };
125 void RunTest(bool expect_success,
126 BackgroundPageConfiguration bg_config,
127 bool should_close,
128 bool will_be_open) {
129 ASSERT_TRUE(embedded_test_server()->InitializeAndWaitUntilReady());
131 GURL web_url = embedded_test_server()->GetURL("example.com", "/empty.html");
132 host_resolver()->AddRule(web_url.host(), "127.0.0.1");
134 TestExtensionDir extension_dir;
136 std::string manifest_json;
137 switch (bg_config) {
138 case EVENT:
139 manifest_json =
140 base::StringPrintf(kManifestJson,
141 " 'background': {\n"
142 " 'persistent': false,\n"
143 " 'scripts': ['background.js']\n"
144 " },");
145 break;
146 case PERSISTENT:
147 manifest_json =
148 base::StringPrintf(kManifestJson,
149 " 'background': {\n"
150 " 'persistent': true,\n"
151 " 'scripts': ['background.js']\n"
152 " },");
153 break;
154 case NONE:
155 manifest_json = base::StringPrintf(kManifestJson, "");
156 break;
158 base::ReplaceChars(manifest_json, "'", "\"", &manifest_json);
159 extension_dir.WriteManifest(manifest_json);
160 // Empty background page. Closing/opening it is driven by this test.
161 extension_dir.WriteFile(FILE_PATH_LITERAL("background.js"), "");
162 extension_dir.WriteFile(FILE_PATH_LITERAL("content_script.js"),
163 kContentScriptJs);
166 // Install the extension, then close its background page if desired..
167 const Extension* extension = LoadExtension(extension_dir.unpacked_path());
168 CHECK(extension);
170 // Regardless of |will_be_open|, we haven't closed the background page yet,
171 // so it should always open if it exists.
172 if (bg_config != NONE)
173 BackgroundPageWatcher(process_manager(), extension).WaitForOpen();
175 if (should_close) {
176 GetBackgroundPage(extension->id())->Close();
177 BackgroundPageWatcher(process_manager(), extension).WaitForClose();
178 EXPECT_FALSE(GetBackgroundPage(extension->id()));
181 // Start a content script to wake up the background page, if it's closed.
183 ExtensionTestMessageListener listener(false /* will_reply */);
184 ui_test_utils::NavigateToURL(browser(), web_url);
185 ASSERT_TRUE(listener.WaitUntilSatisfied());
186 EXPECT_EQ(expect_success ? "success" : "failure", listener.message());
189 EXPECT_EQ(will_be_open, GetBackgroundPage(extension->id()) != nullptr);
191 // Run the content script again. The background page will be awaken iff
192 // |will_be_open| is true, but if not, this is a harmless no-op.
194 ExtensionTestMessageListener listener(false /* will_reply */);
195 ui_test_utils::NavigateToURL(browser(), web_url);
196 ASSERT_TRUE(listener.WaitUntilSatisfied());
197 EXPECT_EQ(expect_success ? "success" : "failure", listener.message());
200 EXPECT_EQ(will_be_open, GetBackgroundPage(extension->id()) != nullptr);
203 private:
204 ExtensionHost* GetBackgroundPage(const std::string& extension_id) {
205 return process_manager()->GetBackgroundHostForExtension(extension_id);
208 ProcessManager* process_manager() { return ProcessManager::Get(profile()); }
210 DISALLOW_COPY_AND_ASSIGN(WakeEventPageTest);
213 IN_PROC_BROWSER_TEST_F(WakeEventPageTest, ClosedEventPage) {
214 RunTest(true /* expect_success */, EVENT, true /* should_close */,
215 true /* will_be_open */);
218 IN_PROC_BROWSER_TEST_F(WakeEventPageTest, OpenEventPage) {
219 RunTest(true /* expect_success */, EVENT, false /* should_close */,
220 true /* will_be_open */);
223 IN_PROC_BROWSER_TEST_F(WakeEventPageTest, ClosedPersistentBackgroundPage) {
224 // Note: this is an odd test, because persistent background pages aren't
225 // supposed to close. Extensions can close them with window.close() but why
226 // would they do that? Test it anyway.
227 RunTest(false /* expect_success */, PERSISTENT, true /* should_close */,
228 false /* will_be_open */);
231 IN_PROC_BROWSER_TEST_F(WakeEventPageTest, OpenPersistentBackgroundPage) {
232 RunTest(true /* expect_success */, PERSISTENT, false /* should_close */,
233 true /* will_be_open */);
236 IN_PROC_BROWSER_TEST_F(WakeEventPageTest, NoBackgroundPage) {
237 RunTest(false /* expect_success */, NONE, false /* should_close */,
238 false /* will_be_open */);
241 } // namespace
242 } // namespace extensions