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

Unified 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: Refactored the JS for clarity 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 side-by-side diff with in-line comments
Download patch
Index: headless/lib/embedder_mojo_browsertest.cc
diff --git a/headless/lib/embedder_mojo_browsertest.cc b/headless/lib/embedder_mojo_browsertest.cc
new file mode 100644
index 0000000000000000000000000000000000000000..94158f771eb87a860614e0390f89192b88e214c1
--- /dev/null
+++ b/headless/lib/embedder_mojo_browsertest.cc
@@ -0,0 +1,226 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include "content/public/test/browser_test.h"
+#include "headless/grit/headless_browsertest_resources.h"
+#include "headless/lib/embedder_test.mojom.h"
+#include "headless/public/domains/runtime.h"
+#include "headless/public/headless_browser.h"
+#include "headless/public/headless_devtools_client.h"
+#include "headless/public/headless_devtools_target.h"
+#include "headless/public/headless_web_contents.h"
+#include "headless/test/headless_browser_test.h"
+#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/bindings/interface_ptr_set.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/resource/resource_bundle.h"
+#include "url/gurl.h"
+
+namespace headless {
+
+#define DEVTOOLS_CLIENT_TEST_F(TEST_FIXTURE_NAME) \
+ IN_PROC_BROWSER_TEST_F(TEST_FIXTURE_NAME, RunAsyncTest) { RunTest(); } \
+ class AsyncHeadlessBrowserTestNeedsSemicolon##TEST_FIXTURE_NAME {}
+
+// A test fixture which attaches a devtools client before starting the test.
+class EmbedderMojoTest : public HeadlessBrowserTest,
+ public HeadlessWebContents::Observer,
+ public embedder_test::TestEmbedderService {
+ public:
+ EmbedderMojoTest()
+ : web_contents_(nullptr),
+ devtools_client_(HeadlessDevToolsClient::Create()) {}
+ ~EmbedderMojoTest() override {}
+
+ // HeadlessWebContentsObserver implementation:
+ void DevToolsTargetReady() override {
+ EXPECT_TRUE(web_contents_->GetDevToolsTarget());
+ web_contents_->GetDevToolsTarget()->AttachClient(devtools_client_.get());
+
+ RunMojoTest();
+ }
+
+ virtual void RunMojoTest() = 0;
+
+ virtual GURL GetInitialUrl() const { return GURL("about:blank"); }
+
+ void OnEvalResult(std::unique_ptr<runtime::EvaluateResult> result) {
+ EXPECT_FALSE(result->HasExceptionDetails())
+ << "JS exception: " << result->GetExceptionDetails()->GetText();
+ if (result->HasExceptionDetails()) {
+ FinishAsynchronousTest();
+ }
+ }
+
+ protected:
+ void RunTest() {
+ std::string embedder_test_mojom_js =
+ ResourceBundle::GetSharedInstance()
+ .GetRawDataResource(IDR_HEADLESS_EMBEDDER_TEST_MOJOM_JS)
+ .as_string();
Sami 2016/06/20 16:58:16 Idle thought: normal headless embedders probably w
alex clarke (OOO till 29th) 2016/06/20 23:19:13 Right but the API doesn't mention them? :)
Sami 2016/06/21 10:22:26 Yep, and we should probably keep it that way.
+ web_contents_ =
+ browser()
+ ->CreateWebContentsBuilder()
+ .SetInitialURL(GURL(GetInitialUrl()))
+ .AddMojoService(base::Bind(&EmbedderMojoTest::CreateTestMojoService,
+ base::Unretained(this)))
+ .AddJsMojoBindings("headless/lib/embedder_test.mojom",
+ embedder_test_mojom_js)
+ .Build();
+
+ web_contents_->AddObserver(this);
+ RunAsynchronousTest();
+
+ web_contents_->GetDevToolsTarget()->DetachClient(devtools_client_.get());
+ web_contents_->RemoveObserver(this);
+ web_contents_->Close();
+ web_contents_ = nullptr;
+ }
+
+ void CreateTestMojoService(
+ mojo::InterfaceRequest<embedder_test::TestEmbedderService> request) {
+ test_embedder_mojo_bindings_.AddBinding(this, std::move(request));
+ }
+
+ HeadlessWebContents* web_contents_;
+ std::unique_ptr<HeadlessDevToolsClient> devtools_client_;
+
+ mojo::BindingSet<embedder_test::TestEmbedderService>
+ test_embedder_mojo_bindings_;
+};
+
+class EmbedderMojoBindingsTest : public EmbedderMojoTest {
+ public:
+ void RunMojoTest() override {
+ devtools_client_->GetRuntime()->Evaluate(
+ R"(
+ mojo.services.embedder_test.TestEmbedderService.then(function(service) {
+ service.returnTestResult("hello world");
+ }); )",
+ base::Bind(&EmbedderMojoTest::OnEvalResult, base::Unretained(this)));
+ }
+
+ // embedder_test::TestEmbedderService:
+ void ReturnTestResult(const mojo::String& result) override {
+ EXPECT_EQ("hello world", result.get());
+ FinishAsynchronousTest();
+ }
+};
+
+DEVTOOLS_CLIENT_TEST_F(EmbedderMojoBindingsTest);
+
+class RejectNonExistantBindingsTest : public EmbedderMojoTest {
Sami 2016/06/20 16:58:16 typo: Nonexistent (couple other instances too)
alex clarke (OOO till 29th) 2016/06/20 23:19:13 Done.
+ public:
+ void RunMojoTest() override {
+ devtools_client_->GetRuntime()->Evaluate(
+ R"(
+ mojo.services.embedder_test.TestEmbedderService.then(function(service) {
+ mojo.services.nonExistant.MojoService.then(function() {
+ service.returnTestResult("Fail - promise not rejected");
+ }).catch(function() {
+ service.returnTestResult("Pass - promise rejected");
+ });
+ }); )",
+ base::Bind(&EmbedderMojoTest::OnEvalResult, base::Unretained(this)));
+ }
+
+ // embedder_test::TestEmbedderService:
+ void ReturnTestResult(const mojo::String& result) override {
+ EXPECT_EQ("Pass - promise rejected", result.get());
+ FinishAsynchronousTest();
+ }
+};
+
+DEVTOOLS_CLIENT_TEST_F(RejectNonExistantBindingsTest);
+
+// Test bindings that occur after the onload event, which is after the browser
+// has sent us the bindings.
+class DelayedRejectNonExistantBindingsTest : public EmbedderMojoTest {
+ public:
+ void RunMojoTest() override {
+ devtools_client_->GetRuntime()->Evaluate(
+ R"(
+ // Make sure our test code runs after the onload event.
+ requestAnimationFrame(function() {
Sami 2016/06/20 16:58:16 rAF can be triggered before the onload. Maybe sche
alex clarke (OOO till 29th) 2016/06/20 23:19:13 Done.
+ mojo.services.embedder_test.TestEmbedderService.then(
+ function(service) {
+ mojo.services.nonExistant.MojoService.then(function() {
+ service.returnTestResult("Fail - promise not rejected");
+ }).catch(function() {
+ service.returnTestResult("Pass - promise rejected");
+ });
+ });
+ }); )",
+ base::Bind(&EmbedderMojoTest::OnEvalResult, base::Unretained(this)));
+ }
+
+ // embedder_test::TestEmbedderService:
+ void ReturnTestResult(const mojo::String& result) override {
+ EXPECT_EQ("Pass - promise rejected", result.get());
+ FinishAsynchronousTest();
+ }
+};
+
+DEVTOOLS_CLIENT_TEST_F(DelayedRejectNonExistantBindingsTest);
+
+class HeadScriptEmbedderMojoBindingsTest : public EmbedderMojoTest {
+ public:
+ HeadScriptEmbedderMojoBindingsTest() {
+ EXPECT_TRUE(embedded_test_server()->Start());
+ }
+
+ void RunMojoTest() override {}
+
+ GURL GetInitialUrl() const override {
+ return embedded_test_server()->GetURL("/mojo_test.html");
+ }
+
+ // embedder_test::TestEmbedderService:
+ void ReturnTestResult(const mojo::String& result) override {
+ EXPECT_EQ("hello world", result.get());
+ FinishAsynchronousTest();
+ }
+};
+
+DEVTOOLS_CLIENT_TEST_F(HeadScriptEmbedderMojoBindingsTest);
+
+class DefaultMojoStyleBindingsTest : public EmbedderMojoTest {
+ public:
+ void RunMojoTest() override {
+ devtools_client_->GetRuntime()->Evaluate(
+ R"(
+ // Note define() defines a module in the mojo module dependency
+ // system. While we don't expose our module, the callback below only
+ // fires after the requested modules have been loaded.
+ define([
+ "headless/lib/embedder_test.mojom",
+ "mojo/public/js/core",
+ "mojo/public/js/router",
+ "content/public/renderer/frame_service_registry",
+ ], function(embedderMojom, mojoCore, routerModule,
+ serviceProvider) {
+ var testEmbedderService =
+ new embedderMojom.TestEmbedderService.proxyClass(
+ new routerModule.Router(
+ serviceProvider.connectToService(
+ embedderMojom.TestEmbedderService.name)));
+
+ // Send a message to the embedder!
+ testEmbedderService.returnTestResult("hello world");
+ }); )",
+ base::Bind(&EmbedderMojoTest::OnEvalResult, base::Unretained(this)));
+ }
+
+ // embedder_test::TestEmbedderService:
+ void ReturnTestResult(const mojo::String& result) override {
+ EXPECT_EQ("hello world", result.get());
+ FinishAsynchronousTest();
+ }
+};
+
+DEVTOOLS_CLIENT_TEST_F(DefaultMojoStyleBindingsTest);
+
+} // namespace headless

Powered by Google App Engine
This is Rietveld 408576698