Add an ApplicationConnector interface, etc.
Also do a bit of (minimal) cleanup of ApplicationImpl.
From the Shell interface, you can mint ApplicationConnectors, which
allows you to connect to other applications. This is useful if you want
to connect to applications from other threads or other environments
(e.g., inside a VM).
TODO(vtl): Maybe add a Duplicate() to ApplicationConnector. The reason
we don't just add a Duplicate() to Shell is that Shell is associated
with low-level stuff (e.g., process lifetime), and we may want to add
more low-level process-y stuff (which shouldn't be delegated) to it in
the future.
R=jamesr@chromium.org
Review URL: https://codereview.chromium.org/1435153003 .
diff --git a/shell/BUILD.gn b/shell/BUILD.gn
index 0919596..a09eb67 100644
--- a/shell/BUILD.gn
+++ b/shell/BUILD.gn
@@ -650,6 +650,7 @@
"//mojo/public/cpp/bindings:callback",
"//mojo/public/cpp/environment",
"//mojo/public/cpp/system:system",
+ "//mojo/public/interfaces/application",
"//mojo/services/http_server/cpp",
"//mojo/services/http_server/interfaces",
"//mojo/services/network/interfaces",
diff --git a/shell/application_manager/BUILD.gn b/shell/application_manager/BUILD.gn
index 9a9cf0c..dac121c 100644
--- a/shell/application_manager/BUILD.gn
+++ b/shell/application_manager/BUILD.gn
@@ -44,6 +44,7 @@
"//base/third_party/dynamic_annotations",
"//crypto:crypto",
"//url",
+ "//mojo/common",
"//mojo/edk/system",
"//mojo/environment:chromium",
"//mojo/services/content_handler/interfaces",
diff --git a/shell/application_manager/shell_impl.cc b/shell/application_manager/shell_impl.cc
index f75c028..4d0532e 100644
--- a/shell/application_manager/shell_impl.cc
+++ b/shell/application_manager/shell_impl.cc
@@ -21,7 +21,8 @@
identity_(identity),
on_application_end_(on_application_end),
application_(application.Pass()),
- binding_(this) {
+ binding_(this),
+ application_connector_impl_(this) {
binding_.set_connection_error_handler(
[this]() { manager_->OnShellImplError(this); });
}
@@ -45,7 +46,6 @@
requested_url.spec());
}
-// Shell implementation:
void ShellImpl::ConnectToApplication(
const mojo::String& app_url,
mojo::InterfaceRequest<ServiceProvider> services,
@@ -59,4 +59,11 @@
exposed_services.Pass(), base::Closure());
}
+void ShellImpl::CreateApplicationConnector(
+ mojo::InterfaceRequest<mojo::ApplicationConnector>
+ application_connector_request) {
+ application_connectors_.AddBinding(&application_connector_impl_,
+ application_connector_request.Pass());
+}
+
} // namespace shell
diff --git a/shell/application_manager/shell_impl.h b/shell/application_manager/shell_impl.h
index 0155720..2fc4846 100644
--- a/shell/application_manager/shell_impl.h
+++ b/shell/application_manager/shell_impl.h
@@ -6,8 +6,11 @@
#define SHELL_APPLICATION_MANAGER_SHELL_IMPL_H_
#include "base/callback.h"
+#include "base/macros.h"
+#include "mojo/common/binding_set.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/interfaces/application/application.mojom.h"
+#include "mojo/public/interfaces/application/application_connector.mojom.h"
#include "mojo/public/interfaces/application/shell.mojom.h"
#include "shell/application_manager/identity.h"
#include "url/gurl.h"
@@ -16,6 +19,11 @@
class ApplicationManager;
+// TODO(vtl): This both implements the |Shell| interface and holds the
+// |ApplicationPtr| (from back when they were paired interfaces on the same
+// message pipe). The way it manages lifetime is dubious/wrong. We should have
+// an object holding stuff associated to an application, namely its "real"
+// |ShellImpl|, its |ApplicationPtr|, and tracking its |ApplicationConnector|s.
class ShellImpl : public mojo::Shell {
public:
ShellImpl(mojo::ApplicationPtr application,
@@ -37,11 +45,32 @@
base::Closure on_application_end() const { return on_application_end_; }
private:
+ class ApplicationConnectorImpl : public mojo::ApplicationConnector {
+ public:
+ explicit ApplicationConnectorImpl(mojo::Shell* shell) : shell_(shell) {}
+ ~ApplicationConnectorImpl() override {}
+
+ void ConnectToApplication(
+ const mojo::String& app_url,
+ mojo::InterfaceRequest<mojo::ServiceProvider> services,
+ mojo::ServiceProviderPtr exposed_services) override {
+ shell_->ConnectToApplication(app_url, services.Pass(),
+ exposed_services.Pass());
+ }
+
+ private:
+ mojo::Shell* const shell_;
+ DISALLOW_COPY_AND_ASSIGN(ApplicationConnectorImpl);
+ };
+
// mojo::Shell implementation:
void ConnectToApplication(
const mojo::String& app_url,
mojo::InterfaceRequest<mojo::ServiceProvider> services,
mojo::ServiceProviderPtr exposed_services) override;
+ void CreateApplicationConnector(
+ mojo::InterfaceRequest<mojo::ApplicationConnector>
+ application_connector_request) override;
ApplicationManager* const manager_;
const Identity identity_;
@@ -49,6 +78,9 @@
mojo::ApplicationPtr application_;
mojo::Binding<mojo::Shell> binding_;
+ ApplicationConnectorImpl application_connector_impl_;
+ mojo::BindingSet<mojo::ApplicationConnector> application_connectors_;
+
DISALLOW_COPY_AND_ASSIGN(ShellImpl);
};
diff --git a/shell/shell_apptest.cc b/shell/shell_apptest.cc
index 1011e24..7bc5e85 100644
--- a/shell/shell_apptest.cc
+++ b/shell/shell_apptest.cc
@@ -13,7 +13,9 @@
#include "mojo/data_pipe_utils/data_pipe_utils.h"
#include "mojo/public/cpp/application/application_impl.h"
#include "mojo/public/cpp/application/application_test_base.h"
+#include "mojo/public/cpp/application/connect.h"
#include "mojo/public/cpp/system/macros.h"
+#include "mojo/public/interfaces/application/application_connector.mojom.h"
#include "mojo/services/http_server/cpp/http_server_util.h"
#include "mojo/services/http_server/interfaces/http_server.mojom.h"
#include "mojo/services/http_server/interfaces/http_server_factory.mojom.h"
@@ -195,4 +197,21 @@
base::RunLoop().Run();
}
+TEST_F(ShellAppTest, ApplicationConnector) {
+ mojo::ApplicationConnectorPtr app_connector;
+ app_connector.Bind(application_impl()->CreateApplicationConnector());
+
+ PingablePtr pingable;
+ ConnectToService(app_connector.get(), "mojo:pingable_app", &pingable);
+ auto callback = [this](const String& app_url, const String& connection_url,
+ const String& message) {
+ EXPECT_TRUE(EndsWith(app_url, "/pingable_app.mojo", true));
+ EXPECT_EQ(app_url, connection_url);
+ EXPECT_EQ("hello", message);
+ base::MessageLoop::current()->Quit();
+ };
+ pingable->Ping("hello", callback);
+ base::RunLoop().Run();
+}
+
} // namespace