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

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: Seems we need a new OWNERS file 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 R"(
114 mojo.services.embedder_test.TestEmbedderService.then(function(service) {
115 service.returnTestResult("hello world");
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 R"(
134 mojo.services.embedder_test.TestEmbedderService.then(function(service) {
135 mojo.services.nonExistent.MojoService.then(function() {
136 service.returnTestResult("Fail - promise not rejected");
137 }).catch(function() {
138 service.returnTestResult("Pass - promise rejected");
139 });
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 R"(
203 // Note define() defines a module in the mojo module dependency
204 // system. While we don't expose our module, the callback below only
205 // fires after the requested modules have been loaded.
206 define([
207 "headless/lib/embedder_test.mojom",
208 "mojo/public/js/core",
209 "mojo/public/js/router",
210 "content/public/renderer/frame_service_registry",
211 ], function(embedderMojom, mojoCore, routerModule,
212 serviceProvider) {
213 var testEmbedderService =
214 new embedderMojom.TestEmbedderService.proxyClass(
215 new routerModule.Router(
216 serviceProvider.connectToService(
217 embedderMojom.TestEmbedderService.name)));
218
219 // Send a message to the embedder!
220 testEmbedderService.returnTestResult("hello world");
221 }); )",
222 base::Bind(&EmbedderMojoTest::OnEvalResult, base::Unretained(this)));
223 }
224
225 // embedder_test::TestEmbedderService:
226 void ReturnTestResult(const mojo::String& result) override {
227 EXPECT_EQ("hello world", result.get());
228 FinishAsynchronousTest();
229 }
230 };
231
232 DEVTOOLS_CLIENT_TEST_F(DefaultMojoStyleBindingsTest);
233
234 class AssignToMojoServicesProxyNotAllowed : public EmbedderMojoTest {
235 public:
236 void RunMojoTest() override {
237 devtools_client_->GetRuntime()->Evaluate(
238 "mojo.services.foo = 'bar';",
239 base::Bind(&AssignToMojoServicesProxyNotAllowed::OnEvalResult,
240 base::Unretained(this)));
241 }
242
243 void OnEvalResult(std::unique_ptr<runtime::EvaluateResult> result) {
244 ASSERT_TRUE(result->HasExceptionDetails());
245 EXPECT_EQ(
246 "Uncaught Error: Assignment to the mojo services proxy is not allowed",
247 result->GetExceptionDetails()->GetText());
248 FinishAsynchronousTest();
249 }
250
251 void ReturnTestResult(const mojo::String& result) override {}
252 };
253
254 DEVTOOLS_CLIENT_TEST_F(AssignToMojoServicesProxyNotAllowed);
255
256 class AssignToMojoServicesSecondaryProxyNotAllowed : public EmbedderMojoTest {
257 public:
258 void RunMojoTest() override {
259 devtools_client_->GetRuntime()->Evaluate(
260 "mojo.services.foo.bar = 'baz';",
261 base::Bind(&AssignToMojoServicesSecondaryProxyNotAllowed::OnEvalResult,
262 base::Unretained(this)));
263 }
264
265 void OnEvalResult(std::unique_ptr<runtime::EvaluateResult> result) {
266 ASSERT_TRUE(result->HasExceptionDetails());
267 EXPECT_EQ(
268 "Uncaught Error: Assignment to the mojo services proxy is not allowed",
269 result->GetExceptionDetails()->GetText());
270 FinishAsynchronousTest();
271 }
272
273 void ReturnTestResult(const mojo::String& result) override {}
274 };
275
276 DEVTOOLS_CLIENT_TEST_F(AssignToMojoServicesSecondaryProxyNotAllowed);
277
278 } // namespace headless
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698