summaryrefslogtreecommitdiffstats
path: root/mojo/application
diff options
context:
space:
mode:
authorjam <jam@chromium.org>2015-05-14 15:56:10 -0700
committerCommit bot <commit-bot@chromium.org>2015-05-14 22:56:18 +0000
commit05a3de409c2653028aede6a467bb70c0addf57fc (patch)
tree77329d790a38ff6aed7d8f9ae1d17e169887057a /mojo/application
parent067d014b8f1918db09939aa765bdfa7576ab3d50 (diff)
downloadchromium_src-05a3de409c2653028aede6a467bb70c0addf57fc.zip
chromium_src-05a3de409c2653028aede6a467bb70c0addf57fc.tar.gz
chromium_src-05a3de409c2653028aede6a467bb70c0addf57fc.tar.bz2
Fork the mojo shell interfaces used by Mandoline.
Per in-person discussions, as long as we have a fork of mojo shell we'll fork the interfaces. I'll do third_party/mojo/src/mojo/public/java/application in a followup. TBR=tsepez Review URL: https://codereview.chromium.org/1139123006 Cr-Commit-Position: refs/heads/master@{#329965}
Diffstat (limited to 'mojo/application')
-rw-r--r--mojo/application/BUILD.gn6
-rw-r--r--mojo/application/application_runner_chromium.cc4
-rw-r--r--mojo/application/application_test_base_chromium.cc4
-rw-r--r--mojo/application/application_test_base_chromium.h4
-rw-r--r--mojo/application/content_handler_factory.cc8
-rw-r--r--mojo/application/content_handler_factory.h4
-rw-r--r--mojo/application/public/cpp/BUILD.gn99
-rw-r--r--mojo/application/public/cpp/application_connection.h98
-rw-r--r--mojo/application/public/cpp/application_delegate.h47
-rw-r--r--mojo/application/public/cpp/application_impl.h140
-rw-r--r--mojo/application/public/cpp/application_runner.h44
-rw-r--r--mojo/application/public/cpp/application_test_base.h62
-rw-r--r--mojo/application/public/cpp/connect.h23
-rw-r--r--mojo/application/public/cpp/interface_factory.h31
-rw-r--r--mojo/application/public/cpp/interface_factory_impl.h49
-rw-r--r--mojo/application/public/cpp/lazy_interface_ptr.h46
-rw-r--r--mojo/application/public/cpp/lib/application_connection.cc12
-rw-r--r--mojo/application/public/cpp/lib/application_delegate.cc30
-rw-r--r--mojo/application/public/cpp/lib/application_impl.cc117
-rw-r--r--mojo/application/public/cpp/lib/application_runner.cc40
-rw-r--r--mojo/application/public/cpp/lib/application_test_base.cc165
-rw-r--r--mojo/application/public/cpp/lib/application_test_main.cc14
-rw-r--r--mojo/application/public/cpp/lib/interface_factory_connector.h37
-rw-r--r--mojo/application/public/cpp/lib/service_connector_registry.cc59
-rw-r--r--mojo/application/public/cpp/lib/service_connector_registry.h62
-rw-r--r--mojo/application/public/cpp/lib/service_provider_impl.cc48
-rw-r--r--mojo/application/public/cpp/lib/service_registry.cc73
-rw-r--r--mojo/application/public/cpp/lib/service_registry.h67
-rw-r--r--mojo/application/public/cpp/service_connector.h30
-rw-r--r--mojo/application/public/cpp/service_provider_impl.h53
-rw-r--r--mojo/application/public/cpp/tests/BUILD.gn19
-rw-r--r--mojo/application/public/cpp/tests/service_registry_unittest.cc70
-rw-r--r--mojo/application/public/interfaces/BUILD.gn14
-rw-r--r--mojo/application/public/interfaces/application.mojom59
-rw-r--r--mojo/application/public/interfaces/service_provider.mojom17
-rw-r--r--mojo/application/public/interfaces/shell.mojom38
36 files changed, 1678 insertions, 15 deletions
diff --git a/mojo/application/BUILD.gn b/mojo/application/BUILD.gn
index 958d87b..5800c0c 100644
--- a/mojo/application/BUILD.gn
+++ b/mojo/application/BUILD.gn
@@ -10,7 +10,7 @@ source_set("application") {
]
public_deps = [
- "//third_party/mojo/src/mojo/public/cpp/application",
+ "//mojo/application/public/cpp:application",
]
deps = [
"//base",
@@ -27,9 +27,9 @@ source_set("content_handler") {
deps = [
":application",
"//base",
+ "//mojo/application/public/interfaces",
"//mojo/common",
"//mojo/environment:chromium",
- "//third_party/mojo/src/mojo/public/interfaces/application",
"//third_party/mojo_services/src/content_handler/public/interfaces",
"//mojo/services/network/public/interfaces",
]
@@ -46,7 +46,7 @@ source_set("test_support") {
deps = [
"//base",
"//base/test:test_support",
- "//third_party/mojo/src/mojo/public/cpp/application:application",
+ "//mojo/application/public/cpp:application",
"//third_party/mojo/src/mojo/public/cpp/bindings",
"//third_party/mojo/src/mojo/public/cpp/environment",
"//third_party/mojo/src/mojo/public/cpp/system",
diff --git a/mojo/application/application_runner_chromium.cc b/mojo/application/application_runner_chromium.cc
index e5f21ca..35d945d 100644
--- a/mojo/application/application_runner_chromium.cc
+++ b/mojo/application/application_runner_chromium.cc
@@ -9,9 +9,9 @@
#include "base/debug/stack_trace.h"
#include "base/memory/scoped_ptr.h"
#include "base/message_loop/message_loop.h"
+#include "mojo/application/public/cpp/application_delegate.h"
+#include "mojo/application/public/cpp/application_impl.h"
#include "mojo/common/message_pump_mojo.h"
-#include "mojo/public/cpp/application/application_delegate.h"
-#include "mojo/public/cpp/application/application_impl.h"
int g_argc;
const char* const* g_argv;
diff --git a/mojo/application/application_test_base_chromium.cc b/mojo/application/application_test_base_chromium.cc
index 72bf189..bb9afa1 100644
--- a/mojo/application/application_test_base_chromium.cc
+++ b/mojo/application/application_test_base_chromium.cc
@@ -6,11 +6,11 @@
#include "base/command_line.h"
#include "base/strings/utf_string_conversions.h"
-#include "mojo/public/cpp/application/application_impl.h"
+#include "mojo/application/public/cpp/application_impl.h"
+#include "mojo/application/public/interfaces/application.mojom.h"
#include "mojo/public/cpp/bindings/binding.h"
#include "mojo/public/cpp/environment/environment.h"
#include "mojo/public/cpp/system/message_pipe.h"
-#include "mojo/public/interfaces/application/application.mojom.h"
namespace mojo {
namespace test {
diff --git a/mojo/application/application_test_base_chromium.h b/mojo/application/application_test_base_chromium.h
index c050848..ee17e42 100644
--- a/mojo/application/application_test_base_chromium.h
+++ b/mojo/application/application_test_base_chromium.h
@@ -5,11 +5,11 @@
#ifndef MOJO_APPLICATION_APPLICATION_TEST_BASE_CHROMIUM_H_
#define MOJO_APPLICATION_APPLICATION_TEST_BASE_CHROMIUM_H_
-#include "mojo/public/cpp/application/application_delegate.h"
+#include "mojo/application/public/cpp/application_delegate.h"
+#include "mojo/application/public/interfaces/application.mojom.h"
#include "mojo/public/cpp/bindings/array.h"
#include "mojo/public/cpp/bindings/string.h"
#include "mojo/public/cpp/system/macros.h"
-#include "mojo/public/interfaces/application/application.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
namespace mojo {
diff --git a/mojo/application/content_handler_factory.cc b/mojo/application/content_handler_factory.cc
index 8518f4c..9fac371 100644
--- a/mojo/application/content_handler_factory.cc
+++ b/mojo/application/content_handler_factory.cc
@@ -11,11 +11,11 @@
#include "base/memory/weak_ptr.h"
#include "base/threading/platform_thread.h"
#include "mojo/application/application_runner_chromium.h"
+#include "mojo/application/public/cpp/application_connection.h"
+#include "mojo/application/public/cpp/application_delegate.h"
+#include "mojo/application/public/cpp/application_impl.h"
+#include "mojo/application/public/cpp/interface_factory_impl.h"
#include "mojo/common/message_pump_mojo.h"
-#include "mojo/public/cpp/application/application_connection.h"
-#include "mojo/public/cpp/application/application_delegate.h"
-#include "mojo/public/cpp/application/application_impl.h"
-#include "mojo/public/cpp/application/interface_factory_impl.h"
#include "mojo/public/cpp/bindings/strong_binding.h"
namespace mojo {
diff --git a/mojo/application/content_handler_factory.h b/mojo/application/content_handler_factory.h
index aabba6f..25ee2be 100644
--- a/mojo/application/content_handler_factory.h
+++ b/mojo/application/content_handler_factory.h
@@ -6,8 +6,8 @@
#define MOJO_APPLICATION_CONTENT_HANDLER_FACTORY_H_
#include "base/memory/scoped_ptr.h"
-#include "mojo/public/cpp/application/interface_factory.h"
-#include "mojo/public/interfaces/application/shell.mojom.h"
+#include "mojo/application/public/cpp/interface_factory.h"
+#include "mojo/application/public/interfaces/shell.mojom.h"
#include "mojo/services/network/public/interfaces/url_loader.mojom.h"
#include "third_party/mojo_services/src/content_handler/public/interfaces/content_handler.mojom.h"
diff --git a/mojo/application/public/cpp/BUILD.gn b/mojo/application/public/cpp/BUILD.gn
new file mode 100644
index 0000000..796f615
--- /dev/null
+++ b/mojo/application/public/cpp/BUILD.gn
@@ -0,0 +1,99 @@
+# Copyright 2014 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.
+
+import("//third_party/mojo/src/mojo/public/mojo_sdk.gni")
+
+# GYP version: mojo/mojo_base.gyp:mojo_application_base
+mojo_sdk_source_set("application") {
+ restrict_external_deps = false
+ sources = [
+ "application_connection.h",
+ "application_delegate.h",
+ "application_impl.h",
+ "connect.h",
+ "interface_factory.h",
+ "interface_factory_impl.h",
+ "lib/application_connection.cc",
+ "lib/application_delegate.cc",
+ "lib/application_impl.cc",
+ "lib/interface_factory_connector.h",
+ "lib/service_connector_registry.cc",
+ "lib/service_connector_registry.h",
+ "lib/service_provider_impl.cc",
+ "lib/service_registry.cc",
+ "lib/service_registry.h",
+ "service_connector.h",
+ "service_provider_impl.h",
+ ]
+
+ deps = [
+ "//mojo/application/public/interfaces",
+ ]
+
+ mojo_sdk_deps = [
+ "mojo/public/cpp/bindings",
+ "mojo/public/cpp/environment",
+ "mojo/public/cpp/system",
+ ]
+}
+
+# GYP version: mojo/mojo_base.gyp:mojo_application_standalone
+mojo_sdk_source_set("standalone") {
+ sources = [
+ "lib/application_runner.cc",
+ ]
+
+ public_deps = [
+ ":application",
+ ]
+
+ mojo_sdk_deps = [
+ "mojo/public/cpp/environment:standalone",
+ "mojo/public/cpp/utility",
+ ]
+}
+
+mojo_sdk_source_set("test_support") {
+ testonly = true
+ restrict_external_deps = false
+ sources = [
+ "application_test_base.h",
+ "lib/application_test_base.cc",
+ ]
+
+ deps = [
+ ":application",
+ "//mojo/application/public/interfaces",
+ "//testing/gtest",
+ ]
+
+ mojo_sdk_deps = [
+ "mojo/public/cpp/bindings",
+ "mojo/public/cpp/environment",
+ "mojo/public/cpp/system",
+ ]
+}
+
+mojo_sdk_source_set("test_support_standalone") {
+ testonly = true
+ restrict_external_deps = false
+ sources = [
+ "lib/application_test_main.cc",
+ ]
+
+ public_deps = [
+ ":test_support",
+ ]
+
+ deps = [
+ ":application",
+ "//mojo/application/public/interfaces",
+ ]
+
+ mojo_sdk_deps = [
+ "mojo/public/cpp/environment:standalone",
+ "mojo/public/cpp/system",
+ "mojo/public/cpp/utility",
+ ]
+}
diff --git a/mojo/application/public/cpp/application_connection.h b/mojo/application/public/cpp/application_connection.h
new file mode 100644
index 0000000..ff900d3
--- /dev/null
+++ b/mojo/application/public/cpp/application_connection.h
@@ -0,0 +1,98 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_CONNECTION_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_CONNECTION_H_
+
+#include <string>
+
+#include "mojo/application/public/cpp/lib/interface_factory_connector.h"
+#include "mojo/application/public/interfaces/service_provider.mojom.h"
+
+namespace mojo {
+
+class ServiceConnector;
+
+// Represents a connection to another application. An instance of this class is
+// passed to ApplicationDelegate's ConfigureIncomingConnection() method each
+// time a connection is made to this app, and to ApplicationDelegate's
+// ConfigureOutgoingConnection() method when the app connects to another.
+//
+// To use, define a class that implements your specific service API (e.g.,
+// FooImpl to implement a service named Foo). Then implement an
+// InterfaceFactory<Foo> that binds instances of FooImpl to
+// InterfaceRequest<Foo>s and register that on the connection like this:
+//
+// connection->AddService(&factory);
+//
+// Or, if you have multiple factories implemented by the same type, explicitly
+// specify the interface to register the factory for:
+//
+// connection->AddService<Foo>(&my_foo_and_bar_factory_);
+// connection->AddService<Bar>(&my_foo_and_bar_factory_);
+//
+// The InterfaceFactory must outlive the ApplicationConnection.
+//
+// Additionally you specify a ServiceConnector. If a ServiceConnector has
+// been set and an InterfaceFactory has not been registered for the interface
+// request, than the interface request is sent to the ServiceConnector.
+//
+// Just as with InterfaceFactory, ServiceConnector must outlive
+// ApplicationConnection.
+class ApplicationConnection {
+ public:
+ virtual ~ApplicationConnection();
+
+ // See class description for details.
+ virtual void SetServiceConnector(ServiceConnector* connector) = 0;
+
+ // Makes Interface available as a service to the remote application.
+ // |factory| will create implementations of Interface on demand.
+ template <typename Interface>
+ void AddService(InterfaceFactory<Interface>* factory) {
+ SetServiceConnectorForName(
+ new internal::InterfaceFactoryConnector<Interface>(factory),
+ Interface::Name_);
+ }
+
+ // Binds |ptr| to an implemention of Interface in the remote application.
+ // |ptr| can immediately be used to start sending requests to the remote
+ // service.
+ template <typename Interface>
+ void ConnectToService(InterfacePtr<Interface>* ptr) {
+ if (ServiceProvider* sp = GetServiceProvider()) {
+ MessagePipe pipe;
+ ptr->Bind(InterfacePtrInfo<Interface>(pipe.handle0.Pass(), 0u));
+ sp->ConnectToService(Interface::Name_, pipe.handle1.Pass());
+ }
+ }
+
+ // Returns the URL that was used by the source application to establish a
+ // connection to the destination application.
+ //
+ // When ApplicationConnection is representing an incoming connection this can
+ // be different than the URL the application was initially loaded from, if the
+ // application handles multiple URLs. Note that this is the URL after all
+ // URL rewriting and HTTP redirects have been performed.
+ //
+ // When ApplicationConnection is representing and outgoing connection, this
+ // will be the same as the value returned by GetRemoveApplicationURL().
+ virtual const std::string& GetConnectionURL() = 0;
+
+ // Returns the URL identifying the remote application on this connection.
+ virtual const std::string& GetRemoteApplicationURL() = 0;
+
+ // Returns the raw proxy to the remote application's ServiceProvider
+ // interface. Most applications will just use ConnectToService() instead.
+ // Caller does not take ownership.
+ virtual ServiceProvider* GetServiceProvider() = 0;
+
+ private:
+ virtual void SetServiceConnectorForName(ServiceConnector* service_connector,
+ const std::string& name) = 0;
+};
+
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_CONNECTION_H_
diff --git a/mojo/application/public/cpp/application_delegate.h b/mojo/application/public/cpp/application_delegate.h
new file mode 100644
index 0000000..2c3423f
--- /dev/null
+++ b/mojo/application/public/cpp/application_delegate.h
@@ -0,0 +1,47 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_DELEGATE_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_DELEGATE_H_
+
+#include <string>
+
+#include "mojo/public/cpp/system/macros.h"
+
+namespace mojo {
+
+class ApplicationConnection;
+class ApplicationImpl;
+
+// An abstract class that the application may subclass to control various
+// behaviors of ApplicationImpl.
+class ApplicationDelegate {
+ public:
+ ApplicationDelegate();
+ virtual ~ApplicationDelegate();
+
+ // Called exactly once before any other method.
+ virtual void Initialize(ApplicationImpl* app);
+
+ // Override this method to configure what services a connection supports when
+ // being connected to from an app.
+ // Return false to reject the connection entirely.
+ virtual bool ConfigureIncomingConnection(ApplicationConnection* connection);
+
+ // Override this method to configure what services a connection supports when
+ // connecting to another app.
+ // Return false to reject the connection entirely.
+ virtual bool ConfigureOutgoingConnection(ApplicationConnection* connection);
+
+ // Called before ApplicationImpl::Terminate(). After returning from this call
+ // the delegate can no longer rely on the main run loop still running.
+ virtual void Quit();
+
+ private:
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ApplicationDelegate);
+};
+
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_DELEGATE_H_
diff --git a/mojo/application/public/cpp/application_impl.h b/mojo/application/public/cpp/application_impl.h
new file mode 100644
index 0000000..a5d58f50
--- /dev/null
+++ b/mojo/application/public/cpp/application_impl.h
@@ -0,0 +1,140 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_IMPL_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_IMPL_H_
+
+#include <vector>
+
+#include "mojo/application/public/cpp/application_connection.h"
+#include "mojo/application/public/cpp/application_delegate.h"
+#include "mojo/application/public/cpp/lib/service_registry.h"
+#include "mojo/application/public/interfaces/application.mojom.h"
+#include "mojo/application/public/interfaces/shell.mojom.h"
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+
+// Utility class for communicating with the Shell, and providing Services
+// to clients.
+//
+// To use define a class that implements your specific server api, e.g. FooImpl
+// to implement a service named Foo.
+// That class must subclass an InterfaceImpl specialization.
+//
+// If there is context that is to be shared amongst all instances, define a
+// constructor with that class as its only argument, otherwise define an empty
+// constructor.
+//
+// class FooImpl : public InterfaceImpl<Foo> {
+// public:
+// FooImpl(ApplicationContext* app_context) {}
+// };
+//
+// or
+//
+// class BarImpl : public InterfaceImpl<Bar> {
+// public:
+// // contexts will remain valid for the lifetime of BarImpl.
+// BarImpl(ApplicationContext* app_context, BarContext* service_context)
+// : app_context_(app_context), servicecontext_(context) {}
+//
+// Create an ApplicationImpl instance that collects any service implementations.
+//
+// ApplicationImpl app(service_provider_handle);
+// app.AddService<FooImpl>();
+//
+// BarContext context;
+// app.AddService<BarImpl>(&context);
+//
+//
+class ApplicationImpl : public Application {
+ public:
+ // Does not take ownership of |delegate|, which must remain valid for the
+ // lifetime of ApplicationImpl.
+ ApplicationImpl(ApplicationDelegate* delegate,
+ InterfaceRequest<Application> request);
+ ~ApplicationImpl() override;
+
+ // The Mojo shell. This will return a valid pointer after Initialize() has
+ // been invoked. It will remain valid until UnbindConnections() is invoked or
+ // the ApplicationImpl is destroyed.
+ Shell* shell() const { return shell_.get(); }
+
+ const std::string& url() const { return url_; }
+
+ // Returns any initial configuration arguments, passed by the Shell.
+ const std::vector<std::string>& args() const { return args_; }
+ bool HasArg(const std::string& arg) const;
+
+ // Requests a new connection to an application. Returns a pointer to the
+ // connection if the connection is permitted by this application's delegate,
+ // or nullptr otherwise. Caller does not take ownership. The pointer remains
+ // valid until an error occurs on the connection with the Shell, or until the
+ // ApplicationImpl is destroyed, whichever occurs first.
+ ApplicationConnection* ConnectToApplication(const String& application_url);
+
+ // Connect to application identified by |application_url| and connect to the
+ // service implementation of the interface identified by |Interface|.
+ template <typename Interface>
+ void ConnectToService(const std::string& application_url,
+ InterfacePtr<Interface>* ptr) {
+ ConnectToApplication(application_url)->ConnectToService(ptr);
+ }
+
+ // Application implementation.
+ void Initialize(ShellPtr shell,
+ Array<String> args,
+ const mojo::String& url) override;
+
+ // Block until the Application is initialized, if it is not already.
+ void WaitForInitialize();
+
+ // Unbinds the Shell and Application connections. Can be used to re-bind the
+ // handles to another implementation of ApplicationImpl, for instance when
+ // running apptests.
+ void UnbindConnections(InterfaceRequest<Application>* application_request,
+ ShellPtr* shell);
+
+ // Quits the main run loop for this application.
+ static void Terminate();
+
+ protected:
+ // Application implementation.
+ void AcceptConnection(const String& requestor_url,
+ InterfaceRequest<ServiceProvider> services,
+ ServiceProviderPtr exposed_services,
+ const String& url) override;
+
+ private:
+ class ShellPtrWatcher;
+
+ void ClearConnections();
+
+ void OnShellError() {
+ delegate_->Quit();
+ ClearConnections();
+ Terminate();
+ }
+
+ // Application implementation.
+ void RequestQuit() override;
+
+ typedef std::vector<internal::ServiceRegistry*> ServiceRegistryList;
+
+ ServiceRegistryList incoming_service_registries_;
+ ServiceRegistryList outgoing_service_registries_;
+ ApplicationDelegate* delegate_;
+ Binding<Application> binding_;
+ ShellPtr shell_;
+ ShellPtrWatcher* shell_watch_;
+ std::string url_;
+ std::vector<std::string> args_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ApplicationImpl);
+};
+
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_IMPL_H_
diff --git a/mojo/application/public/cpp/application_runner.h b/mojo/application/public/cpp/application_runner.h
new file mode 100644
index 0000000..e537c66
--- /dev/null
+++ b/mojo/application/public/cpp/application_runner.h
@@ -0,0 +1,44 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_RUNNER_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_RUNNER_H_
+
+#include "mojo/public/cpp/system/core.h"
+
+namespace mojo {
+
+class ApplicationDelegate;
+
+// A utility for running an Application. The typical use case is to use
+// when writing your MojoMain:
+//
+// MojoResult MojoMain(MojoHandle application_request) {
+// mojo::ApplicationRunner runner(new MyApplicationDelegate());
+// return runner.Run(application_request);
+// }
+//
+// ApplicationRunner takes care of mojo environment initialization and
+// shutdown, and starting a RunLoop from which your application can run and
+// ultimately Quit().
+class ApplicationRunner {
+ public:
+ // Takes ownership of |delegate|.
+ explicit ApplicationRunner(ApplicationDelegate* delegate);
+ ~ApplicationRunner();
+
+ // Once the various parameters have been set above, use Run to initialize an
+ // ApplicationImpl wired to the provided delegate, and run a RunLoop until
+ // the application exits.
+ MojoResult Run(MojoHandle application_request);
+
+ private:
+ ApplicationDelegate* delegate_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ApplicationRunner);
+};
+
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_RUNNER_H_
diff --git a/mojo/application/public/cpp/application_test_base.h b/mojo/application/public/cpp/application_test_base.h
new file mode 100644
index 0000000..9314bda
--- /dev/null
+++ b/mojo/application/public/cpp/application_test_base.h
@@ -0,0 +1,62 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_TEST_BASE_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_TEST_BASE_H_
+
+#include "mojo/application/public/cpp/application_delegate.h"
+#include "mojo/application/public/interfaces/application.mojom.h"
+#include "mojo/public/cpp/bindings/array.h"
+#include "mojo/public/cpp/bindings/string.h"
+#include "mojo/public/cpp/system/macros.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+
+class ApplicationImpl;
+
+namespace test {
+
+// Access the command line arguments passed to the application test.
+const Array<String>& Args();
+
+// Run all application tests. This must be called after the environment is
+// initialized, to support construction of a default run loop.
+MojoResult RunAllTests(MojoHandle application_request_handle);
+
+// A GTEST base class for application testing executed in mojo_shell.
+class ApplicationTestBase : public testing::Test {
+ public:
+ ApplicationTestBase();
+ ~ApplicationTestBase() override;
+
+ protected:
+ ApplicationImpl* application_impl() { return application_impl_; }
+
+ // Get the ApplicationDelegate for the application to be tested.
+ virtual ApplicationDelegate* GetApplicationDelegate();
+
+ // testing::Test:
+ void SetUp() override;
+ void TearDown() override;
+
+ // True by default, which indicates a MessageLoop will automatically be
+ // created for the application. Tests may override this function to prevent
+ // a default loop from being created.
+ virtual bool ShouldCreateDefaultRunLoop();
+
+ private:
+ // The application implementation instance, reconstructed for each test.
+ ApplicationImpl* application_impl_;
+ // The application delegate used if GetApplicationDelegate is not overridden.
+ ApplicationDelegate default_application_delegate_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ApplicationTestBase);
+};
+
+} // namespace test
+
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_APPLICATION_TEST_BASE_H_
diff --git a/mojo/application/public/cpp/connect.h b/mojo/application/public/cpp/connect.h
new file mode 100644
index 0000000..ecf920e
--- /dev/null
+++ b/mojo/application/public/cpp/connect.h
@@ -0,0 +1,23 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_CONNECT_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_CONNECT_H_
+
+#include "mojo/application/public/interfaces/service_provider.mojom.h"
+
+namespace mojo {
+
+// Binds |ptr| to a remote implementation of Interface from |service_provider|.
+template <typename Interface>
+inline void ConnectToService(ServiceProvider* service_provider,
+ InterfacePtr<Interface>* ptr) {
+ MessagePipe pipe;
+ ptr->Bind(InterfacePtrInfo<Interface>(pipe.handle0.Pass(), 0u));
+ service_provider->ConnectToService(Interface::Name_, pipe.handle1.Pass());
+}
+
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_CONNECT_H_
diff --git a/mojo/application/public/cpp/interface_factory.h b/mojo/application/public/cpp/interface_factory.h
new file mode 100644
index 0000000..cd7f6e1
--- /dev/null
+++ b/mojo/application/public/cpp/interface_factory.h
@@ -0,0 +1,31 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_INTERFACE_FACTORY_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_INTERFACE_FACTORY_H_
+
+#include "mojo/public/cpp/bindings/interface_impl.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+
+namespace mojo {
+
+class ApplicationConnection;
+template <typename Interface>
+class InterfaceRequest;
+
+// Implement this class to provide implementations of a given interface and
+// bind them to incoming requests. The implementation of this class is
+// responsible for managing the lifetime of the implementations of the
+// interface.
+template <typename Interface>
+class InterfaceFactory {
+ public:
+ virtual ~InterfaceFactory() {}
+ virtual void Create(ApplicationConnection* connection,
+ InterfaceRequest<Interface> request) = 0;
+};
+
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_INTERFACE_FACTORY_H_
diff --git a/mojo/application/public/cpp/interface_factory_impl.h b/mojo/application/public/cpp/interface_factory_impl.h
new file mode 100644
index 0000000..d4cf1c2
--- /dev/null
+++ b/mojo/application/public/cpp/interface_factory_impl.h
@@ -0,0 +1,49 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_INTERFACE_FACTORY_IMPL_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_INTERFACE_FACTORY_IMPL_H_
+
+#include "mojo/application/public/cpp/interface_factory.h"
+
+namespace mojo {
+
+// Use this class to allocate and bind instances of Impl to interface requests.
+// The lifetime of the constructed Impl is bound to the pipe.
+template <typename Impl,
+ typename Interface = typename Impl::ImplementedInterface>
+class InterfaceFactoryImpl : public InterfaceFactory<Interface> {
+ public:
+ virtual ~InterfaceFactoryImpl() {}
+
+ virtual void Create(ApplicationConnection* connection,
+ InterfaceRequest<Interface> request) override {
+ BindToRequest(new Impl(), &request);
+ }
+};
+
+// Use this class to allocate and bind instances of Impl constructed with a
+// context parameter to interface requests. The lifetime of the constructed
+// Impl is bound to the pipe.
+template <typename Impl,
+ typename Context,
+ typename Interface = typename Impl::ImplementedInterface>
+class InterfaceFactoryImplWithContext : public InterfaceFactory<Interface> {
+ public:
+ explicit InterfaceFactoryImplWithContext(Context* context)
+ : context_(context) {}
+ virtual ~InterfaceFactoryImplWithContext() {}
+
+ virtual void Create(ApplicationConnection* connection,
+ InterfaceRequest<Interface> request) override {
+ BindToRequest(new Impl(context_), &request);
+ }
+
+ private:
+ Context* context_;
+};
+
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_INTERFACE_FACTORY_IMPL_H_
diff --git a/mojo/application/public/cpp/lazy_interface_ptr.h b/mojo/application/public/cpp/lazy_interface_ptr.h
new file mode 100644
index 0000000..090beb2
--- /dev/null
+++ b/mojo/application/public/cpp/lazy_interface_ptr.h
@@ -0,0 +1,46 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_LAZY_INTERFACE_PTR_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_LAZY_INTERFACE_PTR_H_
+
+#include "mojo/application/public/cpp/connect.h"
+#include "mojo/application/public/interfaces/service_provider.mojom.h"
+
+namespace mojo {
+
+// An InterfacePtr that will request an implementation from a specified
+// ServiceProvider when it is first accessed with the get() method.
+template <typename Interface>
+class LazyInterfacePtr : public InterfacePtr<Interface> {
+ public:
+ LazyInterfacePtr() : service_provider_(nullptr) {}
+
+ LazyInterfacePtr(ServiceProvider* service_provider)
+ : service_provider_(service_provider) {}
+
+ void set_service_provider(ServiceProvider* service_provider) {
+ if (service_provider != service_provider_) {
+ InterfacePtr<Interface>::reset();
+ }
+ service_provider_ = service_provider;
+ }
+
+ Interface* get() const {
+ if (!InterfacePtr<Interface>::get() && service_provider_) {
+ mojo::ConnectToService<Interface>(
+ service_provider_, const_cast<LazyInterfacePtr<Interface>*>(this));
+ }
+ return InterfacePtr<Interface>::get();
+ }
+ Interface* operator->() const { return get(); }
+ Interface& operator*() const { return *get(); }
+
+ private:
+ ServiceProvider* service_provider_;
+};
+
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_LAZY_INTERFACE_PTR_H_
diff --git a/mojo/application/public/cpp/lib/application_connection.cc b/mojo/application/public/cpp/lib/application_connection.cc
new file mode 100644
index 0000000..a76757f
--- /dev/null
+++ b/mojo/application/public/cpp/lib/application_connection.cc
@@ -0,0 +1,12 @@
+// Copyright 2014 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 "mojo/application/public/cpp/application_connection.h"
+
+namespace mojo {
+
+ApplicationConnection::~ApplicationConnection() {
+}
+
+} // namespace mojo
diff --git a/mojo/application/public/cpp/lib/application_delegate.cc b/mojo/application/public/cpp/lib/application_delegate.cc
new file mode 100644
index 0000000..bbe75cc
--- /dev/null
+++ b/mojo/application/public/cpp/lib/application_delegate.cc
@@ -0,0 +1,30 @@
+// Copyright 2014 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 "mojo/application/public/cpp/application_delegate.h"
+
+namespace mojo {
+
+ApplicationDelegate::ApplicationDelegate() {
+}
+ApplicationDelegate::~ApplicationDelegate() {
+}
+
+void ApplicationDelegate::Initialize(ApplicationImpl* app) {
+}
+
+bool ApplicationDelegate::ConfigureIncomingConnection(
+ ApplicationConnection* connection) {
+ return true;
+}
+
+bool ApplicationDelegate::ConfigureOutgoingConnection(
+ ApplicationConnection* connection) {
+ return true;
+}
+
+void ApplicationDelegate::Quit() {
+}
+
+} // namespace mojo
diff --git a/mojo/application/public/cpp/lib/application_impl.cc b/mojo/application/public/cpp/lib/application_impl.cc
new file mode 100644
index 0000000..018729f
--- /dev/null
+++ b/mojo/application/public/cpp/lib/application_impl.cc
@@ -0,0 +1,117 @@
+// Copyright 2014 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 "mojo/application/public/cpp/application_impl.h"
+
+#include "mojo/application/public/cpp/application_delegate.h"
+#include "mojo/application/public/cpp/lib/service_registry.h"
+#include "mojo/public/cpp/bindings/interface_ptr.h"
+#include "mojo/public/cpp/environment/logging.h"
+
+namespace mojo {
+
+class ApplicationImpl::ShellPtrWatcher : public ErrorHandler {
+ public:
+ ShellPtrWatcher(ApplicationImpl* impl) : impl_(impl) {}
+
+ ~ShellPtrWatcher() override {}
+
+ void OnConnectionError() override { impl_->OnShellError(); }
+
+ private:
+ ApplicationImpl* impl_;
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ShellPtrWatcher);
+};
+
+ApplicationImpl::ApplicationImpl(ApplicationDelegate* delegate,
+ InterfaceRequest<Application> request)
+ : delegate_(delegate),
+ binding_(this, request.Pass()),
+ shell_watch_(nullptr) {
+}
+
+bool ApplicationImpl::HasArg(const std::string& arg) const {
+ return std::find(args_.begin(), args_.end(), arg) != args_.end();
+}
+
+void ApplicationImpl::ClearConnections() {
+ for (ServiceRegistryList::iterator i(incoming_service_registries_.begin());
+ i != incoming_service_registries_.end();
+ ++i)
+ delete *i;
+ for (ServiceRegistryList::iterator i(outgoing_service_registries_.begin());
+ i != outgoing_service_registries_.end();
+ ++i)
+ delete *i;
+ incoming_service_registries_.clear();
+ outgoing_service_registries_.clear();
+}
+
+ApplicationImpl::~ApplicationImpl() {
+ ClearConnections();
+ delete shell_watch_;
+}
+
+ApplicationConnection* ApplicationImpl::ConnectToApplication(
+ const String& application_url) {
+ MOJO_CHECK(shell_);
+ ServiceProviderPtr local_services;
+ InterfaceRequest<ServiceProvider> local_request = GetProxy(&local_services);
+ ServiceProviderPtr remote_services;
+ shell_->ConnectToApplication(application_url, GetProxy(&remote_services),
+ local_services.Pass());
+ internal::ServiceRegistry* registry = new internal::ServiceRegistry(
+ this, application_url, application_url, remote_services.Pass(),
+ local_request.Pass());
+ if (!delegate_->ConfigureOutgoingConnection(registry)) {
+ delete registry;
+ return nullptr;
+ }
+ outgoing_service_registries_.push_back(registry);
+ return registry;
+}
+
+void ApplicationImpl::Initialize(ShellPtr shell,
+ Array<String> args,
+ const mojo::String& url) {
+ shell_ = shell.Pass();
+ shell_watch_ = new ShellPtrWatcher(this);
+ shell_.set_error_handler(shell_watch_);
+ url_ = url;
+ args_ = args.To<std::vector<std::string>>();
+ delegate_->Initialize(this);
+}
+
+void ApplicationImpl::WaitForInitialize() {
+ if (!shell_)
+ binding_.WaitForIncomingMethodCall();
+}
+
+void ApplicationImpl::UnbindConnections(
+ InterfaceRequest<Application>* application_request,
+ ShellPtr* shell) {
+ *application_request = binding_.Unbind();
+ shell->Bind(shell_.PassInterface());
+}
+
+void ApplicationImpl::AcceptConnection(
+ const String& requestor_url,
+ InterfaceRequest<ServiceProvider> services,
+ ServiceProviderPtr exposed_services,
+ const String& url) {
+ internal::ServiceRegistry* registry = new internal::ServiceRegistry(
+ this, url, requestor_url, exposed_services.Pass(), services.Pass());
+ if (!delegate_->ConfigureIncomingConnection(registry)) {
+ delete registry;
+ return;
+ }
+ incoming_service_registries_.push_back(registry);
+}
+
+void ApplicationImpl::RequestQuit() {
+ delegate_->Quit();
+ Terminate();
+}
+
+} // namespace mojo
diff --git a/mojo/application/public/cpp/lib/application_runner.cc b/mojo/application/public/cpp/lib/application_runner.cc
new file mode 100644
index 0000000..c1d4c0a
--- /dev/null
+++ b/mojo/application/public/cpp/lib/application_runner.cc
@@ -0,0 +1,40 @@
+// Copyright 2014 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 "mojo/application/public/cpp/application_runner.h"
+
+#include "mojo/application/public/cpp/application_delegate.h"
+#include "mojo/application/public/cpp/application_impl.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/utility/run_loop.h"
+
+namespace mojo {
+
+// static
+void ApplicationImpl::Terminate() {
+ RunLoop::current()->Quit();
+}
+
+ApplicationRunner::ApplicationRunner(ApplicationDelegate* delegate)
+ : delegate_(delegate) {
+}
+ApplicationRunner::~ApplicationRunner() {
+ assert(!delegate_);
+}
+
+MojoResult ApplicationRunner::Run(MojoHandle app_request_handle) {
+ Environment env;
+ {
+ RunLoop loop;
+ ApplicationImpl app(delegate_, MakeRequest<Application>(MakeScopedHandle(
+ MessagePipeHandle(app_request_handle))));
+ loop.Run();
+ }
+
+ delete delegate_;
+ delegate_ = nullptr;
+ return MOJO_RESULT_OK;
+}
+
+} // namespace mojo
diff --git a/mojo/application/public/cpp/lib/application_test_base.cc b/mojo/application/public/cpp/lib/application_test_base.cc
new file mode 100644
index 0000000..f3048da
--- /dev/null
+++ b/mojo/application/public/cpp/lib/application_test_base.cc
@@ -0,0 +1,165 @@
+// Copyright 2014 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 "mojo/public/cpp/application/application_test_base.h"
+
+#include "mojo/application/public/interfaces/application.mojom.h"
+#include "mojo/public/cpp/application/application_impl.h"
+#include "mojo/public/cpp/bindings/binding.h"
+#include "mojo/public/cpp/environment/environment.h"
+#include "mojo/public/cpp/system/message_pipe.h"
+
+namespace mojo {
+namespace test {
+
+namespace {
+// Share the application command-line arguments with multiple application tests.
+Array<String> g_args;
+
+// Share the application URL with multiple application tests.
+String g_url;
+
+// Application request handle passed from the shell in MojoMain, stored in
+// between SetUp()/TearDown() so we can (re-)intialize new ApplicationImpls.
+InterfaceRequest<Application> g_application_request;
+
+// Shell pointer passed in the initial mojo.Application.Initialize() call,
+// stored in between initial setup and the first test and between SetUp/TearDown
+// calls so we can (re-)initialize new ApplicationImpls.
+ShellPtr g_shell;
+
+void InitializeArgs(int argc, std::vector<const char*> argv) {
+ MOJO_CHECK(g_args.is_null());
+ for (const char* arg : argv) {
+ if (arg)
+ g_args.push_back(arg);
+ }
+}
+
+class ShellAndArgumentGrabber : public Application {
+ public:
+ ShellAndArgumentGrabber(Array<String>* args,
+ InterfaceRequest<Application> application_request)
+ : args_(args), binding_(this, application_request.Pass()) {}
+
+ void WaitForInitialize() {
+ // Initialize is always the first call made on Application.
+ MOJO_CHECK(binding_.WaitForIncomingMethodCall());
+ }
+
+ private:
+ // Application implementation.
+ void Initialize(ShellPtr shell,
+ Array<String> args,
+ const mojo::String& url) override {
+ *args_ = args.Pass();
+ g_url = url;
+ g_application_request = binding_.Unbind();
+ g_shell = shell.Pass();
+ }
+
+ void AcceptConnection(const String& requestor_url,
+ InterfaceRequest<ServiceProvider> services,
+ ServiceProviderPtr exposed_services,
+ const String& url) override {
+ MOJO_CHECK(false);
+ }
+
+ void RequestQuit() override { MOJO_CHECK(false); }
+
+ Array<String>* args_;
+ Binding<Application> binding_;
+};
+
+} // namespace
+
+const Array<String>& Args() {
+ return g_args;
+}
+
+MojoResult RunAllTests(MojoHandle application_request_handle) {
+ {
+ // This loop is used for init, and then destroyed before running tests.
+ Environment::InstantiateDefaultRunLoop();
+
+ // Grab the shell handle and GTEST commandline arguments.
+ // GTEST command line arguments are supported amid application arguments:
+ // $ mojo_shell mojo:example_apptests
+ // --args-for='mojo:example_apptests arg1 --gtest_filter=foo arg2'
+ Array<String> args;
+ ShellAndArgumentGrabber grabber(
+ &args, MakeRequest<Application>(MakeScopedHandle(
+ MessagePipeHandle(application_request_handle))));
+ grabber.WaitForInitialize();
+ MOJO_CHECK(g_shell);
+ MOJO_CHECK(g_application_request.is_pending());
+
+ // InitGoogleTest expects (argc + 1) elements, including a terminating null.
+ // It also removes GTEST arguments from |argv| and updates the |argc| count.
+ MOJO_CHECK(args.size() <
+ static_cast<size_t>(std::numeric_limits<int>::max()));
+ int argc = static_cast<int>(args.size());
+ std::vector<const char*> argv(argc + 1);
+ for (int i = 0; i < argc; ++i)
+ argv[i] = args[i].get().c_str();
+ argv[argc] = nullptr;
+
+ testing::InitGoogleTest(&argc, const_cast<char**>(&(argv[0])));
+ InitializeArgs(argc, argv);
+
+ Environment::DestroyDefaultRunLoop();
+ }
+
+ int result = RUN_ALL_TESTS();
+
+ // Shut down our message pipes before exiting.
+ (void)g_application_request.PassMessagePipe();
+ (void)g_shell.PassInterface();
+
+ return (result == 0) ? MOJO_RESULT_OK : MOJO_RESULT_UNKNOWN;
+}
+
+ApplicationTestBase::ApplicationTestBase() : application_impl_(nullptr) {
+}
+
+ApplicationTestBase::~ApplicationTestBase() {
+}
+
+ApplicationDelegate* ApplicationTestBase::GetApplicationDelegate() {
+ return &default_application_delegate_;
+}
+
+void ApplicationTestBase::SetUp() {
+ // A run loop is recommended for ApplicationImpl initialization and
+ // communication.
+ if (ShouldCreateDefaultRunLoop())
+ Environment::InstantiateDefaultRunLoop();
+
+ MOJO_CHECK(g_application_request.is_pending());
+ MOJO_CHECK(g_shell);
+
+ // New applications are constructed for each test to avoid persisting state.
+ application_impl_ = new ApplicationImpl(GetApplicationDelegate(),
+ g_application_request.Pass());
+
+ // Fake application initialization with the given command line arguments.
+ application_impl_->Initialize(g_shell.Pass(), g_args.Clone(), g_url);
+}
+
+void ApplicationTestBase::TearDown() {
+ MOJO_CHECK(!g_application_request.is_pending());
+ MOJO_CHECK(!g_shell);
+
+ application_impl_->UnbindConnections(&g_application_request, &g_shell);
+ delete application_impl_;
+ if (ShouldCreateDefaultRunLoop())
+ Environment::DestroyDefaultRunLoop();
+}
+
+bool ApplicationTestBase::ShouldCreateDefaultRunLoop() {
+ return true;
+}
+
+} // namespace test
+} // namespace mojo
diff --git a/mojo/application/public/cpp/lib/application_test_main.cc b/mojo/application/public/cpp/lib/application_test_main.cc
new file mode 100644
index 0000000..2df150a
--- /dev/null
+++ b/mojo/application/public/cpp/lib/application_test_main.cc
@@ -0,0 +1,14 @@
+// Copyright 2014 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 "mojo/application/public/cpp/application_test_base.h"
+#include "mojo/public/c/system/main.h"
+#include "mojo/public/cpp/environment/environment.h"
+
+MojoResult MojoMain(MojoHandle handle) {
+ // An Environment instance is needed to construct run loops.
+ mojo::Environment environment;
+
+ return mojo::test::RunAllTests(handle);
+}
diff --git a/mojo/application/public/cpp/lib/interface_factory_connector.h b/mojo/application/public/cpp/lib/interface_factory_connector.h
new file mode 100644
index 0000000..8d13bc2
--- /dev/null
+++ b/mojo/application/public/cpp/lib/interface_factory_connector.h
@@ -0,0 +1,37 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_LIB_INTERFACE_FACTORY_CONNECTOR_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_LIB_INTERFACE_FACTORY_CONNECTOR_H_
+
+#include "mojo/application/public/cpp/interface_factory.h"
+#include "mojo/application/public/cpp/service_connector.h"
+#include "mojo/public/cpp/bindings/interface_request.h"
+
+namespace mojo {
+namespace internal {
+
+template <typename Interface>
+class InterfaceFactoryConnector : public ServiceConnector {
+ public:
+ explicit InterfaceFactoryConnector(InterfaceFactory<Interface>* factory)
+ : factory_(factory) {}
+ ~InterfaceFactoryConnector() override {}
+
+ void ConnectToService(ApplicationConnection* application_connection,
+ const std::string& interface_name,
+ ScopedMessagePipeHandle client_handle) override {
+ factory_->Create(application_connection,
+ MakeRequest<Interface>(client_handle.Pass()));
+ }
+
+ private:
+ InterfaceFactory<Interface>* factory_;
+ MOJO_DISALLOW_COPY_AND_ASSIGN(InterfaceFactoryConnector);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_LIB_INTERFACE_FACTORY_CONNECTOR_H_
diff --git a/mojo/application/public/cpp/lib/service_connector_registry.cc b/mojo/application/public/cpp/lib/service_connector_registry.cc
new file mode 100644
index 0000000..97c4316
--- /dev/null
+++ b/mojo/application/public/cpp/lib/service_connector_registry.cc
@@ -0,0 +1,59 @@
+// Copyright 2015 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 "mojo/application/public/cpp/lib/service_connector_registry.h"
+
+#include "mojo/application/public/cpp/service_connector.h"
+
+namespace mojo {
+namespace internal {
+
+ServiceConnectorRegistry::ServiceConnectorRegistry()
+ : service_connector_(nullptr) {
+}
+
+ServiceConnectorRegistry::~ServiceConnectorRegistry() {
+ for (NameToServiceConnectorMap::iterator i =
+ name_to_service_connector_.begin();
+ i != name_to_service_connector_.end(); ++i) {
+ delete i->second;
+ }
+ name_to_service_connector_.clear();
+}
+
+void ServiceConnectorRegistry::SetServiceConnectorForName(
+ ServiceConnector* service_connector,
+ const std::string& interface_name) {
+ RemoveServiceConnectorForName(interface_name);
+ name_to_service_connector_[interface_name] = service_connector;
+}
+
+void ServiceConnectorRegistry::RemoveServiceConnectorForName(
+ const std::string& interface_name) {
+ NameToServiceConnectorMap::iterator it =
+ name_to_service_connector_.find(interface_name);
+ if (it == name_to_service_connector_.end())
+ return;
+ delete it->second;
+ name_to_service_connector_.erase(it);
+}
+
+void ServiceConnectorRegistry::ConnectToService(
+ ApplicationConnection* application_connection,
+ const std::string& interface_name,
+ ScopedMessagePipeHandle client_handle) {
+ auto iter = name_to_service_connector_.find(interface_name);
+ if (iter != name_to_service_connector_.end()) {
+ iter->second->ConnectToService(application_connection, interface_name,
+ client_handle.Pass());
+ return;
+ }
+ if (service_connector_) {
+ service_connector_->ConnectToService(application_connection, interface_name,
+ client_handle.Pass());
+ }
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/application/public/cpp/lib/service_connector_registry.h b/mojo/application/public/cpp/lib/service_connector_registry.h
new file mode 100644
index 0000000..b196353
--- /dev/null
+++ b/mojo/application/public/cpp/lib/service_connector_registry.h
@@ -0,0 +1,62 @@
+// Copyright 2015 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_LIB_SERVICE_CONNECTOR_REGISTRY_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_LIB_SERVICE_CONNECTOR_REGISTRY_H_
+
+#include <map>
+#include <string>
+
+#include "mojo/public/cpp/system/message_pipe.h"
+
+namespace mojo {
+
+class ApplicationConnection;
+class ServiceConnector;
+
+namespace internal {
+
+// ServiceConnectorRegistry maintains a default ServiceConnector as well as at
+// most one ServiceConnector per interface name. When ConnectToService() is
+// invoked the ServiceConnector registered by name is given the request. If
+// a ServiceConnector has not been registered by name than the default
+// ServiceConnector is given the request.
+class ServiceConnectorRegistry {
+ public:
+ ServiceConnectorRegistry();
+ ~ServiceConnectorRegistry();
+
+ // Sets the default ServiceConnector. ServiceConnectorRegistry does *not*
+ // take ownership of |service_connector|.
+ void set_service_connector(ServiceConnector* service_connector) {
+ service_connector_ = service_connector;
+ }
+
+ // Returns true if non ServiceConnectors have been registered by name.
+ bool empty() const { return name_to_service_connector_.empty(); }
+
+ // Sets a ServiceConnector by name. This deletes the existing ServiceConnector
+ // and takes ownership of |service_connector|.
+ void SetServiceConnectorForName(ServiceConnector* service_connector,
+ const std::string& interface_name);
+ void RemoveServiceConnectorForName(const std::string& interface_name);
+
+ void ConnectToService(ApplicationConnection* application_connection,
+ const std::string& interface_name,
+ ScopedMessagePipeHandle client_handle);
+
+ private:
+ using NameToServiceConnectorMap = std::map<std::string, ServiceConnector*>;
+
+ ServiceConnector* service_connector_;
+
+ NameToServiceConnectorMap name_to_service_connector_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceConnectorRegistry);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_LIB_SERVICE_CONNECTOR_REGISTRY_H_
diff --git a/mojo/application/public/cpp/lib/service_provider_impl.cc b/mojo/application/public/cpp/lib/service_provider_impl.cc
new file mode 100644
index 0000000..3d6ee6e
--- /dev/null
+++ b/mojo/application/public/cpp/lib/service_provider_impl.cc
@@ -0,0 +1,48 @@
+// Copyright 2014 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 "mojo/application/public/cpp/service_provider_impl.h"
+
+#include "mojo/application/public/cpp/service_connector.h"
+#include "mojo/public/cpp/environment/logging.h"
+
+namespace mojo {
+
+ServiceProviderImpl::ServiceProviderImpl() : binding_(this) {
+}
+
+ServiceProviderImpl::ServiceProviderImpl(
+ InterfaceRequest<ServiceProvider> request)
+ : binding_(this, request.Pass()) {
+}
+
+ServiceProviderImpl::~ServiceProviderImpl() {
+}
+
+void ServiceProviderImpl::Bind(InterfaceRequest<ServiceProvider> request) {
+ binding_.Bind(request.Pass());
+}
+
+void ServiceProviderImpl::Close() {
+ if (binding_.is_bound())
+ binding_.Close();
+}
+
+void ServiceProviderImpl::ConnectToService(
+ const String& service_name,
+ ScopedMessagePipeHandle client_handle) {
+ // TODO(beng): perhaps take app connection thru ctor so that we can pass
+ // ApplicationConnection through?
+ service_connector_registry_.ConnectToService(nullptr, service_name,
+ client_handle.Pass());
+}
+
+void ServiceProviderImpl::SetServiceConnectorForName(
+ ServiceConnector* service_connector,
+ const std::string& interface_name) {
+ service_connector_registry_.SetServiceConnectorForName(service_connector,
+ interface_name);
+}
+
+} // namespace mojo
diff --git a/mojo/application/public/cpp/lib/service_registry.cc b/mojo/application/public/cpp/lib/service_registry.cc
new file mode 100644
index 0000000..844ec3a
--- /dev/null
+++ b/mojo/application/public/cpp/lib/service_registry.cc
@@ -0,0 +1,73 @@
+// Copyright 2014 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 "mojo/application/public/cpp/lib/service_registry.h"
+
+#include "mojo/application/public/cpp/application_connection.h"
+#include "mojo/application/public/cpp/application_impl.h"
+#include "mojo/application/public/cpp/service_connector.h"
+
+namespace mojo {
+namespace internal {
+
+ServiceRegistry::ServiceRegistry(
+ ApplicationImpl* application_impl,
+ const std::string& connection_url,
+ const std::string& remote_url,
+ ServiceProviderPtr remote_services,
+ InterfaceRequest<ServiceProvider> local_services)
+ : application_impl_(application_impl),
+ connection_url_(connection_url),
+ remote_url_(remote_url),
+ local_binding_(this),
+ remote_service_provider_(remote_services.Pass()) {
+ if (local_services.is_pending())
+ local_binding_.Bind(local_services.Pass());
+}
+
+ServiceRegistry::ServiceRegistry()
+ : application_impl_(nullptr), local_binding_(this) {
+}
+
+ServiceRegistry::~ServiceRegistry() {
+}
+
+void ServiceRegistry::SetServiceConnector(ServiceConnector* connector) {
+ service_connector_registry_.set_service_connector(connector);
+}
+
+void ServiceRegistry::SetServiceConnectorForName(
+ ServiceConnector* service_connector,
+ const std::string& interface_name) {
+ service_connector_registry_.SetServiceConnectorForName(service_connector,
+ interface_name);
+}
+
+void ServiceRegistry::RemoveServiceConnectorForName(
+ const std::string& interface_name) {
+ service_connector_registry_.RemoveServiceConnectorForName(interface_name);
+ if (service_connector_registry_.empty())
+ remote_service_provider_.reset();
+}
+
+const std::string& ServiceRegistry::GetConnectionURL() {
+ return connection_url_;
+}
+
+const std::string& ServiceRegistry::GetRemoteApplicationURL() {
+ return remote_url_;
+}
+
+ServiceProvider* ServiceRegistry::GetServiceProvider() {
+ return remote_service_provider_.get();
+}
+
+void ServiceRegistry::ConnectToService(const mojo::String& service_name,
+ ScopedMessagePipeHandle client_handle) {
+ service_connector_registry_.ConnectToService(this, service_name,
+ client_handle.Pass());
+}
+
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/application/public/cpp/lib/service_registry.h b/mojo/application/public/cpp/lib/service_registry.h
new file mode 100644
index 0000000..9eee695
--- /dev/null
+++ b/mojo/application/public/cpp/lib/service_registry.h
@@ -0,0 +1,67 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_LIB_SERVICE_REGISTRY_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_LIB_SERVICE_REGISTRY_H_
+
+#include <string>
+
+#include "mojo/application/public/cpp/application_connection.h"
+#include "mojo/application/public/cpp/lib/service_connector_registry.h"
+#include "mojo/application/public/interfaces/service_provider.mojom.h"
+
+namespace mojo {
+
+class Application;
+class ApplicationImpl;
+
+namespace internal {
+
+// A ServiceRegistry represents each half of a connection between two
+// applications, allowing customization of which services are published to the
+// other.
+class ServiceRegistry : public ServiceProvider, public ApplicationConnection {
+ public:
+ ServiceRegistry();
+ ServiceRegistry(ApplicationImpl* application_impl,
+ const std::string& connection_url,
+ const std::string& remote_url,
+ ServiceProviderPtr remote_services,
+ InterfaceRequest<ServiceProvider> local_services);
+ ~ServiceRegistry() override;
+
+ // ApplicationConnection overrides.
+ void SetServiceConnector(ServiceConnector* service_connector) override;
+ void SetServiceConnectorForName(ServiceConnector* service_connector,
+ const std::string& interface_name) override;
+ const std::string& GetConnectionURL() override;
+ const std::string& GetRemoteApplicationURL() override;
+ ServiceProvider* GetServiceProvider() override;
+
+ void RemoveServiceConnectorForName(const std::string& interface_name);
+
+ private:
+ // ServiceProvider method.
+ void ConnectToService(const mojo::String& service_name,
+ ScopedMessagePipeHandle client_handle) override;
+
+ ApplicationImpl* application_impl_;
+ const std::string connection_url_;
+ const std::string remote_url_;
+
+ private:
+ void RemoveServiceConnectorForNameInternal(const std::string& interface_name);
+
+ Application* application_;
+ Binding<ServiceProvider> local_binding_;
+ ServiceProviderPtr remote_service_provider_;
+ ServiceConnectorRegistry service_connector_registry_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceRegistry);
+};
+
+} // namespace internal
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_LIB_SERVICE_REGISTRY_H_
diff --git a/mojo/application/public/cpp/service_connector.h b/mojo/application/public/cpp/service_connector.h
new file mode 100644
index 0000000..3a7d656
--- /dev/null
+++ b/mojo/application/public/cpp/service_connector.h
@@ -0,0 +1,30 @@
+// Copyright 2015 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_SERVICE_CONNECTOR_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_SERVICE_CONNECTOR_H_
+
+#include <string>
+
+#include "mojo/public/cpp/system/message_pipe.h"
+
+namespace mojo {
+
+class ApplicationConnection;
+
+class ServiceConnector {
+ public:
+ virtual ~ServiceConnector() {}
+
+ // Asks the ServiceConnector to connect to the specified service. If the
+ // ServiceConnector connects to the service it should take ownership of
+ // the handle in |handle|.
+ virtual void ConnectToService(ApplicationConnection* application_connection,
+ const std::string& interface_name,
+ ScopedMessagePipeHandle handle) = 0;
+};
+
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_SERVICE_CONNECTOR_H_
diff --git a/mojo/application/public/cpp/service_provider_impl.h b/mojo/application/public/cpp/service_provider_impl.h
new file mode 100644
index 0000000..033bdac
--- /dev/null
+++ b/mojo/application/public/cpp/service_provider_impl.h
@@ -0,0 +1,53 @@
+// Copyright 2014 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.
+
+#ifndef MOJO_APPLICATION_PUBLIC_CPP_SERVICE_PROVIDER_IMPL_H_
+#define MOJO_APPLICATION_PUBLIC_CPP_SERVICE_PROVIDER_IMPL_H_
+
+#include <string>
+
+#include "mojo/application/public/cpp/lib/interface_factory_connector.h"
+#include "mojo/application/public/cpp/lib/service_connector_registry.h"
+#include "mojo/application/public/interfaces/service_provider.mojom.h"
+#include "mojo/public/cpp/bindings/binding.h"
+
+namespace mojo {
+
+// Implements a registry that can be used to expose services to another app.
+class ServiceProviderImpl : public ServiceProvider {
+ public:
+ ServiceProviderImpl();
+ explicit ServiceProviderImpl(InterfaceRequest<ServiceProvider> request);
+ ~ServiceProviderImpl() override;
+
+ void Bind(InterfaceRequest<ServiceProvider> request);
+ // Disconnect this service provider and put it in a state where it can be
+ // rebound to a new request.
+ void Close();
+
+ template <typename Interface>
+ void AddService(InterfaceFactory<Interface>* factory) {
+ SetServiceConnectorForName(
+ new internal::InterfaceFactoryConnector<Interface>(factory),
+ Interface::Name_);
+ }
+
+ private:
+ // Overridden from ServiceProvider:
+ void ConnectToService(const String& service_name,
+ ScopedMessagePipeHandle client_handle) override;
+
+ void SetServiceConnectorForName(ServiceConnector* service_connector,
+ const std::string& interface_name);
+
+ Binding<ServiceProvider> binding_;
+
+ internal::ServiceConnectorRegistry service_connector_registry_;
+
+ MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceProviderImpl);
+};
+
+} // namespace mojo
+
+#endif // MOJO_APPLICATION_PUBLIC_CPP_SERVICE_PROVIDER_IMPL_H_
diff --git a/mojo/application/public/cpp/tests/BUILD.gn b/mojo/application/public/cpp/tests/BUILD.gn
new file mode 100644
index 0000000..88690d0
--- /dev/null
+++ b/mojo/application/public/cpp/tests/BUILD.gn
@@ -0,0 +1,19 @@
+# Copyright 2014 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.
+
+import("//testing/test.gni")
+
+test("mojo_public_application_unittests") {
+ sources = [
+ "service_registry_unittest.cc",
+ ]
+
+ deps = [
+ "//mojo/application/public/cpp:standalone",
+ "//testing/gtest",
+ "//third_party/mojo/src/mojo/edk/test:run_all_unittests",
+ "//third_party/mojo/src/mojo/public/cpp/environment:standalone",
+ "//third_party/mojo/src/mojo/public/cpp/utility",
+ ]
+}
diff --git a/mojo/application/public/cpp/tests/service_registry_unittest.cc b/mojo/application/public/cpp/tests/service_registry_unittest.cc
new file mode 100644
index 0000000..a746026
--- /dev/null
+++ b/mojo/application/public/cpp/tests/service_registry_unittest.cc
@@ -0,0 +1,70 @@
+// Copyright 2014 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 "mojo/application/public/cpp/lib/service_registry.h"
+
+#include "mojo/application/public/cpp/service_connector.h"
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace mojo {
+namespace internal {
+namespace {
+
+class TestConnector : public ServiceConnector {
+ public:
+ explicit TestConnector(int* delete_count) : delete_count_(delete_count) {}
+ ~TestConnector() override { (*delete_count_)++; }
+ void ConnectToService(ApplicationConnection* application_connection,
+ const std::string& interface_name,
+ ScopedMessagePipeHandle client_handle) override {}
+
+ private:
+ int* delete_count_;
+};
+
+TEST(ServiceRegistryTest, Ownership) {
+ int delete_count = 0;
+
+ // Destruction.
+ {
+ ServiceRegistry registry;
+ registry.SetServiceConnectorForName(new TestConnector(&delete_count),
+ "TC1");
+ }
+ EXPECT_EQ(1, delete_count);
+
+ // Removal.
+ {
+ ServiceRegistry registry;
+ ServiceConnector* c = new TestConnector(&delete_count);
+ registry.SetServiceConnectorForName(c, "TC1");
+ registry.RemoveServiceConnectorForName("TC1");
+ EXPECT_EQ(2, delete_count);
+ }
+
+ // Multiple.
+ {
+ ServiceRegistry registry;
+ registry.SetServiceConnectorForName(new TestConnector(&delete_count),
+ "TC1");
+ registry.SetServiceConnectorForName(new TestConnector(&delete_count),
+ "TC2");
+ }
+ EXPECT_EQ(4, delete_count);
+
+ // Re-addition.
+ {
+ ServiceRegistry registry;
+ registry.SetServiceConnectorForName(new TestConnector(&delete_count),
+ "TC1");
+ registry.SetServiceConnectorForName(new TestConnector(&delete_count),
+ "TC1");
+ EXPECT_EQ(5, delete_count);
+ }
+ EXPECT_EQ(6, delete_count);
+}
+
+} // namespace
+} // namespace internal
+} // namespace mojo
diff --git a/mojo/application/public/interfaces/BUILD.gn b/mojo/application/public/interfaces/BUILD.gn
new file mode 100644
index 0000000..37d91b0
--- /dev/null
+++ b/mojo/application/public/interfaces/BUILD.gn
@@ -0,0 +1,14 @@
+# Copyright 2014 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.
+
+import("//third_party/mojo/src/mojo/public/tools/bindings/mojom.gni")
+
+# GYP version: mojo/mojo_base.gyp:mojo_application_bindings
+mojom("interfaces") {
+ sources = [
+ "application.mojom",
+ "service_provider.mojom",
+ "shell.mojom",
+ ]
+}
diff --git a/mojo/application/public/interfaces/application.mojom b/mojo/application/public/interfaces/application.mojom
new file mode 100644
index 0000000..dc9f2f63
--- /dev/null
+++ b/mojo/application/public/interfaces/application.mojom
@@ -0,0 +1,59 @@
+// Copyright 2014 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.
+
+module mojo;
+
+import "mojo/application/public/interfaces/service_provider.mojom";
+import "mojo/application/public/interfaces/shell.mojom";
+
+// This is the primary interface implemented by every Mojo application. It
+// allows the application to receive its startup arguments from the shell, and
+// to be notified of events that occur during its execution.
+//
+// TODO(aa): It would be good to reorder the parameters once we have interface
+// versioning.
+interface Application {
+ // Initializes the application with the specified arguments. This method is
+ // guaranteed to be called before any other method is called, and will only be
+ // called once.
+ //
+ // The |url| parameter is the identity of the application as far as the shell
+ // is concerned. This will be the URL the application was found at, after all
+ // mappings, resolution, and redirects. And it will not include the
+ // querystring, since the querystring is not part of an application's
+ // identity.
+ Initialize(Shell shell, array<string>? args, string url);
+
+ // Called when another application (identified by |requestor_url|) attempts to
+ // open a connection to this application.
+ //
+ // If the other application wants to request services from this application,
+ // it will have passed a valid interface request through the |services|
+ // parameter (i.e. one containing a valid message pipe endpoint). This
+ // application may then bind an implementation of |ServiceProvider| to that
+ // request in order to make services available to the other application.
+ //
+ // If the other application wants to offer services to this application, it
+ // will have passed a bound interface through the |exposed_services|
+ // parameter. This application may then request services through that
+ // interface.
+ //
+ // It is possible that both parameters will be valid/bound if the other
+ // application wants to both request services from and offer services to this
+ // application.
+ //
+ // This application is free to ignore the |services| or |exposed_services|
+ // parameters if it does not wish to offer or request services.
+ //
+ // resolved_url is the URL that was requested to create this connection, after
+ // all mappings, resolutions, and redirects. This will include any querystring
+ // that was part of the request.
+ AcceptConnection(string requestor_url,
+ ServiceProvider&? services,
+ ServiceProvider? exposed_services,
+ string resolved_url);
+
+ // Called to request the application shut itself down gracefully.
+ RequestQuit();
+};
diff --git a/mojo/application/public/interfaces/service_provider.mojom b/mojo/application/public/interfaces/service_provider.mojom
new file mode 100644
index 0000000..8c81879
--- /dev/null
+++ b/mojo/application/public/interfaces/service_provider.mojom
@@ -0,0 +1,17 @@
+// Copyright 2014 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.
+
+module mojo;
+
+// An interface through which a client may request services from a host.
+// Instances of this interface are created within the context of an
+// already-identified client and host pair, so there is no need to explicitly
+// identify the client or host in the methods below.
+interface ServiceProvider {
+ // Asks the host to provide the service identified by |interface_name| through
+ // the message |pipe| endpoint supplied by the caller. If the host is not
+ // willing or able to provide the requested service, it should close the
+ // |pipe|.
+ ConnectToService(string interface_name, handle<message_pipe> pipe);
+};
diff --git a/mojo/application/public/interfaces/shell.mojom b/mojo/application/public/interfaces/shell.mojom
new file mode 100644
index 0000000..b6b1319
--- /dev/null
+++ b/mojo/application/public/interfaces/shell.mojom
@@ -0,0 +1,38 @@
+// Copyright 2014 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.
+
+module mojo;
+
+import "mojo/application/public/interfaces/service_provider.mojom";
+
+// An interface through which a Mojo application may communicate with the Mojo
+// system and request connections to other applications.
+interface Shell {
+ // Establishes a connection with another application (located at
+ // |application_url|) through which the calling application and the other
+ // application may request services from one another.
+ //
+ // If the calling application would like to request services from the other
+ // application, it should pass a valid interface request in the |services|
+ // parameter (i.e. one containing a valid message pipe endpoint). If the other
+ // application does not wish to offer services, it may either not bind an
+ // implementation to the interface request, or else bind an implementation
+ // that will reject some or all service requests.
+ //
+ // If the calling application would like to offer services to the other
+ // application, it should pass a bound interface through the
+ // |exposed_services| parameter. The other application may then request
+ // services through that interface.
+ //
+ // At least one of |services| or |exposed_services| should be valid/bound in
+ // the call.
+ //
+ // If the |application_url| does not contain a domain, but is of the form
+ // "mojo:{service}", it is up to the Mojo shell to select an appropriate
+ // application for the service. Currently, the shell does this based on the
+ // value of its --origin flag.
+ ConnectToApplication(string application_url,
+ ServiceProvider&? services,
+ ServiceProvider? exposed_services);
+};