Factor stuff from ApplicationImpl out to a new class, ApplicationImplBase. ApplicationImpl is now a rather dumb class that just calls its ApplicationDelegate. Using base/implementation classes is preferable to the delegate pattern because: * It's simpler (see below). * With the delgate pattern, the impl and the delegate both need pointers to each other. And so there are lifetime problems/considerations. * The delegate just ends up calling into the impl a lot. Unfortunately, it's rather hard (impossible) to use ApplicationImplBase right now (as intended): I'll need to refactor ApplicationRunner(Chromium) to not just instantiate ApplicationImpl, etc. (I'll also need a story for the crazy that is ApplicationImpl(Base)::Terminate().) R=vardhan@google.com Review URL: https://codereview.chromium.org/1985223003 .
diff --git a/examples/bank_app/customer.cc b/examples/bank_app/customer.cc index 089de8d..77562c9 100644 --- a/examples/bank_app/customer.cc +++ b/examples/bank_app/customer.cc
@@ -6,6 +6,7 @@ #include "examples/bank_app/bank.mojom.h" #include "mojo/public/c/system/main.h" +#include "mojo/public/cpp/application/application_delegate.h" #include "mojo/public/cpp/application/application_impl.h" #include "mojo/public/cpp/application/application_runner.h" #include "mojo/public/cpp/application/connect.h"
diff --git a/mojo/application/application_runner_chromium.cc b/mojo/application/application_runner_chromium.cc index b528034..7a4635e 100644 --- a/mojo/application/application_runner_chromium.cc +++ b/mojo/application/application_runner_chromium.cc
@@ -11,13 +11,14 @@ #include "mojo/message_pump/message_pump_mojo.h" #include "mojo/public/cpp/application/application_delegate.h" #include "mojo/public/cpp/application/application_impl.h" +#include "mojo/public/cpp/application/application_impl_base.h" #include "mojo/public/cpp/system/handle.h" #include "mojo/public/cpp/system/message_pipe.h" namespace mojo { // static -void ApplicationImpl::Terminate() { +void ApplicationImplBase::Terminate() { if (base::MessageLoop::current()->is_running()) base::MessageLoop::current()->Quit(); }
diff --git a/mojo/public/cpp/application/BUILD.gn b/mojo/public/cpp/application/BUILD.gn index 543207f..ec0deae 100644 --- a/mojo/public/cpp/application/BUILD.gn +++ b/mojo/public/cpp/application/BUILD.gn
@@ -9,10 +9,12 @@ sources = [ "application_delegate.h", "application_impl.h", + "application_impl_base.h", "connect.h", "connection_context.h", "lib/application_delegate.cc", "lib/application_impl.cc", + "lib/application_impl_base.cc", "lib/connect.cc", "lib/service_provider_impl.cc", "service_connector.h",
diff --git a/mojo/public/cpp/application/application_impl.h b/mojo/public/cpp/application/application_impl.h index 2621daa..fffc890 100644 --- a/mojo/public/cpp/application/application_impl.h +++ b/mojo/public/cpp/application/application_impl.h
@@ -5,17 +5,12 @@ #ifndef MOJO_PUBLIC_CPP_APPLICATION_APPLICATION_IMPL_H_ #define MOJO_PUBLIC_CPP_APPLICATION_APPLICATION_IMPL_H_ -#include <memory> -#include <string> -#include <vector> - -#include "mojo/public/cpp/application/application_delegate.h" +#include "mojo/public/cpp/application/application_impl_base.h" #include "mojo/public/cpp/system/macros.h" -#include "mojo/public/interfaces/application/application.mojom.h" -#include "mojo/public/interfaces/application/shell.mojom.h" namespace mojo { +class ApplicationDelegate; class ServiceProviderImpl; // Implements the Application interface, which the shell uses for basic @@ -30,7 +25,7 @@ // ConfigureIncomingConnection() adds services to each connection. Finally, you // instantiate your delegate and pass it to an ApplicationRunner, which will // create the ApplicationImpl and then run a message (or run) loop. -class ApplicationImpl : public Application { +class ApplicationImpl : public ApplicationImplBase { public: // Does not take ownership of |delegate|, which must remain valid for the // lifetime of ApplicationImpl. @@ -38,38 +33,13 @@ InterfaceRequest<Application> request); ~ApplicationImpl() override; - // Quits the main run loop for this application. - // TODO(vtl): This is implemented in application_runner.cc (for example). Its - // presence here is pretty dubious. - static void Terminate(); - - // The Mojo shell. This will return a valid pointer after Initialize() has - // been invoked. It will remain valid until this object 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; - private: - // |Application| implementation. - void Initialize(InterfaceHandle<Shell> shell, - Array<String> args, - const mojo::String& url) override; - void AcceptConnection(const String& requestor_url, - InterfaceRequest<ServiceProvider> services, - InterfaceHandle<ServiceProvider> exposed_services, - const String& url) override; - void RequestQuit() override; + // |ApplicationImplBase| implementation/overrides: + void OnInitialize() final; + bool OnAcceptConnection(ServiceProviderImpl* service_provider_impl) final; + void OnQuit() final; - std::vector<std::unique_ptr<ServiceProviderImpl>> service_provider_impls_; - ApplicationDelegate* delegate_; - Binding<Application> application_binding_; - ShellPtr shell_; - std::string url_; - std::vector<std::string> args_; + ApplicationDelegate* const delegate_; MOJO_DISALLOW_COPY_AND_ASSIGN(ApplicationImpl); };
diff --git a/mojo/public/cpp/application/application_impl_base.h b/mojo/public/cpp/application/application_impl_base.h new file mode 100644 index 0000000..04109d7 --- /dev/null +++ b/mojo/public/cpp/application/application_impl_base.h
@@ -0,0 +1,98 @@ +// 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. + +#ifndef MOJO_PUBLIC_CPP_APPLICATION_APPLICATION_IMPL_BASE_H_ +#define MOJO_PUBLIC_CPP_APPLICATION_APPLICATION_IMPL_BASE_H_ + +#include <memory> +#include <string> +#include <vector> + +#include "mojo/public/cpp/bindings/binding.h" +#include "mojo/public/cpp/bindings/interface_request.h" +#include "mojo/public/cpp/system/macros.h" +#include "mojo/public/interfaces/application/application.mojom.h" +#include "mojo/public/interfaces/application/shell.mojom.h" + +namespace mojo { + +class ServiceProviderImpl; + +// Base helper class for implementing the |Application| interface, which the +// shell uses for basic communication with an application (e.g., to connect +// clients to services provided by an application). +// +// To use this class, subclass it and implement/override the required methods +// (see below). +// +// TODO(vtl): ApplicationRunners should take this instead of an +// ApplicationDelegate. Write more here when that's true (it's pretty hard to +// use this class in the current setup). +class ApplicationImplBase : public Application { + public: + explicit ApplicationImplBase( + InterfaceRequest<Application> application_request); + ~ApplicationImplBase() override; + + // Quits the main run loop for this application. + // TODO(vtl): This is implemented in application_runner.cc (for example). Its + // presence here is pretty dubious. + static void Terminate(); + + // This will be valid after |Initialize()| has been received and remain valid + // until this object is destroyed. + Shell* shell() const { return shell_.get(); } + + // 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; + + const std::string& url() const { return url_; } + + // Methods to be implemented/overridden by subclasses: + + // Called after |Initialize()| has been received (|shell()|, |args()|, and + // |url()| will be valid when this is called. The default implementation does + // nothing. + virtual void OnInitialize() {} + + // Called when another application connects to this application (i.e., we + // receive |AcceptConnection()|). This should either configure what services + // are "provided" (made available via a |ServiceProvider|) to that application + // and return true, or this may return false to reject the connection + // entirely. + virtual bool OnAcceptConnection( + ServiceProviderImpl* service_provider_impl) = 0; + + // Called before quitting the main message (run) loop, i.e., before + // |Terminate()|. The default implementation does nothing. + virtual void OnQuit() {} + + private: + // |Application| implementation. In general, you probably shouldn't call these + // directly (but I can't really stop you). + void Initialize(InterfaceHandle<Shell> shell, + Array<String> args, + const mojo::String& url) final; + void AcceptConnection(const String& requestor_url, + InterfaceRequest<ServiceProvider> services, + InterfaceHandle<ServiceProvider> exposed_services, + const String& url) final; + void RequestQuit() final; + + Binding<Application> application_binding_; + + // Set by |Initialize()|. + ShellPtr shell_; + std::vector<std::string> args_; + std::string url_; + + std::vector<std::unique_ptr<ServiceProviderImpl>> service_provider_impls_; + + MOJO_DISALLOW_COPY_AND_ASSIGN(ApplicationImplBase); +}; + +} // namespace mojo + +#endif // MOJO_PUBLIC_CPP_APPLICATION_APPLICATION_IMPL_BASE_H_
diff --git a/mojo/public/cpp/application/lib/application_impl.cc b/mojo/public/cpp/application/lib/application_impl.cc index 6be42ff..194c942 100644 --- a/mojo/public/cpp/application/lib/application_impl.cc +++ b/mojo/public/cpp/application/lib/application_impl.cc
@@ -4,64 +4,27 @@ #include "mojo/public/cpp/application/application_impl.h" -#include <utility> - #include "mojo/public/cpp/application/application_delegate.h" -#include "mojo/public/cpp/application/connection_context.h" -#include "mojo/public/cpp/application/service_provider_impl.h" -#include "mojo/public/cpp/bindings/interface_ptr.h" -#include "mojo/public/cpp/bindings/interface_request.h" -#include "mojo/public/cpp/environment/logging.h" namespace mojo { ApplicationImpl::ApplicationImpl(ApplicationDelegate* delegate, InterfaceRequest<Application> request) - : delegate_(delegate), application_binding_(this, request.Pass()) {} + : ApplicationImplBase(request.Pass()), delegate_(delegate) {} ApplicationImpl::~ApplicationImpl() {} -bool ApplicationImpl::HasArg(const std::string& arg) const { - return std::find(args_.begin(), args_.end(), arg) != args_.end(); -} - -void ApplicationImpl::Initialize(InterfaceHandle<Shell> shell, - Array<String> args, - const mojo::String& url) { - shell_ = ShellPtr::Create(std::move(shell)); - shell_.set_connection_error_handler([this]() { - delegate_->Quit(); - service_provider_impls_.clear(); - Terminate(); - }); - url_ = url; - args_ = args.To<std::vector<std::string>>(); +void ApplicationImpl::OnInitialize() { delegate_->Initialize(this); } -void ApplicationImpl::AcceptConnection( - const String& requestor_url, - InterfaceRequest<ServiceProvider> services, - InterfaceHandle<ServiceProvider> exposed_services, - const String& url) { - // Note: The shell no longer actually connects |exposed_services|, so a) we - // never actually get valid |exposed_services| here, b) it should be OK to - // drop it on the floor. - MOJO_LOG_IF(ERROR, exposed_services) - << "DEPRECATED: exposed_services is going away"; - std::unique_ptr<ServiceProviderImpl> service_provider_impl( - new ServiceProviderImpl( - ConnectionContext(ConnectionContext::Type::INCOMING, requestor_url, - url), - services.Pass())); - if (!delegate_->ConfigureIncomingConnection(service_provider_impl.get())) - return; - service_provider_impls_.push_back(std::move(service_provider_impl)); +bool ApplicationImpl::OnAcceptConnection( + ServiceProviderImpl* service_provider_impl) { + return delegate_->ConfigureIncomingConnection(service_provider_impl); } -void ApplicationImpl::RequestQuit() { +void ApplicationImpl::OnQuit() { delegate_->Quit(); - Terminate(); } } // namespace mojo
diff --git a/mojo/public/cpp/application/lib/application_impl_base.cc b/mojo/public/cpp/application/lib/application_impl_base.cc new file mode 100644 index 0000000..a5e90d6 --- /dev/null +++ b/mojo/public/cpp/application/lib/application_impl_base.cc
@@ -0,0 +1,65 @@ +// 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 "mojo/public/cpp/application/application_impl_base.h" + +#include <algorithm> +#include <utility> + +#include "mojo/public/cpp/application/connection_context.h" +#include "mojo/public/cpp/application/service_provider_impl.h" +#include "mojo/public/cpp/environment/logging.h" + +namespace mojo { + +ApplicationImplBase::ApplicationImplBase( + InterfaceRequest<Application> application_request) + : application_binding_(this, application_request.Pass()) {} + +ApplicationImplBase::~ApplicationImplBase() {} + +bool ApplicationImplBase::HasArg(const std::string& arg) const { + return std::find(args_.begin(), args_.end(), arg) != args_.end(); +} + +void ApplicationImplBase::Initialize(InterfaceHandle<Shell> shell, + Array<String> args, + const mojo::String& url) { + shell_ = ShellPtr::Create(std::move(shell)); + shell_.set_connection_error_handler([this]() { + OnQuit(); + service_provider_impls_.clear(); + Terminate(); + }); + url_ = url; + args_ = args.To<std::vector<std::string>>(); + OnInitialize(); +} + +void ApplicationImplBase::AcceptConnection( + const String& requestor_url, + InterfaceRequest<ServiceProvider> services, + InterfaceHandle<ServiceProvider> exposed_services, + const String& url) { + // Note: The shell no longer actually connects |exposed_services|, so a) we + // never actually get valid |exposed_services| here, b) it should be OK to + // drop it on the floor. + MOJO_LOG_IF(ERROR, exposed_services) + << "DEPRECATED: exposed_services is going away"; + std::unique_ptr<ServiceProviderImpl> service_provider_impl( + new ServiceProviderImpl( + ConnectionContext(ConnectionContext::Type::INCOMING, requestor_url, + url), + services.Pass())); + if (!OnAcceptConnection(service_provider_impl.get())) + return; + service_provider_impls_.push_back(std::move(service_provider_impl)); +} + +void ApplicationImplBase::RequestQuit() { + OnQuit(); + Terminate(); +} + +} // namespace mojo
diff --git a/mojo/public/cpp/application/lib/application_runner.cc b/mojo/public/cpp/application/lib/application_runner.cc index 4ef544b..a5c87b7 100644 --- a/mojo/public/cpp/application/lib/application_runner.cc +++ b/mojo/public/cpp/application/lib/application_runner.cc
@@ -6,6 +6,7 @@ #include "mojo/public/cpp/application/application_delegate.h" #include "mojo/public/cpp/application/application_impl.h" +#include "mojo/public/cpp/application/application_impl_base.h" #include "mojo/public/cpp/environment/environment.h" #include "mojo/public/cpp/environment/logging.h" #include "mojo/public/cpp/utility/run_loop.h" @@ -16,7 +17,7 @@ } // namespace // static -void ApplicationImpl::Terminate() { +void ApplicationImplBase::Terminate() { RunLoop::current()->Quit(); }
diff --git a/mojo/ui/view_provider_app.h b/mojo/ui/view_provider_app.h index 177f419..4f6293b 100644 --- a/mojo/ui/view_provider_app.h +++ b/mojo/ui/view_provider_app.h
@@ -9,6 +9,7 @@ #include "mojo/common/strong_binding_set.h" #include "mojo/public/c/system/main.h" +#include "mojo/public/cpp/application/application_delegate.h" #include "mojo/public/cpp/application/application_impl.h" #include "mojo/public/cpp/application/service_provider_impl.h" #include "mojo/public/cpp/system/macros.h"
diff --git a/services/nacl/nonsfi/content_handler_main_nexe.cc b/services/nacl/nonsfi/content_handler_main_nexe.cc index 207ecf0..0ccada1 100644 --- a/services/nacl/nonsfi/content_handler_main_nexe.cc +++ b/services/nacl/nonsfi/content_handler_main_nexe.cc
@@ -11,6 +11,7 @@ #include "mojo/message_pump/message_pump_mojo.h" #include "mojo/nacl/nonsfi/nexe_launcher_nonsfi.h" #include "mojo/public/c/system/main.h" +#include "mojo/public/cpp/application/application_delegate.h" #include "mojo/public/cpp/application/application_impl.h" namespace nacl {
diff --git a/services/nacl/nonsfi/content_handler_main_pexe.cc b/services/nacl/nonsfi/content_handler_main_pexe.cc index b992367..f0ecc3b 100644 --- a/services/nacl/nonsfi/content_handler_main_pexe.cc +++ b/services/nacl/nonsfi/content_handler_main_pexe.cc
@@ -15,6 +15,7 @@ #include "mojo/nacl/nonsfi/file_util.h" #include "mojo/nacl/nonsfi/nexe_launcher_nonsfi.h" #include "mojo/public/c/system/main.h" +#include "mojo/public/cpp/application/application_delegate.h" #include "mojo/public/cpp/application/application_impl.h" #include "mojo/public/cpp/application/connect.h" #include "mojo/public/cpp/bindings/array.h"