OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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/macros.h" | |
7 #include "base/strings/stringprintf.h" | |
8 #include "chrome/browser/extensions/active_script_controller.h" | |
9 #include "chrome/browser/extensions/extension_action.h" | |
10 #include "chrome/browser/extensions/extension_browsertest.h" | |
11 #include "chrome/browser/extensions/extension_test_message_listener.h" | |
12 #include "chrome/browser/extensions/location_bar_controller.h" | |
13 #include "chrome/browser/extensions/tab_helper.h" | |
14 #include "chrome/browser/extensions/test_extension_dir.h" | |
15 #include "chrome/browser/ui/browser.h" | |
16 #include "chrome/browser/ui/tabs/tab_strip_model.h" | |
17 #include "chrome/test/base/ui_test_utils.h" | |
18 #include "content/public/test/browser_test_utils.h" | |
19 #include "extensions/common/feature_switch.h" | |
20 #include "extensions/common/switches.h" | |
21 #include "net/test/embedded_test_server/embedded_test_server.h" | |
22 #include "testing/gtest/include/gtest/gtest.h" | |
23 | |
24 namespace extensions { | |
25 | |
26 namespace { | |
27 | |
28 // Within manifest permissions: | |
29 const char kAllPermission[] = "*://*/*"; | |
30 const char kParticularPermission[] = "http://127.0.0.1/*"; | |
31 const char kNowherePermission[] = "http://nowhere.com/*"; | |
32 | |
33 // Within declarative condition: | |
34 const char kAllMatcher[] = "{ pageUrl: { hostContains: '' } }"; | |
35 const char kParticularMatcher[] = "{ pageUrl: { hostEquals: '127.0.0.1' } }"; | |
36 const char kNowhereMatcher[] = "{ pageUrl: { hostEquals: 'nowhere.com' } }"; | |
37 | |
38 // Within |kManifest| below: %s -> |kAllPermission| or |kParticularPermission|. | |
39 const char kManifest[] = | |
40 "{\n" | |
41 " \"name\": \"Test DeclarativeContentScript\",\n" | |
42 " \"manifest_version\": 2,\n" | |
43 " \"version\": \"1.0\",\n" | |
44 " \"description\": \"Test declarative content script interface\",\n" | |
45 " \"permissions\": [\"declarativeContent\", \"%s\"],\n" | |
46 " \"background\": {\n" | |
47 " \"scripts\": [\"background.js\"]\n" | |
48 " }\n" | |
49 "}\n"; | |
50 | |
51 // Script sources: | |
52 // Within kBackgroundScriptSource below: %s -> |kAllMatcher| or | |
53 // |kParticularMatcher|. | |
54 const char kBackgroundScriptSource[] = | |
55 "var declarativeContent = chrome.declarativeContent;\n" | |
56 "var PageStateMatcher = declarativeContent.PageStateMatcher;\n" | |
57 "var RequestContentScript = declarativeContent.RequestContentScript;\n" | |
58 "var ShowPageAction = declarativeContent.ShowPageAction;\n" | |
59 "var onPageChanged = declarativeContent.onPageChanged;\n" | |
60 "onPageChanged.removeRules(undefined, function() {\n" | |
61 " onPageChanged.addRules(\n" | |
62 " [{\n" | |
63 " conditions: [new PageStateMatcher(%s)],\n" | |
64 " actions: [new RequestContentScript({js: ['script.js']}\n" | |
65 " )]\n" | |
66 " }],\n" | |
67 " function(details) {\n" | |
68 " if (!chrome.runtime.lastError)\n" | |
69 " chrome.test.sendMessage('injection setup');\n" | |
70 " }\n" | |
71 " );\n" | |
72 "});\n"; | |
73 const char kContentScriptSource[] = | |
74 "chrome.test.sendMessage('injection succeeded');"; | |
75 | |
76 // Messages from scripts: | |
77 const char kInjectionSetup[] = "injection setup"; | |
78 const char kInjectionSucceeded[] = "injection succeeded"; | |
79 | |
80 enum ManifestPermissionType { | |
81 MP_ALL, | |
82 MP_PARTICULAR, | |
83 MP_NOWHERE | |
84 }; | |
85 | |
86 enum ScriptMatcherType { | |
87 SM_ALL, | |
88 SM_PARTICULAR, | |
89 SM_NOWHERE | |
90 }; | |
91 | |
92 // Runs all pending tasks in the renderer associated with |web_contents|. | |
93 // Returns true on success. | |
94 bool RunAllPendingInRenderer(content::WebContents* web_contents) { | |
Devlin
2014/08/25 22:31:05
// TODO(devlin): If too many tests start to need t
Mark Dittmer
2014/08/26 17:53:58
Done.
| |
95 // This is slight hack to achieve a RunPendingInRenderer() method. Since IPCs | |
96 // are sent synchronously, anything started prior to this method will finish | |
97 // before this method returns (as content::ExecuteScript() is synchronous). | |
98 return content::ExecuteScript(web_contents, "1 == 1;"); | |
99 } | |
100 | |
101 } // namespace | |
102 | |
103 class RequestContentScriptBrowserTest : public ExtensionBrowserTest { | |
104 public: | |
105 RequestContentScriptBrowserTest(); | |
106 | |
107 // Associates this test with a new extension, the given |manifest_permission| | |
108 // and |script_matcher|. | |
109 testing::AssertionResult Init(ManifestPermissionType manifest_permission, | |
110 ScriptMatcherType script_matcher); | |
111 | |
112 // Performs script injection test on a common local URL. Does not return until | |
113 // the renderer should have completed its task and any browser-side reactions | |
114 // have been cleared from the task queue. | |
115 testing::AssertionResult RunTest(); | |
116 | |
117 ExtensionTestMessageListener* injection_setup_listener() { | |
118 return injection_setup_listener_.get(); | |
119 } | |
120 ExtensionTestMessageListener* injection_succeeded_listener() { | |
121 return injection_succeeded_listener_.get(); | |
122 } | |
123 | |
124 private: | |
125 scoped_ptr<TestExtensionDir> test_extension_dir_; | |
126 const Extension* extension_; | |
127 content::WebContents* web_contents_; | |
128 scoped_ptr<ExtensionTestMessageListener> injection_setup_listener_; | |
129 scoped_ptr<ExtensionTestMessageListener> injection_succeeded_listener_; | |
130 }; | |
131 | |
132 RequestContentScriptBrowserTest::RequestContentScriptBrowserTest() | |
133 : extension_(NULL), | |
134 web_contents_(NULL) {} | |
135 | |
136 testing::AssertionResult RequestContentScriptBrowserTest::Init( | |
137 ManifestPermissionType manifest_permission, | |
138 ScriptMatcherType script_matcher) { | |
139 const char* permission; | |
140 switch (manifest_permission) { | |
141 case MP_ALL: | |
142 permission = kAllPermission; | |
Devlin
2014/08/25 22:31:05
How about making a const char* kPermissions[] {
| |
143 break; | |
144 case MP_PARTICULAR: | |
145 permission = kParticularPermission; | |
146 break; | |
147 case MP_NOWHERE: | |
148 permission = kNowherePermission; | |
149 break; | |
150 } | |
151 std::string manifest = base::StringPrintf(kManifest, permission); | |
152 | |
153 const char* matcher; | |
Devlin
2014/08/25 22:31:05
ditto for matcher. Although if ManifestPermission
Mark Dittmer
2014/08/26 17:53:58
I was thinking that they may not remain the same s
| |
154 switch (script_matcher) { | |
155 case SM_ALL: | |
156 matcher = kAllMatcher; | |
157 break; | |
158 case SM_PARTICULAR: | |
159 matcher = kParticularMatcher; | |
160 break; | |
161 case SM_NOWHERE: | |
162 matcher = kNowhereMatcher; | |
163 break; | |
164 } | |
165 std::string background_src = base::StringPrintf(kBackgroundScriptSource, | |
166 matcher); | |
167 | |
168 scoped_ptr<TestExtensionDir> dir(new TestExtensionDir); | |
169 dir->WriteManifest(manifest); | |
170 dir->WriteFile(FILE_PATH_LITERAL("background.js"), background_src); | |
171 dir->WriteFile(FILE_PATH_LITERAL("script.js"), | |
172 kContentScriptSource); | |
173 | |
174 const Extension* extension = LoadExtension(dir->unpacked_path()); | |
175 if (!extension) | |
176 return testing::AssertionFailure() << "Failed to load extension."; | |
177 | |
178 test_extension_dir_.reset(dir.release()); | |
179 extension_ = extension; | |
180 | |
181 injection_setup_listener_.reset(new ExtensionTestMessageListener( | |
182 kInjectionSetup, | |
183 false /* won't reply */)); | |
184 injection_succeeded_listener_.reset(new ExtensionTestMessageListener( | |
185 kInjectionSucceeded, | |
186 false /* won't reply */)); | |
187 | |
188 injection_setup_listener_->set_extension_id(extension->id()); | |
189 injection_succeeded_listener_->set_extension_id(extension->id()); | |
190 return testing::AssertionSuccess(); | |
191 } | |
192 | |
193 testing::AssertionResult RequestContentScriptBrowserTest::RunTest() { | |
194 if (!embedded_test_server()->InitializeAndWaitUntilReady()) { | |
195 return testing::AssertionFailure() << | |
196 "Could not initialize embedded test server."; | |
197 } | |
198 ui_test_utils::NavigateToURL( | |
199 browser(), embedded_test_server()->GetURL("/extensions/test_file.html")); | |
200 | |
201 web_contents_ = | |
202 browser() ? browser()->tab_strip_model()->GetActiveWebContents() : NULL; | |
203 if (!web_contents_) | |
204 return testing::AssertionFailure() << "No web contents."; | |
205 | |
Devlin
2014/08/25 22:31:05
Since we never ever ever expect our Injection Setu
Mark Dittmer
2014/08/26 17:53:58
Done.
| |
206 // Give the extension plenty of time to inject. | |
207 if (!RunAllPendingInRenderer(web_contents_)) | |
208 return testing::AssertionFailure() << "Could not run pending in renderer."; | |
209 | |
210 // Make sure all running tasks are complete. | |
211 content::RunAllPendingInMessageLoop(); | |
212 | |
213 return testing::AssertionSuccess(); | |
214 } | |
215 | |
216 IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, | |
217 AllPermissionAllMatcherInject) { | |
218 EXPECT_TRUE(Init(MP_ALL, SM_ALL)); | |
219 EXPECT_TRUE(RunTest()); | |
Devlin
2014/08/25 22:31:05
This is a *lot* of browsertests. Unfortunately, b
| |
220 | |
221 ASSERT_TRUE(injection_setup_listener()->was_satisfied()); | |
222 ASSERT_TRUE(injection_succeeded_listener()->was_satisfied()); | |
223 } | |
224 | |
225 IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, | |
226 AllPermissionParticularMatcherInject) { | |
227 EXPECT_TRUE(Init(MP_ALL, SM_PARTICULAR)); | |
228 EXPECT_TRUE(RunTest()); | |
229 | |
230 ASSERT_TRUE(injection_setup_listener()->was_satisfied()); | |
231 ASSERT_TRUE(injection_succeeded_listener()->was_satisfied()); | |
232 } | |
233 | |
234 IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, | |
235 ParticularPermissionAllMatcherInject) { | |
236 EXPECT_TRUE(Init(MP_PARTICULAR, SM_ALL)); | |
237 EXPECT_TRUE(RunTest()); | |
238 | |
239 ASSERT_TRUE(injection_setup_listener()->was_satisfied()); | |
240 ASSERT_TRUE(injection_succeeded_listener()->was_satisfied()); | |
241 } | |
242 | |
243 IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, | |
244 ParticularPermissionParticularMatcherInject) { | |
245 EXPECT_TRUE(Init(MP_PARTICULAR, SM_PARTICULAR)); | |
246 EXPECT_TRUE(RunTest()); | |
247 | |
248 ASSERT_TRUE(injection_setup_listener()->was_satisfied()); | |
249 ASSERT_TRUE(injection_succeeded_listener()->was_satisfied()); | |
250 } | |
251 | |
252 IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, | |
253 NowherePermissionAllMatcherNoInject) { | |
254 EXPECT_TRUE(Init(MP_NOWHERE, SM_ALL)); | |
255 EXPECT_TRUE(RunTest()); | |
256 | |
257 ASSERT_TRUE(injection_setup_listener()->was_satisfied()); | |
258 ASSERT_FALSE(injection_succeeded_listener()->was_satisfied()); | |
259 } | |
260 | |
261 IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, | |
262 NowherePermissionParticularMatcherNoInject) { | |
263 EXPECT_TRUE(Init(MP_NOWHERE, SM_PARTICULAR)); | |
264 EXPECT_TRUE(RunTest()); | |
265 | |
266 ASSERT_TRUE(injection_setup_listener()->was_satisfied()); | |
267 ASSERT_FALSE(injection_succeeded_listener()->was_satisfied()); | |
268 } | |
269 | |
270 IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, | |
271 NowherePermissionNowhereMatcherNoInject) { | |
272 EXPECT_TRUE(Init(MP_NOWHERE, SM_NOWHERE)); | |
273 EXPECT_TRUE(RunTest()); | |
274 | |
275 ASSERT_TRUE(injection_setup_listener()->was_satisfied()); | |
276 ASSERT_FALSE(injection_succeeded_listener()->was_satisfied()); | |
277 } | |
278 | |
279 IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, | |
280 AllPermissionNowhereMatcherNoInject) { | |
281 EXPECT_TRUE(Init(MP_ALL, SM_NOWHERE)); | |
282 EXPECT_TRUE(RunTest()); | |
283 | |
284 ASSERT_TRUE(injection_setup_listener()->was_satisfied()); | |
285 ASSERT_FALSE(injection_succeeded_listener()->was_satisfied()); | |
286 } | |
287 | |
288 IN_PROC_BROWSER_TEST_F(RequestContentScriptBrowserTest, | |
289 ParticularPermissionNowhereMatcherNoInject) { | |
290 EXPECT_TRUE(Init(MP_PARTICULAR, SM_NOWHERE)); | |
291 EXPECT_TRUE(RunTest()); | |
292 | |
293 ASSERT_TRUE(injection_setup_listener()->was_satisfied()); | |
294 ASSERT_FALSE(injection_succeeded_listener()->was_satisfied()); | |
295 } | |
296 | |
297 } // namespace extensions | |
OLD | NEW |