Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(126)

Side by Side Diff: headless/lib/embedder_mojo_browsertest.cc

Issue 2049363003: Adds support for headless chrome embedder mojo services (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Fix typo Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 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 <memory>
6 #include "base/path_service.h"
7 #include "base/threading/thread_restrictions.h"
8 #include "content/public/test/browser_test.h"
9 #include "headless/grit/headless_browsertest_resources.h"
10 #include "headless/lib/embedder_test.mojom.h"
11 #include "headless/public/domains/runtime.h"
12 #include "headless/public/headless_browser.h"
13 #include "headless/public/headless_devtools_client.h"
14 #include "headless/public/headless_devtools_target.h"
15 #include "headless/public/headless_web_contents.h"
16 #include "headless/test/headless_browser_test.h"
17 #include "mojo/public/cpp/bindings/binding_set.h"
18 #include "mojo/public/cpp/bindings/interface_ptr_set.h"
19 #include "mojo/public/cpp/bindings/interface_request.h"
20 #include "testing/gtest/include/gtest/gtest.h"
21 #include "ui/base/resource/resource_bundle.h"
22 #include "url/gurl.h"
23
24 namespace headless {
25
26 #define DEVTOOLS_CLIENT_TEST_F(TEST_FIXTURE_NAME) \
27 IN_PROC_BROWSER_TEST_F(TEST_FIXTURE_NAME, RunAsyncTest) { RunTest(); } \
28 class AsyncHeadlessBrowserTestNeedsSemicolon##TEST_FIXTURE_NAME {}
29
30 // A test fixture which attaches a devtools client before starting the test.
31 class EmbedderMojoTest : public HeadlessBrowserTest,
32 public HeadlessWebContents::Observer,
33 public embedder_test::TestEmbedderService {
34 public:
35 EmbedderMojoTest()
36 : web_contents_(nullptr),
37 devtools_client_(HeadlessDevToolsClient::Create()) {}
38 ~EmbedderMojoTest() override {}
39
40 void SetUpOnMainThread() override {
41 base::ThreadRestrictions::SetIOAllowed(true);
42 base::FilePath pak_path;
43 ASSERT_TRUE(PathService::Get(base::DIR_MODULE, &pak_path));
44 pak_path = pak_path.AppendASCII("headless_browser_tests.pak");
45 ResourceBundle::GetSharedInstance().AddDataPackFromPath(
46 pak_path, ui::SCALE_FACTOR_NONE);
47 }
48
49 // HeadlessWebContentsObserver implementation:
50 void DevToolsTargetReady() override {
51 EXPECT_TRUE(web_contents_->GetDevToolsTarget());
52 web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get());
53
54 RunMojoTest();
55 }
56
57 virtual void RunMojoTest() = 0;
58
59 virtual GURL GetInitialUrl() const { return GURL("about:blank"); }
60
61 void OnEvalResult(std::unique_ptr<runtime::EvaluateResult> result) {
62 EXPECT_FALSE(result->HasExceptionDetails())
63 << "JS exception: " << result->GetExceptionDetails()->GetText();
64 if (result->HasExceptionDetails()) {
65 FinishAsynchronousTest();
66 }
67 }
68
69 protected:
70 void RunTest() {
71 // Using a pak file is idomatic chromium style, but most embedders probably
72 // wouln't load the javascript bindings file this way.
73 std::string embedder_test_mojom_js =
74 ResourceBundle::GetSharedInstance()
75 .GetRawDataResource(IDR_HEADLESS_EMBEDDER_TEST_MOJOM_JS)
76 .as_string();
77
78 web_contents_ =
79 browser()
80 ->CreateWebContentsBuilder()
81 .SetInitialURL(GURL(GetInitialUrl()))
82 .AddMojoService(base::Bind(&EmbedderMojoTest::CreateTestMojoService,
83 base::Unretained(this)))
84 .AddJsMojoBindings("headless/lib/embedder_test.mojom",
85 embedder_test_mojom_js)
86 .Build();
87
88 web_contents_->AddObserver(this);
89 RunAsynchronousTest();
90
91 web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get());
92 web_contents_->RemoveObserver(this);
93 web_contents_->Close();
94 web_contents_ = nullptr;
95 }
96
97 void CreateTestMojoService(
98 mojo::InterfaceRequest<embedder_test::TestEmbedderService> request) {
99 test_embedder_mojo_bindings_.AddBinding(this, std::move(request));
100 }
101
102 HeadlessWebContents* web_contents_;
103 std::unique_ptr<HeadlessDevToolsClient> devtools_client_;
104
105 mojo::BindingSet<embedder_test::TestEmbedderService>
106 test_embedder_mojo_bindings_;
107 };
108
109 class EmbedderMojoBindingsTest : public EmbedderMojoTest {
110 public:
111 void RunMojoTest() override {
112 devtools_client_->GetRuntime()->Evaluate(
113 "mojo.services.embedder_test.TestEmbedderService.then( \n"
114 " function(service) { \n"
115 " service.returnTestResult('hello world'); \n"
116 " });",
117 base::Bind(&EmbedderMojoTest::OnEvalResult, base::Unretained(this)));
118 }
119
120 // embedder_test::TestEmbedderService:
121 void ReturnTestResult(const mojo::String& result) override {
122 EXPECT_EQ("hello world", result.get());
123 FinishAsynchronousTest();
124 }
125 };
126
127 DEVTOOLS_CLIENT_TEST_F(EmbedderMojoBindingsTest);
128
129 class RejectNonExistentBindingsTest : public EmbedderMojoTest {
130 public:
131 void RunMojoTest() override {
132 devtools_client_->GetRuntime()->Evaluate(
133 "mojo.services.embedder_test.TestEmbedderService.then( \n"
134 " function(service) { \n"
135 " mojo.services.nonExistent.MojoService.then(function() { \n"
136 " service.returnTestResult('Fail - promise not rejected'); \n"
137 " }).catch(function() { \n"
138 " service.returnTestResult('Pass - promise rejected'); \n"
139 " }); \n"
140 " });",
141 base::Bind(&EmbedderMojoTest::OnEvalResult, base::Unretained(this)));
142 }
143
144 // embedder_test::TestEmbedderService:
145 void ReturnTestResult(const mojo::String& result) override {
146 EXPECT_EQ("Pass - promise rejected", result.get());
147 FinishAsynchronousTest();
148 }
149 };
150
151 DEVTOOLS_CLIENT_TEST_F(RejectNonExistentBindingsTest);
152
153 // Test bindings that occur after the onload event, which is after the browser
154 // has sent us the bindings.
155 class DelayedRejectNonExistentBindingsTest : public EmbedderMojoTest {
156 public:
157 DelayedRejectNonExistentBindingsTest() {
158 EXPECT_TRUE(embedded_test_server()->Start());
159 }
160
161 GURL GetInitialUrl() const override {
162 return embedded_test_server()->GetURL(
163 "/late_nonexistent_mojo_binding.html");
164 }
165
166 void RunMojoTest() override {}
167
168 // embedder_test::TestEmbedderService:
169 void ReturnTestResult(const mojo::String& result) override {
170 EXPECT_EQ("Pass - promise rejected", result.get());
171 FinishAsynchronousTest();
172 }
173 };
174
175 DEVTOOLS_CLIENT_TEST_F(DelayedRejectNonExistentBindingsTest);
176
177 class HeadScriptEmbedderMojoBindingsTest : public EmbedderMojoTest {
178 public:
179 HeadScriptEmbedderMojoBindingsTest() {
180 EXPECT_TRUE(embedded_test_server()->Start());
181 }
182
183 void RunMojoTest() override {}
184
185 GURL GetInitialUrl() const override {
186 return embedded_test_server()->GetURL("/mojo_test.html");
187 }
188
189 // embedder_test::TestEmbedderService:
190 void ReturnTestResult(const mojo::String& result) override {
191 EXPECT_EQ("hello world", result.get());
192 FinishAsynchronousTest();
193 }
194 };
195
196 DEVTOOLS_CLIENT_TEST_F(HeadScriptEmbedderMojoBindingsTest);
197
198 class DefaultMojoStyleBindingsTest : public EmbedderMojoTest {
199 public:
200 void RunMojoTest() override {
201 devtools_client_->GetRuntime()->Evaluate(
202 "// Note define() defines a module in the mojo module dependency \n"
203 "// system. While we don't expose our module, the callback below only\n"
204 "// fires after the requested modules have been loaded. \n"
205 "define([ \n"
206 " 'headless/lib/embedder_test.mojom', \n"
207 " 'mojo/public/js/core', \n"
208 " 'mojo/public/js/router', \n"
209 " 'content/public/renderer/frame_service_registry', \n"
210 " ], function(embedderMojom, mojoCore, routerModule, \n"
211 " serviceProvider) { \n"
212 " var testEmbedderService = \n"
213 " new embedderMojom.TestEmbedderService.proxyClass( \n"
214 " new routerModule.Router( \n"
215 " serviceProvider.connectToService( \n"
216 " embedderMojom.TestEmbedderService.name))); \n"
217 " \n"
218 " // Send a message to the embedder! \n"
219 " testEmbedderService.returnTestResult('hello world'); \n"
220 "});",
221 base::Bind(&EmbedderMojoTest::OnEvalResult, base::Unretained(this)));
222 }
223
224 // embedder_test::TestEmbedderService:
225 void ReturnTestResult(const mojo::String& result) override {
226 EXPECT_EQ("hello world", result.get());
227 FinishAsynchronousTest();
228 }
229 };
230
231 DEVTOOLS_CLIENT_TEST_F(DefaultMojoStyleBindingsTest);
232
233 class AssignToMojoServicesProxyNotAllowed : public EmbedderMojoTest {
234 public:
235 void RunMojoTest() override {
236 devtools_client_->GetRuntime()->Evaluate(
237 "mojo.services.foo = 'bar';",
238 base::Bind(&AssignToMojoServicesProxyNotAllowed::OnEvalResult,
239 base::Unretained(this)));
240 }
241
242 void OnEvalResult(std::unique_ptr<runtime::EvaluateResult> result) {
243 ASSERT_TRUE(result->HasExceptionDetails());
244 EXPECT_EQ(
245 "Uncaught Error: Assignment to the mojo services proxy is not allowed",
246 result->GetExceptionDetails()->GetText());
247 FinishAsynchronousTest();
248 }
249
250 void ReturnTestResult(const mojo::String& result) override {}
251 };
252
253 DEVTOOLS_CLIENT_TEST_F(AssignToMojoServicesProxyNotAllowed);
254
255 class AssignToMojoServicesSecondaryProxyNotAllowed : public EmbedderMojoTest {
256 public:
257 void RunMojoTest() override {
258 devtools_client_->GetRuntime()->Evaluate(
259 "mojo.services.foo.bar = 'baz';",
260 base::Bind(&AssignToMojoServicesSecondaryProxyNotAllowed::OnEvalResult,
261 base::Unretained(this)));
262 }
263
264 void OnEvalResult(std::unique_ptr<runtime::EvaluateResult> result) {
265 ASSERT_TRUE(result->HasExceptionDetails());
266 EXPECT_EQ(
267 "Uncaught Error: Assignment to the mojo services proxy is not allowed",
268 result->GetExceptionDetails()->GetText());
269 FinishAsynchronousTest();
270 }
271
272 void ReturnTestResult(const mojo::String& result) override {}
273 };
274
275 DEVTOOLS_CLIENT_TEST_F(AssignToMojoServicesSecondaryProxyNotAllowed);
276
277 class MojoBindingsReinstalledAfterNavigation : public EmbedderMojoTest {
278 public:
279 MojoBindingsReinstalledAfterNavigation() : seen_page_one_(false) {
280 EXPECT_TRUE(embedded_test_server()->Start());
281 }
282
283 void RunMojoTest() override {}
284
285 GURL GetInitialUrl() const override {
286 // Note page_one.html should navigate to page_two.html and ReturnTestResult
287 // should be called once from each.
288 return embedded_test_server()->GetURL("/page_one.html");
289 }
290
291 // embedder_test::TestEmbedderService:
292 void ReturnTestResult(const mojo::String& result) override {
293 if (result.get() == "page one") {
294 seen_page_one_ = true;
295 } else {
296 EXPECT_TRUE(seen_page_one_);
297 EXPECT_EQ("page two", result.get());
298 FinishAsynchronousTest();
299 }
300 }
301
302 private:
303 bool seen_page_one_;
304 };
305
306 DEVTOOLS_CLIENT_TEST_F(MojoBindingsReinstalledAfterNavigation);
307
308 } // namespace headless
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698