diff options
author | sky <sky@chromium.org> | 2015-08-31 17:58:50 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-09-01 00:59:26 +0000 |
commit | 6e094e866fc853c369d2cf27fc947bd0708c6840 (patch) | |
tree | 242a733e7122b71e4ea686a4e045a2c91ae6ee20 | |
parent | 2b15299836d8c046ac3315e87ce3cd5f3af9ce50 (diff) | |
download | chromium_src-6e094e866fc853c369d2cf27fc947bd0708c6840.zip chromium_src-6e094e866fc853c369d2cf27fc947bd0708c6840.tar.gz chromium_src-6e094e866fc853c369d2cf27fc947bd0708c6840.tar.bz2 |
Adds a way to determine id of content handler that created app
This is needed for html viewer so that it can know which html_viewer is servicing the request.
BUG=479172,490221
TEST=covered by tests
R=ben@chromium.org
Review URL: https://codereview.chromium.org/1311353005
Cr-Commit-Position: refs/heads/master@{#346541}
28 files changed, 502 insertions, 144 deletions
diff --git a/components/font_service/public/cpp/font_loader.cc b/components/font_service/public/cpp/font_loader.cc index 5a1e8f5..c7886a7 100644 --- a/components/font_service/public/cpp/font_loader.cc +++ b/components/font_service/public/cpp/font_loader.cc @@ -4,22 +4,25 @@ #include "components/font_service/public/cpp/font_loader.h" +#include "base/bind.h" #include "components/font_service/public/cpp/font_service_thread.h" #include "mojo/application/public/cpp/application_impl.h" #include "mojo/application/public/cpp/connect.h" #include "mojo/application/public/interfaces/shell.mojom.h" namespace font_service { +namespace { +void OnGotContentHandlerID(uint32_t content_handler_id) {} +} // namespace FontLoader::FontLoader(mojo::Shell* shell) { mojo::ServiceProviderPtr font_service_provider; mojo::URLRequestPtr request(mojo::URLRequest::New()); request->url = mojo::String::From("mojo:font_service"); FontServicePtr font_service; - shell->ConnectToApplication(request.Pass(), - GetProxy(&font_service_provider), - nullptr, - nullptr); + shell->ConnectToApplication(request.Pass(), GetProxy(&font_service_provider), + nullptr, nullptr, + base::Bind(&OnGotContentHandlerID)); mojo::ConnectToService(font_service_provider.get(), &font_service); thread_ = new internal::FontServiceThread(font_service.Pass()); diff --git a/components/html_viewer/media_factory.cc b/components/html_viewer/media_factory.cc index ebae252..260df92 100644 --- a/components/html_viewer/media_factory.cc +++ b/components/html_viewer/media_factory.cc @@ -44,6 +44,8 @@ bool AreSecureCodecsSupported() { return false; } +void OnGotContentHandlerID(uint32_t content_handler_id) {} + } // namespace MediaFactory::MediaFactory( @@ -120,7 +122,8 @@ media::interfaces::ServiceFactory* MediaFactory::GetMediaServiceFactory() { mojo::URLRequestPtr request(mojo::URLRequest::New()); request->url = mojo::String::From("mojo:media"); shell_->ConnectToApplication(request.Pass(), GetProxy(&service_provider), - nullptr, nullptr); + nullptr, nullptr, + base::Bind(&OnGotContentHandlerID)); mojo::ConnectToService(service_provider.get(), &media_service_factory_); } diff --git a/components/pdf_viewer/pdf_viewer.cc b/components/pdf_viewer/pdf_viewer.cc index 730ce3a..fbdd506 100644 --- a/components/pdf_viewer/pdf_viewer.cc +++ b/components/pdf_viewer/pdf_viewer.cc @@ -53,6 +53,8 @@ void LostContext(void*) { DCHECK(false); } +void OnGotContentHandlerID(uint32_t content_handler_id) {} + // BitmapUploader is useful if you want to draw a bitmap or color in a View. class BitmapUploader : public mojo::SurfaceClient { public: @@ -79,7 +81,7 @@ class BitmapUploader : public mojo::SurfaceClient { request2->url = mojo::String::From("mojo:view_manager"); shell->ConnectToApplication(request2.Pass(), mojo::GetProxy(&gpu_service_provider), nullptr, - nullptr); + nullptr, base::Bind(&OnGotContentHandlerID)); ConnectToService(gpu_service_provider.get(), &gpu_service_); mojo::CommandBufferPtr gles2_client; diff --git a/components/resource_provider/public/cpp/resource_loader.cc b/components/resource_provider/public/cpp/resource_loader.cc index e26c9dc..3b6ea16 100644 --- a/components/resource_provider/public/cpp/resource_loader.cc +++ b/components/resource_provider/public/cpp/resource_loader.cc @@ -29,10 +29,9 @@ ResourceLoader::ResourceLoader(mojo::Shell* shell, mojo::URLRequestPtr request(mojo::URLRequest::New()); request->url = mojo::String::From("mojo:resource_provider"); mojo::ServiceProviderPtr resource_provider_service_provider; - shell->ConnectToApplication(request.Pass(), - GetProxy(&resource_provider_service_provider), - nullptr, - nullptr); + shell->ConnectToApplication( + request.Pass(), GetProxy(&resource_provider_service_provider), nullptr, + nullptr, mojo::Shell::ConnectToApplicationCallback()); mojo::ConnectToService(resource_provider_service_provider.get(), &resource_provider_); std::vector<std::string> paths_vector(paths.begin(), paths.end()); diff --git a/content/browser/frame_host/frame_mojo_shell.cc b/content/browser/frame_host/frame_mojo_shell.cc index c230403..91a3875 100644 --- a/content/browser/frame_host/frame_mojo_shell.cc +++ b/content/browser/frame_host/frame_mojo_shell.cc @@ -32,7 +32,8 @@ void FrameMojoShell::ConnectToApplication( mojo::URLRequestPtr application_url, mojo::InterfaceRequest<mojo::ServiceProvider> services, mojo::ServiceProviderPtr /* exposed_services */, - mojo::CapabilityFilterPtr filter) { + mojo::CapabilityFilterPtr filter, + const ConnectToApplicationCallback& callback) { mojo::ServiceProviderPtr frame_services; service_provider_bindings_.AddBinding(GetServiceRegistry(), GetProxy(&frame_services)); @@ -43,7 +44,7 @@ void FrameMojoShell::ConnectToApplication( capability_filter = filter->filter.To<mojo::shell::CapabilityFilter>(); MojoShellContext::ConnectToApplication( GURL(application_url->url), frame_host_->GetSiteInstance()->GetSiteURL(), - services.Pass(), frame_services.Pass(), capability_filter); + services.Pass(), frame_services.Pass(), capability_filter, callback); } void FrameMojoShell::QuitApplication() { diff --git a/content/browser/frame_host/frame_mojo_shell.h b/content/browser/frame_host/frame_mojo_shell.h index 5421ea1..b2817a0 100644 --- a/content/browser/frame_host/frame_mojo_shell.h +++ b/content/browser/frame_host/frame_mojo_shell.h @@ -31,7 +31,8 @@ class FrameMojoShell : public mojo::Shell { mojo::URLRequestPtr application_url, mojo::InterfaceRequest<mojo::ServiceProvider> services, mojo::ServiceProviderPtr exposed_services, - mojo::CapabilityFilterPtr filter) override; + mojo::CapabilityFilterPtr filter, + const ConnectToApplicationCallback& callback) override; void QuitApplication() override; ServiceRegistryImpl* GetServiceRegistry(); diff --git a/content/browser/mojo/mojo_app_connection_impl.cc b/content/browser/mojo/mojo_app_connection_impl.cc index 06d07c5..ca8d5a5 100644 --- a/content/browser/mojo/mojo_app_connection_impl.cc +++ b/content/browser/mojo/mojo_app_connection_impl.cc @@ -4,6 +4,7 @@ #include "content/browser/mojo/mojo_app_connection_impl.h" +#include "base/bind.h" #include "content/browser/mojo/mojo_shell_context.h" #include "mojo/shell/capability_filter.h" @@ -11,6 +12,10 @@ namespace content { const char kBrowserMojoAppUrl[] = "system:content_browser"; +namespace { +void OnGotContentHandlerID(uint32_t content_handler_id) {} +} // namespace + // static scoped_ptr<MojoAppConnection> MojoAppConnection::Create( const GURL& url, @@ -23,7 +28,8 @@ MojoAppConnectionImpl::MojoAppConnectionImpl(const GURL& url, const GURL& requestor_url) { MojoShellContext::ConnectToApplication( url, requestor_url, mojo::GetProxy(&services_), - mojo::ServiceProviderPtr(), mojo::shell::GetPermissiveCapabilityFilter()); + mojo::ServiceProviderPtr(), mojo::shell::GetPermissiveCapabilityFilter(), + base::Bind(&OnGotContentHandlerID)); } MojoAppConnectionImpl::~MojoAppConnectionImpl() { diff --git a/content/browser/mojo/mojo_shell_context.cc b/content/browser/mojo/mojo_shell_context.cc index aee1a2e..2f84ac2 100644 --- a/content/browser/mojo/mojo_shell_context.cc +++ b/content/browser/mojo/mojo_shell_context.cc @@ -99,12 +99,13 @@ class MojoShellContext::Proxy { const GURL& requestor_url, mojo::InterfaceRequest<mojo::ServiceProvider> request, mojo::ServiceProviderPtr exposed_services, - const mojo::shell::CapabilityFilter& filter) { + const mojo::shell::CapabilityFilter& filter, + const mojo::Shell::ConnectToApplicationCallback& callback) { if (task_runner_ == base::ThreadTaskRunnerHandle::Get()) { if (shell_context_) { shell_context_->ConnectToApplicationOnOwnThread( - url, requestor_url, request.Pass(), exposed_services.Pass(), - filter); + url, requestor_url, request.Pass(), exposed_services.Pass(), filter, + callback); } } else { // |shell_context_| outlives the main MessageLoop, so it's safe for it to @@ -114,7 +115,7 @@ class MojoShellContext::Proxy { base::Bind(&MojoShellContext::ConnectToApplicationOnOwnThread, base::Unretained(shell_context_), url, requestor_url, base::Passed(&request), base::Passed(&exposed_services), - filter)); + filter, callback)); } } @@ -186,9 +187,10 @@ void MojoShellContext::ConnectToApplication( const GURL& requestor_url, mojo::InterfaceRequest<mojo::ServiceProvider> request, mojo::ServiceProviderPtr exposed_services, - const mojo::shell::CapabilityFilter& filter) { + const mojo::shell::CapabilityFilter& filter, + const mojo::Shell::ConnectToApplicationCallback& callback) { proxy_.Get()->ConnectToApplication(url, requestor_url, request.Pass(), - exposed_services.Pass(), filter); + exposed_services.Pass(), filter, callback); } void MojoShellContext::ConnectToApplicationOnOwnThread( @@ -196,12 +198,13 @@ void MojoShellContext::ConnectToApplicationOnOwnThread( const GURL& requestor_url, mojo::InterfaceRequest<mojo::ServiceProvider> request, mojo::ServiceProviderPtr exposed_services, - const mojo::shell::CapabilityFilter& filter) { + const mojo::shell::CapabilityFilter& filter, + const mojo::Shell::ConnectToApplicationCallback& callback) { mojo::URLRequestPtr url_request = mojo::URLRequest::New(); url_request->url = mojo::String::From(url); application_manager_->ConnectToApplication( nullptr, url_request.Pass(), std::string(), requestor_url, request.Pass(), - exposed_services.Pass(), filter, base::Bind(&base::DoNothing)); + exposed_services.Pass(), filter, base::Bind(&base::DoNothing), callback); } GURL MojoShellContext::ResolveMappings(const GURL& url) { diff --git a/content/browser/mojo/mojo_shell_context.h b/content/browser/mojo/mojo_shell_context.h index ffe7864..897c01b 100644 --- a/content/browser/mojo/mojo_shell_context.h +++ b/content/browser/mojo/mojo_shell_context.h @@ -13,6 +13,7 @@ #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "content/common/content_export.h" +#include "mojo/application/public/interfaces/shell.mojom.h" #include "mojo/shell/application_manager.h" class GURL; @@ -43,7 +44,8 @@ class CONTENT_EXPORT MojoShellContext const GURL& requestor_url, mojo::InterfaceRequest<mojo::ServiceProvider> request, mojo::ServiceProviderPtr exposed_services, - const mojo::shell::CapabilityFilter& filter); + const mojo::shell::CapabilityFilter& filter, + const mojo::Shell::ConnectToApplicationCallback& callback); static void SetApplicationsForTest(const StaticApplicationMap* apps); @@ -56,7 +58,8 @@ class CONTENT_EXPORT MojoShellContext const GURL& requestor_url, mojo::InterfaceRequest<mojo::ServiceProvider> request, mojo::ServiceProviderPtr exposed_services, - const mojo::shell::CapabilityFilter& filter); + const mojo::shell::CapabilityFilter& filter, + const mojo::Shell::ConnectToApplicationCallback& callback); // mojo::shell::ApplicationManager::Delegate: GURL ResolveMappings(const GURL& url) override; diff --git a/content/renderer/render_frame_impl.cc b/content/renderer/render_frame_impl.cc index 3659a5e..cd3e901 100644 --- a/content/renderer/render_frame_impl.cc +++ b/content/renderer/render_frame_impl.cc @@ -537,6 +537,8 @@ bool IsReload(FrameMsg_Navigate_Type::Value navigation_type) { RenderFrameImpl::CreateRenderFrameImplFunction g_create_render_frame_impl = nullptr; +void OnGotContentHandlerID(uint32_t content_handler_id) {} + } // namespace // static @@ -5090,7 +5092,8 @@ mojo::ServiceProviderPtr RenderFrameImpl::ConnectToApplication( mojo::URLRequestPtr request(mojo::URLRequest::New()); request->url = mojo::String::From(url); mojo_shell_->ConnectToApplication(request.Pass(), GetProxy(&service_provider), - nullptr, nullptr); + nullptr, nullptr, + base::Bind(&OnGotContentHandlerID)); return service_provider.Pass(); } diff --git a/mandoline/ui/aura/surface_binding.cc b/mandoline/ui/aura/surface_binding.cc index 6a2a236..998a810 100644 --- a/mandoline/ui/aura/surface_binding.cc +++ b/mandoline/ui/aura/surface_binding.cc @@ -27,6 +27,9 @@ #include "mojo/public/cpp/bindings/binding.h" namespace mandoline { +namespace { +void OnGotContentHandlerID(uint32_t content_handler_id) {} +} // namespace // PerConnectionState ---------------------------------------------------------- @@ -121,10 +124,9 @@ void SurfaceBinding::PerConnectionState::Init() { mojo::ServiceProviderPtr service_provider; mojo::URLRequestPtr request(mojo::URLRequest::New()); request->url = mojo::String::From("mojo:view_manager"); - shell_->ConnectToApplication(request.Pass(), - GetProxy(&service_provider), - nullptr, - nullptr); + shell_->ConnectToApplication(request.Pass(), GetProxy(&service_provider), + nullptr, nullptr, + base::Bind(&OnGotContentHandlerID)); ConnectToService(service_provider.get(), &gpu_); } diff --git a/mojo/application/public/cpp/application_connection.h b/mojo/application/public/cpp/application_connection.h index e4affba..cb42e17 100644 --- a/mojo/application/public/cpp/application_connection.h +++ b/mojo/application/public/cpp/application_connection.h @@ -116,6 +116,17 @@ class ApplicationConnection { virtual void SetRemoteServiceProviderConnectionErrorHandler( const Closure& handler) = 0; + // Returns the id of the deepest content handler used in connecting to + // the application. If the content handler id has not yet been determined + // this returns false, use AddContentHandlerIDCallback() to schedule a + // callback when the content handler is has been obtained. A value of 0 + // indicates no content handler was used in connecting to the application. + virtual bool GetContentHandlerID(uint32_t* content_handler_id) = 0; + + // See description in GetTargetID(). If the id of the content handler has + // been obtained |callback| is run immediately. + virtual void AddContentHandlerIDCallback(const Closure& callback) = 0; + protected: // Returns true if the connector was set, false if it was not set (e.g. by // some filtering policy preventing this interface from being exposed). diff --git a/mojo/application/public/cpp/lib/application_impl.cc b/mojo/application/public/cpp/lib/application_impl.cc index 7885e50..7ea8834 100644 --- a/mojo/application/public/cpp/lib/application_impl.cc +++ b/mojo/application/public/cpp/lib/application_impl.cc @@ -60,17 +60,20 @@ scoped_ptr<ApplicationConnection> InterfaceRequest<ServiceProvider> local_request = GetProxy(&local_services); ServiceProviderPtr remote_services; std::string application_url = request->url.To<std::string>(); - shell_->ConnectToApplication(request.Pass(), GetProxy(&remote_services), - local_services.Pass(), filter.Pass()); // We allow all interfaces on outgoing connections since we are presumably in // a position to know who we're talking to. // TODO(beng): is this a valid assumption or do we need to figure some way to // filter here too? std::set<std::string> allowed; allowed.insert("*"); - scoped_ptr<ApplicationConnection> registry(new internal::ServiceRegistry( + InterfaceRequest<ServiceProvider> remote_services_proxy = + GetProxy(&remote_services); + scoped_ptr<internal::ServiceRegistry> registry(new internal::ServiceRegistry( application_url, application_url, remote_services.Pass(), local_request.Pass(), allowed)); + shell_->ConnectToApplication(request.Pass(), remote_services_proxy.Pass(), + local_services.Pass(), filter.Pass(), + registry->GetConnectToApplicationCallback()); if (!delegate_->ConfigureOutgoingConnection(registry.get())) return nullptr; return registry.Pass(); diff --git a/mojo/application/public/cpp/lib/service_registry.cc b/mojo/application/public/cpp/lib/service_registry.cc index 8b3be11..7edf8d6 100644 --- a/mojo/application/public/cpp/lib/service_registry.cc +++ b/mojo/application/public/cpp/lib/service_registry.cc @@ -4,6 +4,7 @@ #include "mojo/application/public/cpp/lib/service_registry.h" +#include "base/bind.h" #include "base/logging.h" #include "mojo/application/public/cpp/application_connection.h" #include "mojo/application/public/cpp/service_connector.h" @@ -24,6 +25,8 @@ ServiceRegistry::ServiceRegistry( allowed_interfaces_(allowed_interfaces), allow_all_interfaces_(allowed_interfaces_.size() == 1 && allowed_interfaces_.count("*") == 1), + content_handler_id_(0u), + is_content_handler_id_valid_(false), weak_factory_(this) { if (local_services.is_pending()) local_binding_.Bind(local_services.Pass()); @@ -38,6 +41,12 @@ ServiceRegistry::ServiceRegistry() ServiceRegistry::~ServiceRegistry() { } +Shell::ConnectToApplicationCallback +ServiceRegistry::GetConnectToApplicationCallback() { + return base::Bind(&ServiceRegistry::OnGotContentHandlerID, + weak_factory_.GetWeakPtr()); +} + void ServiceRegistry::SetServiceConnector(ServiceConnector* connector) { service_connector_registry_.set_service_connector(connector); } @@ -65,6 +74,22 @@ void ServiceRegistry::SetRemoteServiceProviderConnectionErrorHandler( remote_service_provider_.set_connection_error_handler(handler); } +bool ServiceRegistry::GetContentHandlerID(uint32_t* content_handler_id) { + if (!is_content_handler_id_valid_) + return false; + + *content_handler_id = content_handler_id_; + return true; +} + +void ServiceRegistry::AddContentHandlerIDCallback(const Closure& callback) { + if (is_content_handler_id_valid_) { + callback.Run(); + return; + } + content_handler_id_callbacks_.push_back(callback); +} + base::WeakPtr<ApplicationConnection> ServiceRegistry::GetWeakPtr() { return weak_factory_.GetWeakPtr(); } @@ -88,6 +113,16 @@ ServiceProvider* ServiceRegistry::GetServiceProvider() { return remote_service_provider_.get(); } +void ServiceRegistry::OnGotContentHandlerID(uint32_t content_handler_id) { + DCHECK(!is_content_handler_id_valid_); + is_content_handler_id_valid_ = true; + content_handler_id_ = content_handler_id; + std::vector<Closure> callbacks; + callbacks.swap(content_handler_id_callbacks_); + for (auto callback : callbacks) + callback.Run(); +} + void ServiceRegistry::ConnectToService(const mojo::String& service_name, ScopedMessagePipeHandle client_handle) { service_connector_registry_.ConnectToService(this, service_name, diff --git a/mojo/application/public/cpp/lib/service_registry.h b/mojo/application/public/cpp/lib/service_registry.h index 8cb1d1b..c3610bf 100644 --- a/mojo/application/public/cpp/lib/service_registry.h +++ b/mojo/application/public/cpp/lib/service_registry.h @@ -11,6 +11,7 @@ #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" +#include "mojo/application/public/interfaces/shell.mojom.h" #include "mojo/public/cpp/bindings/binding.h" namespace mojo { @@ -32,6 +33,8 @@ class ServiceRegistry : public ServiceProvider, public ApplicationConnection { const std::set<std::string>& allowed_interfaces); ~ServiceRegistry() override; + Shell::ConnectToApplicationCallback GetConnectToApplicationCallback(); + // ApplicationConnection overrides. void SetServiceConnector(ServiceConnector* service_connector) override; bool SetServiceConnectorForName(ServiceConnector* service_connector, @@ -42,11 +45,15 @@ class ServiceRegistry : public ServiceProvider, public ApplicationConnection { ServiceProvider* GetLocalServiceProvider() override; void SetRemoteServiceProviderConnectionErrorHandler( const Closure& handler) override; + bool GetContentHandlerID(uint32_t* target_id) override; + void AddContentHandlerIDCallback(const Closure& callback) override; base::WeakPtr<ApplicationConnection> GetWeakPtr() override; void RemoveServiceConnectorForName(const std::string& interface_name); private: + void OnGotContentHandlerID(uint32_t content_handler_id); + // ServiceProvider method. void ConnectToService(const mojo::String& service_name, ScopedMessagePipeHandle client_handle) override; @@ -58,7 +65,12 @@ class ServiceRegistry : public ServiceProvider, public ApplicationConnection { ServiceConnectorRegistry service_connector_registry_; const std::set<std::string> allowed_interfaces_; const bool allow_all_interfaces_; - base::WeakPtrFactory<ApplicationConnection> weak_factory_; + // The id of the content_handler is only available once the callback from + // establishing the connection is made. + uint32_t content_handler_id_; + bool is_content_handler_id_valid_; + std::vector<Closure> content_handler_id_callbacks_; + base::WeakPtrFactory<ServiceRegistry> weak_factory_; MOJO_DISALLOW_COPY_AND_ASSIGN(ServiceRegistry); }; diff --git a/mojo/application/public/interfaces/shell.mojom b/mojo/application/public/interfaces/shell.mojom index 3a313dd..acec2c6d 100644 --- a/mojo/application/public/interfaces/shell.mojom +++ b/mojo/application/public/interfaces/shell.mojom @@ -24,6 +24,9 @@ struct CapabilityFilter { // An interface through which a Mojo application may communicate with the Mojo // system and request connections to other applications. interface Shell { + // Used to indicate the app was not launched by a content handler. + const uint32 kInvalidContentHandlerID = 0; + // Establishes a connection with another application ("target application") // (located at |request->url|) through which the calling application and the // target application may request services from one another. @@ -56,10 +59,16 @@ interface Shell { // CapabilityFilter above. Note also that this parameter may be NULL, which // has the same meaning as allowing the target application to connect to // any application and service. + // + // If the connection to |application_url| involves a content handler, then + // |content_handler_id| is the id of the deepest content handler used to + // establish the connection to |application_url|. If no content handler is + // used |content_handler_id| is kInvalidContentHandlerID. + // TODO(beng): determine if we need to expose the target application id also. ConnectToApplication(URLRequest application_url, ServiceProvider&? services, ServiceProvider? exposed_services, - CapabilityFilter? filter); + CapabilityFilter? filter) => (uint32 content_handler_id); // When there are no more instantiated services in an application, it should // start its shutdown process by calling this method. Additionally, it should diff --git a/mojo/runner/about_fetcher_unittest.cc b/mojo/runner/about_fetcher_unittest.cc index 08470b5..0dfd7a1 100644 --- a/mojo/runner/about_fetcher_unittest.cc +++ b/mojo/runner/about_fetcher_unittest.cc @@ -135,7 +135,7 @@ class AboutFetcherTest : public testing::Test { application_manager_->ConnectToApplication( nullptr, request.Pass(), std::string(), GURL(), service_provider_request.Pass(), nullptr, shell::CapabilityFilter(), - base::Closure()); + base::Closure(), shell::EmptyConnectCallback()); run_loop.Run(); } diff --git a/mojo/runner/context.cc b/mojo/runner/context.cc index 7b5be56..fd93119 100644 --- a/mojo/runner/context.cc +++ b/mojo/runner/context.cc @@ -193,10 +193,11 @@ void InitDevToolsServiceIfNeeded(shell::ApplicationManager* manager, ServiceProviderPtr devtools_service_provider; URLRequestPtr request(URLRequest::New()); request->url = "mojo:devtools_service"; - manager->ConnectToApplication( - nullptr, request.Pass(), std::string(), GURL("mojo:shell"), - GetProxy(&devtools_service_provider), nullptr, - shell::GetPermissiveCapabilityFilter(), base::Closure()); + manager->ConnectToApplication(nullptr, request.Pass(), std::string(), + GURL("mojo:shell"), + GetProxy(&devtools_service_provider), nullptr, + shell::GetPermissiveCapabilityFilter(), + base::Closure(), shell::EmptyConnectCallback()); devtools_service::DevToolsCoordinatorPtr devtools_coordinator; devtools_service_provider->ConnectToService( @@ -314,7 +315,8 @@ bool Context::Init() { application_manager_.ConnectToApplication( nullptr, request.Pass(), std::string(), GURL(), GetProxy(&service_provider_ptr), tracing_service_provider_ptr.Pass(), - shell::GetPermissiveCapabilityFilter(), base::Closure()); + shell::GetPermissiveCapabilityFilter(), base::Closure(), + shell::EmptyConnectCallback()); // Record the shell startup metrics used for performance testing. if (base::CommandLine::ForCurrentProcess()->HasSwitch( @@ -381,7 +383,8 @@ void Context::Run(const GURL& url) { application_manager_.ConnectToApplication( nullptr, request.Pass(), std::string(), GURL(), GetProxy(&services), exposed_services.Pass(), shell::GetPermissiveCapabilityFilter(), - base::Bind(&Context::OnApplicationEnd, base::Unretained(this), url)); + base::Bind(&Context::OnApplicationEnd, base::Unretained(this), url), + shell::EmptyConnectCallback()); } void Context::RunCommandLineApplication(const base::Closure& callback) { diff --git a/mojo/runner/native_runner_unittest.cc b/mojo/runner/native_runner_unittest.cc index f717642..351fb34 100644 --- a/mojo/runner/native_runner_unittest.cc +++ b/mojo/runner/native_runner_unittest.cc @@ -106,7 +106,7 @@ TEST_F(NativeApplicationLoaderTest, DoesNotExist) { application_manager_.ConnectToApplication( nullptr, request.Pass(), std::string(), GURL(), services.Pass(), service_provider.Pass(), shell::GetPermissiveCapabilityFilter(), - base::Closure()); + base::Closure(), shell::EmptyConnectCallback()); EXPECT_FALSE(state_.runner_was_created); EXPECT_FALSE(state_.runner_was_started); EXPECT_FALSE(state_.runner_was_destroyed); diff --git a/mojo/runner/shell_test_base.cc b/mojo/runner/shell_test_base.cc index efa5656..890ff3d 100644 --- a/mojo/runner/shell_test_base.cc +++ b/mojo/runner/shell_test_base.cc @@ -54,7 +54,7 @@ ScopedMessagePipeHandle ShellTestBase::ConnectToService( shell_context_.application_manager()->ConnectToApplication( nullptr, request.Pass(), std::string(), GURL(), GetProxy(&services), nullptr, shell::GetPermissiveCapabilityFilter(), - base::Bind(&QuitIfRunning)); + base::Bind(&QuitIfRunning), shell::EmptyConnectCallback()); MessagePipe pipe; services->ConnectToService(service_name, pipe.handle1.Pass()); return pipe.handle0.Pass(); diff --git a/mojo/shell/application_instance.cc b/mojo/shell/application_instance.cc index 13a25763..1c2479b 100644 --- a/mojo/shell/application_instance.cc +++ b/mojo/shell/application_instance.cc @@ -10,9 +10,11 @@ #include "mojo/common/common_type_converters.h" #include "mojo/common/url_type_converters.h" #include "mojo/shell/application_manager.h" +#include "mojo/shell/content_handler_connection.h" namespace mojo { namespace shell { +namespace { // It's valid to specify mojo: URLs in the filter either as mojo:foo or // mojo://foo/ - but we store the filter in the latter form. @@ -29,6 +31,8 @@ CapabilityFilter CanonicalizeFilter(const CapabilityFilter& filter) { return canonicalized; } +} // namespace + ApplicationInstance::QueuedClientRequest::QueuedClientRequest() : originator(nullptr) {} @@ -41,12 +45,14 @@ ApplicationInstance::ApplicationInstance( const Identity& originator_identity, const Identity& identity, const CapabilityFilter& filter, + uint32_t requesting_content_handler_id, const base::Closure& on_application_end) : manager_(manager), originator_identity_(originator_identity), identity_(identity), filter_(CanonicalizeFilter(filter)), allow_any_application_(filter.size() == 1 && filter.count("*") == 1), + requesting_content_handler_id_(requesting_content_handler_id), on_application_end_(on_application_end), application_(application.Pass()), binding_(this), @@ -70,7 +76,9 @@ void ApplicationInstance::ConnectToClient( const GURL& requestor_url, InterfaceRequest<ServiceProvider> services, ServiceProviderPtr exposed_services, - const CapabilityFilter& filter) { + const CapabilityFilter& filter, + const ConnectToApplicationCallback& callback) { + callback.Run(requesting_content_handler_id_); if (queue_requests_) { QueuedClientRequest* queued_request = new QueuedClientRequest(); queued_request->originator = originator; @@ -108,24 +116,26 @@ void ApplicationInstance::ConnectToApplication( URLRequestPtr app_request, InterfaceRequest<ServiceProvider> services, ServiceProviderPtr exposed_services, - CapabilityFilterPtr filter) { + CapabilityFilterPtr filter, + const ConnectToApplicationCallback& callback) { std::string url_string = app_request->url.To<std::string>(); GURL url(url_string); if (!url.is_valid()) { LOG(ERROR) << "Error: invalid URL: " << url_string; + callback.Run(kInvalidContentHandlerID); return; } if (allow_any_application_ || filter_.find(url.spec()) != filter_.end()) { CapabilityFilter capability_filter = GetPermissiveCapabilityFilter(); if (!filter.is_null()) capability_filter = filter->filter.To<CapabilityFilter>(); - manager_->ConnectToApplication(this, app_request.Pass(), std::string(), - identity_.url, services.Pass(), - exposed_services.Pass(), capability_filter, - base::Closure()); + manager_->ConnectToApplication( + this, app_request.Pass(), std::string(), identity_.url, services.Pass(), + exposed_services.Pass(), capability_filter, base::Closure(), callback); } else { LOG(WARNING) << "CapabilityFilter prevented connection from: " << identity_.url << " to: " << url.spec(); + callback.Run(kInvalidContentHandlerID); } } @@ -167,12 +177,10 @@ void ApplicationInstance::OnConnectionError() { url->url = mojo::String::From(request->requested_url.spec()); ApplicationInstance* originator = manager->GetApplicationInstance(originator_identity_); - manager->ConnectToApplication(originator, url.Pass(), std::string(), - request->requestor_url, - request->services.Pass(), - request->exposed_services.Pass(), - request->filter, - base::Closure()); + manager->ConnectToApplication( + originator, url.Pass(), std::string(), request->requestor_url, + request->services.Pass(), request->exposed_services.Pass(), + request->filter, base::Closure(), EmptyConnectCallback()); } STLDeleteElements(&queued_client_requests); } @@ -183,11 +191,9 @@ void ApplicationInstance::OnQuitRequestedResult(bool can_quit) { queue_requests_ = false; for (auto request : queued_client_requests_) { - CallAcceptConnection(request->originator, - request->requestor_url, - request->services.Pass(), - request->exposed_services.Pass(), - request->requested_url); + CallAcceptConnection( + request->originator, request->requestor_url, request->services.Pass(), + request->exposed_services.Pass(), request->requested_url); } STLDeleteElements(&queued_client_requests_); } diff --git a/mojo/shell/application_instance.h b/mojo/shell/application_instance.h index f50ab82..22b4cb1 100644 --- a/mojo/shell/application_instance.h +++ b/mojo/shell/application_instance.h @@ -24,11 +24,15 @@ class ApplicationManager; // shell's ApplicationManager. class ApplicationInstance : public Shell { public: + // |requesting_content_handler_id| is the id of the content handler that + // loaded this app. If the app was not loaded by a content handler the id + // is kInvalidContentHandlerID. ApplicationInstance(ApplicationPtr application, ApplicationManager* manager, const Identity& originator_identity, const Identity& resolved_identity, const CapabilityFilter& filter, + uint32_t requesting_content_handler_id, const base::Closure& on_application_end); ~ApplicationInstance() override; @@ -40,7 +44,8 @@ class ApplicationInstance : public Shell { const GURL& requestor_url, InterfaceRequest<ServiceProvider> services, ServiceProviderPtr exposed_services, - const CapabilityFilter& filter); + const CapabilityFilter& filter, + const ConnectToApplicationCallback& callback); // Returns the set of interfaces this application instance is allowed to see // from an instance with |identity|. @@ -49,13 +54,21 @@ class ApplicationInstance : public Shell { Application* application() { return application_.get(); } const Identity& identity() const { return identity_; } base::Closure on_application_end() const { return on_application_end_; } + void set_requesting_content_handler_id(uint32_t id) { + requesting_content_handler_id_ = id; + } + uint32_t requesting_content_handler_id() const { + return requesting_content_handler_id_; + } private: // Shell implementation: - void ConnectToApplication(URLRequestPtr app_request, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - CapabilityFilterPtr filter) override; + void ConnectToApplication( + URLRequestPtr app_request, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + CapabilityFilterPtr filter, + const ConnectToApplicationCallback& callback) override; void QuitApplication() override; void CallAcceptConnection(ApplicationInstance* originator, @@ -77,6 +90,7 @@ class ApplicationInstance : public Shell { InterfaceRequest<ServiceProvider> services; ServiceProviderPtr exposed_services; CapabilityFilter filter; + ConnectToApplicationCallback connect_callback; }; ApplicationManager* const manager_; @@ -84,6 +98,7 @@ class ApplicationInstance : public Shell { const Identity identity_; const CapabilityFilter filter_; const bool allow_any_application_; + uint32_t requesting_content_handler_id_; base::Closure on_application_end_; ApplicationPtr application_; Binding<Shell> binding_; diff --git a/mojo/shell/application_manager.cc b/mojo/shell/application_manager.cc index 782163c..acafadb 100644 --- a/mojo/shell/application_manager.cc +++ b/mojo/shell/application_manager.cc @@ -30,6 +30,8 @@ namespace { // Used by TestAPI. bool has_created_instance = false; +void OnEmptyOnConnectCallback(uint32_t content_handler_id) {} + } // namespace // static @@ -51,8 +53,10 @@ bool ApplicationManager::TestAPI::HasRunningInstanceForURL( } ApplicationManager::ApplicationManager(Delegate* delegate) - : delegate_(delegate), weak_ptr_factory_(this) { -} + : delegate_(delegate), + disable_cache_(false), + content_handler_id_counter_(0u), + weak_ptr_factory_(this) {} ApplicationManager::~ApplicationManager() { URLToContentHandlerMap url_to_content_handler(url_to_content_handler_); @@ -75,7 +79,8 @@ void ApplicationManager::ConnectToApplication( InterfaceRequest<ServiceProvider> services, ServiceProviderPtr exposed_services, const CapabilityFilter& filter, - const base::Closure& on_application_end) { + const base::Closure& on_application_end, + const Shell::ConnectToApplicationCallback& connect_callback) { GURL requested_gurl(requested_url->url.To<std::string>()); TRACE_EVENT_INSTANT1( "mojo_shell", "ApplicationManager::ConnectToApplication", @@ -87,15 +92,15 @@ void ApplicationManager::ConnectToApplication( GURL mapped_url = delegate_->ResolveMappings(requested_gurl); if (ConnectToRunningApplication(originator, mapped_url, qualifier, - requestor_url, &services, - &exposed_services, filter)) { + requestor_url, &services, &exposed_services, + filter, connect_callback)) { return; } GURL resolved_url = delegate_->ResolveMojoURL(mapped_url); if (ConnectToRunningApplication(originator, resolved_url, qualifier, - requestor_url, &services, - &exposed_services, filter)) { + requestor_url, &services, &exposed_services, + filter, connect_callback)) { return; } @@ -103,21 +108,21 @@ void ApplicationManager::ConnectToApplication( if (ConnectToApplicationWithLoader( originator, requested_gurl, qualifier, mapped_url, requestor_url, &services, &exposed_services, filter, on_application_end, - GetLoaderForURL(mapped_url))) { + connect_callback, GetLoaderForURL(mapped_url))) { return; } if (ConnectToApplicationWithLoader( originator, requested_gurl, qualifier, resolved_url, requestor_url, &services, &exposed_services, filter, on_application_end, - GetLoaderForURL(resolved_url))) { + connect_callback, GetLoaderForURL(resolved_url))) { return; } if (ConnectToApplicationWithLoader( originator, requested_gurl, qualifier, resolved_url, requestor_url, &services, &exposed_services, filter, on_application_end, - default_loader_.get())) { + connect_callback, default_loader_.get())) { return; } @@ -125,7 +130,7 @@ void ApplicationManager::ConnectToApplication( &ApplicationManager::HandleFetchCallback, weak_ptr_factory_.GetWeakPtr(), originator, requested_gurl, qualifier, requestor_url, base::Passed(services.Pass()), base::Passed(exposed_services.Pass()), - filter, on_application_end); + filter, on_application_end, connect_callback); if (delegate_->CreateFetcher( resolved_url, @@ -185,15 +190,16 @@ bool ApplicationManager::ConnectToRunningApplication( const GURL& requestor_url, InterfaceRequest<ServiceProvider>* services, ServiceProviderPtr* exposed_services, - const CapabilityFilter& filter) { + const CapabilityFilter& filter, + const Shell::ConnectToApplicationCallback& connect_callback) { ApplicationInstance* instance = GetApplicationInstance(Identity(resolved_url, qualifier)); if (!instance) return false; instance->ConnectToClient(originator, resolved_url, requestor_url, - services->Pass(), exposed_services->Pass(), - filter); + services->Pass(), exposed_services->Pass(), filter, + connect_callback); return true; } @@ -207,6 +213,7 @@ bool ApplicationManager::ConnectToApplicationWithLoader( ServiceProviderPtr* exposed_services, const CapabilityFilter& filter, const base::Closure& on_application_end, + const Shell::ConnectToApplicationCallback& connect_callback, ApplicationLoader* loader) { if (!loader) return false; @@ -217,8 +224,8 @@ bool ApplicationManager::ConnectToApplicationWithLoader( loader->Load( resolved_url, RegisterInstance(originator, app_url, qualifier, requestor_url, - services->Pass(), exposed_services->Pass(), - filter, on_application_end)); + services->Pass(), exposed_services->Pass(), filter, + on_application_end, connect_callback, nullptr)); return true; } @@ -230,7 +237,9 @@ InterfaceRequest<Application> ApplicationManager::RegisterInstance( InterfaceRequest<ServiceProvider> services, ServiceProviderPtr exposed_services, const CapabilityFilter& filter, - const base::Closure& on_application_end) { + const base::Closure& on_application_end, + const Shell::ConnectToApplicationCallback& connect_callback, + ApplicationInstance** resulting_instance) { Identity app_identity(app_url, qualifier); ApplicationPtr application; @@ -238,13 +247,15 @@ InterfaceRequest<Application> ApplicationManager::RegisterInstance( ApplicationInstance* instance = new ApplicationInstance( application.Pass(), this, originator ? originator->identity() : Identity(GURL()), app_identity, - filter, on_application_end); + filter, Shell::kInvalidContentHandlerID, on_application_end); DCHECK(identity_to_instance_.find(app_identity) == identity_to_instance_.end()); identity_to_instance_[app_identity] = instance; instance->InitializeApplication(); instance->ConnectToClient(originator, app_url, requestor_url, services.Pass(), - exposed_services.Pass(), filter); + exposed_services.Pass(), filter, connect_callback); + if (resulting_instance) + *resulting_instance = instance; return application_request.Pass(); } @@ -265,10 +276,12 @@ void ApplicationManager::HandleFetchCallback( ServiceProviderPtr exposed_services, const CapabilityFilter& filter, const base::Closure& on_application_end, + const Shell::ConnectToApplicationCallback& connect_callback, NativeApplicationCleanup cleanup, scoped_ptr<Fetcher> fetcher) { if (!fetcher) { // Network error. Drop |application_request| to tell requestor. + connect_callback.Run(Shell::kInvalidContentHandlerID); return; } @@ -284,7 +297,7 @@ void ApplicationManager::HandleFetchCallback( request->headers.push_back(header.Pass()); ConnectToApplication(originator, request.Pass(), qualifier, requestor_url, services.Pass(), exposed_services.Pass(), filter, - on_application_end); + on_application_end, connect_callback); return; } @@ -295,18 +308,19 @@ void ApplicationManager::HandleFetchCallback( // Also, it's possible the original URL was redirected to an app that is // already running. if (ConnectToRunningApplication(originator, requested_url, qualifier, - requestor_url, &services, - &exposed_services, filter)) { + requestor_url, &services, &exposed_services, + filter, connect_callback)) { return; } const GURL app_url = requested_url.scheme() == "mojo" ? requested_url : fetcher->GetURL(); + ApplicationInstance* app = nullptr; InterfaceRequest<Application> request( RegisterInstance(originator, app_url, qualifier, requestor_url, services.Pass(), exposed_services.Pass(), filter, - on_application_end)); + on_application_end, EmptyConnectCallback(), &app)); // For resources that are loaded with content handlers, we group app instances // by site. @@ -323,7 +337,8 @@ void ApplicationManager::HandleFetchCallback( std::string site = enable_multi_process ? response->site.To<std::string>() : std::string(); LoadWithContentHandler(originator, content_handler_url, requestor_url, site, - filter, request.Pass(), response.Pass()); + filter, connect_callback, app, request.Pass(), + response.Pass()); return; } @@ -333,7 +348,8 @@ void ApplicationManager::HandleFetchCallback( std::string site = enable_multi_process ? response->site.To<std::string>() : std::string(); LoadWithContentHandler(originator, iter->second, requestor_url, site, - filter, request.Pass(), response.Pass()); + filter, connect_callback, app, request.Pass(), + response.Pass()); return; } @@ -359,8 +375,8 @@ void ApplicationManager::HandleFetchCallback( } LoadWithContentHandler(originator, alias_iter->second.first, requestor_url, - qualifier, filter, request.Pass(), - response.Pass()); + qualifier, filter, connect_callback, app, + request.Pass(), response.Pass()); return; } @@ -390,6 +406,8 @@ void ApplicationManager::HandleFetchCallback( start_sandboxed = true; } + connect_callback.Run(Shell::kInvalidContentHandlerID); + fetcher->AsPath(blocking_pool_, base::Bind(&ApplicationManager::RunNativeApplication, weak_ptr_factory_.GetWeakPtr(), @@ -447,6 +465,8 @@ void ApplicationManager::LoadWithContentHandler( const GURL& requestor_url, const std::string& qualifier, const CapabilityFilter& filter, + const Shell::ConnectToApplicationCallback& connect_callback, + ApplicationInstance* app, InterfaceRequest<Application> application_request, URLResponsePtr url_response) { ContentHandlerConnection* connection = nullptr; @@ -458,13 +478,15 @@ void ApplicationManager::LoadWithContentHandler( connection = iter->second; } else { connection = new ContentHandlerConnection( - originator, this, content_handler_url, requestor_url, qualifier, - filter); + originator, this, content_handler_url, requestor_url, qualifier, filter, + ++content_handler_id_counter_); url_to_content_handler_[key] = connection; } + app->set_requesting_content_handler_id(connection->id()); connection->content_handler()->StartApplication(application_request.Pass(), url_response.Pass()); + connect_callback.Run(connection->id()); } void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader, @@ -546,11 +568,16 @@ ScopedMessagePipeHandle ApplicationManager::ConnectToServiceByName( request->url = mojo::String::From(application_url.spec()); ConnectToApplication(nullptr, request.Pass(), std::string(), GURL(), GetProxy(&services), nullptr, - GetPermissiveCapabilityFilter(), base::Closure()); + GetPermissiveCapabilityFilter(), base::Closure(), + EmptyConnectCallback()); MessagePipe pipe; services->ConnectToService(interface_name, pipe.handle1.Pass()); return pipe.handle0.Pass(); } +Shell::ConnectToApplicationCallback EmptyConnectCallback() { + return base::Bind(&OnEmptyOnConnectCallback); +} + } // namespace shell } // namespace mojo diff --git a/mojo/shell/application_manager.h b/mojo/shell/application_manager.h index 76b5482..cab1168 100644 --- a/mojo/shell/application_manager.h +++ b/mojo/shell/application_manager.h @@ -13,6 +13,7 @@ #include "base/memory/weak_ptr.h" #include "mojo/application/public/interfaces/application.mojom.h" #include "mojo/application/public/interfaces/service_provider.mojom.h" +#include "mojo/application/public/interfaces/shell.mojom.h" #include "mojo/public/cpp/bindings/interface_ptr_info.h" #include "mojo/public/cpp/bindings/interface_request.h" #include "mojo/services/network/public/interfaces/network_service.mojom.h" @@ -82,14 +83,16 @@ class ApplicationManager { // |originator| can be NULL (e.g. for the first application or in tests), but // typically is non-NULL and identifies the instance initiating the // connection. - void ConnectToApplication(ApplicationInstance* originator, - URLRequestPtr requested_url, - const std::string& qualifier, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - const CapabilityFilter& capability_filter, - const base::Closure& on_application_end); + void ConnectToApplication( + ApplicationInstance* originator, + URLRequestPtr requested_url, + const std::string& qualifier, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + const CapabilityFilter& capability_filter, + const base::Closure& on_application_end, + const Shell::ConnectToApplicationCallback& connect_callback); // Must only be used by shell internals and test code as it does not forward // capability filters. @@ -167,13 +170,15 @@ class ApplicationManager { using URLToLoaderMap = std::map<GURL, ApplicationLoader*>; using URLToNativeOptionsMap = std::map<GURL, NativeRunnerFactory::Options>; - bool ConnectToRunningApplication(ApplicationInstance* originator, - const GURL& resolved_url, - const std::string& qualifier, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider>* services, - ServiceProviderPtr* exposed_services, - const CapabilityFilter& filter); + bool ConnectToRunningApplication( + ApplicationInstance* originator, + const GURL& resolved_url, + const std::string& qualifier, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider>* services, + ServiceProviderPtr* exposed_services, + const CapabilityFilter& filter, + const Shell::ConnectToApplicationCallback& connect_callback); bool ConnectToApplicationWithLoader( ApplicationInstance* originator, @@ -185,6 +190,7 @@ class ApplicationManager { ServiceProviderPtr* exposed_services, const CapabilityFilter& filter, const base::Closure& on_application_end, + const Shell::ConnectToApplicationCallback& connect_callback, ApplicationLoader* loader); InterfaceRequest<Application> RegisterInstance( @@ -195,20 +201,24 @@ class ApplicationManager { InterfaceRequest<ServiceProvider> services, ServiceProviderPtr exposed_services, const CapabilityFilter& filter, - const base::Closure& on_application_end); + const base::Closure& on_application_end, + const Shell::ConnectToApplicationCallback& connect_callback, + ApplicationInstance** resulting_instance); // Called once |fetcher| has found app. |requested_url| is the url of the // requested application before any mappings/resolution have been applied. - void HandleFetchCallback(ApplicationInstance* originator, - const GURL& requested_url, - const std::string& qualifier, - const GURL& requestor_url, - InterfaceRequest<ServiceProvider> services, - ServiceProviderPtr exposed_services, - const CapabilityFilter& filter, - const base::Closure& on_application_end, - NativeApplicationCleanup cleanup, - scoped_ptr<Fetcher> fetcher); + void HandleFetchCallback( + ApplicationInstance* originator, + const GURL& requested_url, + const std::string& qualifier, + const GURL& requestor_url, + InterfaceRequest<ServiceProvider> services, + ServiceProviderPtr exposed_services, + const CapabilityFilter& filter, + const base::Closure& on_application_end, + const Shell::ConnectToApplicationCallback& connect_callback, + NativeApplicationCleanup cleanup, + scoped_ptr<Fetcher> fetcher); void RunNativeApplication(InterfaceRequest<Application> application_request, bool start_sandboxed, @@ -218,13 +228,16 @@ class ApplicationManager { const base::FilePath& file_path, bool path_exists); - void LoadWithContentHandler(ApplicationInstance* originator, - const GURL& content_handler_url, - const GURL& requestor_url, - const std::string& qualifier, - const CapabilityFilter& filter, - InterfaceRequest<Application> application_request, - URLResponsePtr url_response); + void LoadWithContentHandler( + ApplicationInstance* originator, + const GURL& content_handler_url, + const GURL& requestor_url, + const std::string& qualifier, + const CapabilityFilter& filter, + const Shell::ConnectToApplicationCallback& connect_callback, + ApplicationInstance* app, + InterfaceRequest<Application> application_request, + URLResponsePtr url_response); // Returns the appropriate loader for |url|, or null if there is no loader // configured for the URL. @@ -257,11 +270,15 @@ class ApplicationManager { MimeTypeToURLMap mime_type_to_url_; ScopedVector<NativeRunner> native_runners_; bool disable_cache_; + // Counter used to assign ids to content_handlers. + uint32_t content_handler_id_counter_; base::WeakPtrFactory<ApplicationManager> weak_ptr_factory_; DISALLOW_COPY_AND_ASSIGN(ApplicationManager); }; +Shell::ConnectToApplicationCallback EmptyConnectCallback(); + } // namespace shell } // namespace mojo diff --git a/mojo/shell/application_manager_unittest.cc b/mojo/shell/application_manager_unittest.cc index a5e9531..90f9edb 100644 --- a/mojo/shell/application_manager_unittest.cc +++ b/mojo/shell/application_manager_unittest.cc @@ -7,10 +7,12 @@ #include "base/macros.h" #include "base/memory/scoped_vector.h" #include "base/message_loop/message_loop.h" +#include "base/run_loop.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.h" +#include "mojo/application/public/interfaces/content_handler.mojom.h" #include "mojo/application/public/interfaces/service_provider.mojom.h" #include "mojo/public/cpp/bindings/strong_binding.h" #include "mojo/shell/application_loader.h" @@ -31,8 +33,10 @@ const char kTestMimeType[] = "test/mime-type"; class TestMimeTypeFetcher : public Fetcher { public: - explicit TestMimeTypeFetcher(const FetchCallback& fetch_callback) - : Fetcher(fetch_callback), url_("xxx") { + TestMimeTypeFetcher(const FetchCallback& fetch_callback, + const GURL& url, + const std::string& mime_type) + : Fetcher(fetch_callback), url_(url), mime_type_(mime_type) { loader_callback_.Run(make_scoped_ptr(this)); } ~TestMimeTypeFetcher() override {} @@ -48,12 +52,13 @@ class TestMimeTypeFetcher : public Fetcher { void AsPath( base::TaskRunner* task_runner, base::Callback<void(const base::FilePath&, bool)> callback) override {} - std::string MimeType() override { return kTestMimeType; } + std::string MimeType() override { return mime_type_; } bool HasMojoMagic() override { return false; } bool PeekFirstLine(std::string* line) override { return false; } private: const GURL url_; + const std::string mime_type_; DISALLOW_COPY_AND_ASSIGN(TestMimeTypeFetcher); }; @@ -118,11 +123,32 @@ class TestClient { DISALLOW_COPY_AND_ASSIGN(TestClient); }; +class TestContentHandler : public ContentHandler, public ApplicationDelegate { + public: + TestContentHandler(ApplicationConnection* connection, + InterfaceRequest<ContentHandler> request) + : binding_(this, request.Pass()) {} + + // ContentHandler: + void StartApplication(InterfaceRequest<Application> application_request, + URLResponsePtr response) override { + apps_.push_back(new ApplicationImpl(this, application_request.Pass())); + } + + private: + StrongBinding<ContentHandler> binding_; + ScopedVector<ApplicationImpl> apps_; + + DISALLOW_COPY_AND_ASSIGN(TestContentHandler); +}; + class TestApplicationLoader : public ApplicationLoader, public ApplicationDelegate, - public InterfaceFactory<TestService> { + public InterfaceFactory<TestService>, + public InterfaceFactory<ContentHandler> { public: - TestApplicationLoader() : context_(nullptr), num_loads_(0) {} + TestApplicationLoader() + : context_(nullptr), num_loads_(0), create_content_handler_(false) {} ~TestApplicationLoader() override { if (context_) @@ -130,6 +156,10 @@ class TestApplicationLoader : public ApplicationLoader, test_app_.reset(); } + void set_create_content_handler(bool value) { + create_content_handler_ = true; + } + void set_context(TestContext* context) { context_ = context; } int num_loads() const { return num_loads_; } const GURL& last_requestor_url() const { return last_requestor_url_; } @@ -144,21 +174,30 @@ class TestApplicationLoader : public ApplicationLoader, // ApplicationDelegate implementation. bool ConfigureIncomingConnection(ApplicationConnection* connection) override { - connection->AddService(this); + connection->AddService<TestService>(this); + if (create_content_handler_) + connection->AddService<ContentHandler>(this); last_requestor_url_ = GURL(connection->GetRemoteApplicationURL()); return true; } - // InterfaceFactory implementation. + // InterfaceFactory<TestService> implementation. void Create(ApplicationConnection* connection, InterfaceRequest<TestService> request) override { new TestServiceImpl(context_, request.Pass()); } + // InterfaceFactory<ContentHandler> implementation. + void Create(ApplicationConnection* connection, + InterfaceRequest<ContentHandler> request) override { + new TestContentHandler(connection, request.Pass()); + } + scoped_ptr<ApplicationImpl> test_app_; TestContext* context_; int num_loads_; GURL last_requestor_url_; + bool create_content_handler_; DISALLOW_COPY_AND_ASSIGN(TestApplicationLoader); }; @@ -418,7 +457,10 @@ class Tester : public ApplicationDelegate, class TestDelegate : public ApplicationManager::Delegate { public: - TestDelegate() : create_test_fetcher_(false) {} + TestDelegate() + : create_test_fetcher_(false), + fetcher_url_("xxx"), + mime_type_(kTestMimeType) {} ~TestDelegate() override {} void AddMapping(const GURL& from, const GURL& to) { mappings_[from] = to; } @@ -427,6 +469,10 @@ class TestDelegate : public ApplicationManager::Delegate { create_test_fetcher_ = create_test_fetcher; } + void set_fetcher_url(const GURL& url) { fetcher_url_ = url; } + + void set_mime_type(const std::string& mime_type) { mime_type_ = mime_type; } + // ApplicationManager::Delegate GURL ResolveMappings(const GURL& url) override { auto it = mappings_.find(url); @@ -448,13 +494,15 @@ class TestDelegate : public ApplicationManager::Delegate { const Fetcher::FetchCallback& loader_callback) override { if (!create_test_fetcher_) return false; - new TestMimeTypeFetcher(loader_callback); + new TestMimeTypeFetcher(loader_callback, fetcher_url_, mime_type_); return true; } private: std::map<GURL, GURL> mappings_; bool create_test_fetcher_; + GURL fetcher_url_; + std::string mime_type_; DISALLOW_COPY_AND_ASSIGN(TestDelegate); }; @@ -763,7 +811,8 @@ TEST_F(ApplicationManagerTest, TestEndApplicationClosure) { application_manager_->ConnectToApplication( nullptr, request.Pass(), std::string(), GURL(), nullptr, nullptr, GetPermissiveCapabilityFilter(), - base::Bind(&QuitClosure, base::Unretained(&called))); + base::Bind(&QuitClosure, base::Unretained(&called)), + EmptyConnectCallback()); loop_.Run(); EXPECT_TRUE(called); } @@ -791,7 +840,8 @@ TEST(ApplicationManagerTest2, ContentHandlerConnectionGetsRequestorURL) { application_manager.ConnectToApplication( nullptr, request.Pass(), std::string(), requestor_url, nullptr, nullptr, GetPermissiveCapabilityFilter(), - base::Bind(&QuitClosure, base::Unretained(&called))); + base::Bind(&QuitClosure, base::Unretained(&called)), + EmptyConnectCallback()); loop.Run(); EXPECT_TRUE(called); @@ -830,6 +880,143 @@ TEST_F(ApplicationManagerTest, SameIdentityShouldNotCauseDuplicateLoad) { EXPECT_EQ(4, test_loader_->num_loads()); } +TEST(ApplicationManagerTest2, + MultipleConnectionsToContentHandlerGetSameContentHandlerId) { + base::MessageLoop loop; + const GURL content_handler_url("http://test.content.handler"); + const GURL requestor_url("http://requestor.url"); + TestContext test_context; + TestDelegate test_delegate; + test_delegate.set_fetcher_url(GURL("test:test")); + test_delegate.set_create_test_fetcher(true); + ApplicationManager application_manager(&test_delegate); + application_manager.set_default_loader(nullptr); + application_manager.RegisterContentHandler(kTestMimeType, + content_handler_url); + + TestApplicationLoader* content_handler_loader = new TestApplicationLoader; + content_handler_loader->set_create_content_handler(true); + content_handler_loader->set_context(&test_context); + application_manager.SetLoaderForURL( + scoped_ptr<ApplicationLoader>(content_handler_loader), + content_handler_url); + + uint32_t content_handler_id; + { + base::RunLoop run_loop; + mojo::URLRequestPtr request(mojo::URLRequest::New()); + request->url = mojo::String::From("test:test"); + application_manager.ConnectToApplication( + nullptr, request.Pass(), std::string(), requestor_url, nullptr, nullptr, + GetPermissiveCapabilityFilter(), base::Closure(), + [&content_handler_id, &run_loop](uint32_t t) { + content_handler_id = t; + run_loop.Quit(); + }); + run_loop.Run(); + EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id); + } + + uint32_t content_handler_id2; + { + base::RunLoop run_loop; + mojo::URLRequestPtr request(mojo::URLRequest::New()); + request->url = mojo::String::From("test:test"); + application_manager.ConnectToApplication( + nullptr, request.Pass(), std::string(), requestor_url, nullptr, nullptr, + GetPermissiveCapabilityFilter(), base::Closure(), + [&content_handler_id2, &run_loop](uint32_t t) { + content_handler_id2 = t; + run_loop.Quit(); + }); + run_loop.Run(); + EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id2); + } + EXPECT_EQ(content_handler_id, content_handler_id2); +} + +TEST(ApplicationManagerTest2, DifferedContentHandlersGetDifferentIDs) { + base::MessageLoop loop; + const GURL content_handler_url("http://test.content.handler"); + const GURL requestor_url("http://requestor.url"); + TestContext test_context; + TestDelegate test_delegate; + test_delegate.set_fetcher_url(GURL("test:test")); + test_delegate.set_create_test_fetcher(true); + ApplicationManager application_manager(&test_delegate); + application_manager.set_default_loader(nullptr); + application_manager.RegisterContentHandler(kTestMimeType, + content_handler_url); + + TestApplicationLoader* content_handler_loader = new TestApplicationLoader; + content_handler_loader->set_create_content_handler(true); + content_handler_loader->set_context(&test_context); + application_manager.SetLoaderForURL( + scoped_ptr<ApplicationLoader>(content_handler_loader), + content_handler_url); + + uint32_t content_handler_id; + { + base::RunLoop run_loop; + mojo::URLRequestPtr request(mojo::URLRequest::New()); + request->url = mojo::String::From("test:test"); + application_manager.ConnectToApplication( + nullptr, request.Pass(), std::string(), requestor_url, nullptr, nullptr, + GetPermissiveCapabilityFilter(), base::Closure(), + [&content_handler_id, &run_loop](uint32_t t) { + content_handler_id = t; + run_loop.Quit(); + }); + run_loop.Run(); + EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id); + } + + const std::string mime_type2("test/mime-type2"); + const GURL content_handler_url2("http://test.content2.handler"); + test_delegate.set_fetcher_url(GURL("test2:test2")); + test_delegate.set_mime_type(mime_type2); + application_manager.RegisterContentHandler(mime_type2, content_handler_url2); + + TestApplicationLoader* content_handler_loader2 = new TestApplicationLoader; + content_handler_loader->set_create_content_handler(true); + content_handler_loader->set_context(&test_context); + application_manager.SetLoaderForURL( + scoped_ptr<ApplicationLoader>(content_handler_loader2), + content_handler_url2); + + uint32_t content_handler_id2; + { + base::RunLoop run_loop; + mojo::URLRequestPtr request(mojo::URLRequest::New()); + request->url = mojo::String::From("test2:test2"); + application_manager.ConnectToApplication( + nullptr, request.Pass(), std::string(), requestor_url, nullptr, nullptr, + GetPermissiveCapabilityFilter(), base::Closure(), + [&content_handler_id2, &run_loop](uint32_t t) { + content_handler_id2 = t; + run_loop.Quit(); + }); + run_loop.Run(); + EXPECT_NE(Shell::kInvalidContentHandlerID, content_handler_id2); + } + EXPECT_NE(content_handler_id, content_handler_id2); +} + +TEST_F(ApplicationManagerTest, + ConnectWithNoContentHandlerGetsInvalidContentHandlerId) { + application_manager_->SetLoaderForScheme( + scoped_ptr<ApplicationLoader>(new TestApplicationLoader), "test"); + + uint32_t content_handler_id = 1u; + mojo::URLRequestPtr request(mojo::URLRequest::New()); + request->url = mojo::String::From("test:test"); + application_manager_->ConnectToApplication( + nullptr, request.Pass(), std::string(), GURL(), nullptr, nullptr, + GetPermissiveCapabilityFilter(), base::Closure(), + [&content_handler_id](uint32_t t) { content_handler_id = t; }); + EXPECT_EQ(0u, content_handler_id); +} + } // namespace } // namespace shell } // namespace mojo diff --git a/mojo/shell/capability_filter_unittest.cc b/mojo/shell/capability_filter_unittest.cc index fda2c31..3449e18 100644 --- a/mojo/shell/capability_filter_unittest.cc +++ b/mojo/shell/capability_filter_unittest.cc @@ -352,7 +352,7 @@ class CapabilityFilterTest : public testing::Test { application_manager_->ConnectToApplication( nullptr, request.Pass(), std::string(), GURL(), GetProxy(&services), exposed_services.Pass(), filter, - base::MessageLoop::QuitWhenIdleClosure()); + base::MessageLoop::QuitWhenIdleClosure(), EmptyConnectCallback()); } void InitValidator(const std::set<std::string>& expectations) { diff --git a/mojo/shell/content_handler_connection.cc b/mojo/shell/content_handler_connection.cc index dd3c5cb..cf733f6 100644 --- a/mojo/shell/content_handler_connection.cc +++ b/mojo/shell/content_handler_connection.cc @@ -15,17 +15,19 @@ ContentHandlerConnection::ContentHandlerConnection( const GURL& content_handler_url, const GURL& requestor_url, const std::string& qualifier, - const CapabilityFilter& filter) + const CapabilityFilter& filter, + uint32_t id) : manager_(manager), content_handler_url_(content_handler_url), content_handler_qualifier_(qualifier), - connection_closed_(false) { + connection_closed_(false), + id_(id) { ServiceProviderPtr services; mojo::URLRequestPtr request(mojo::URLRequest::New()); request->url = mojo::String::From(content_handler_url.spec()); manager->ConnectToApplication( originator, request.Pass(), qualifier, requestor_url, GetProxy(&services), - nullptr, filter, base::Closure()); + nullptr, filter, base::Closure(), EmptyConnectCallback()); MessagePipe pipe; content_handler_.Bind( InterfacePtrInfo<ContentHandler>(pipe.handle0.Pass(), 0u)); diff --git a/mojo/shell/content_handler_connection.h b/mojo/shell/content_handler_connection.h index 1995265..d93dbee 100644 --- a/mojo/shell/content_handler_connection.h +++ b/mojo/shell/content_handler_connection.h @@ -25,12 +25,14 @@ class ApplicationManager; // destruction. class ContentHandlerConnection { public: + // |id| is a unique identifier for this content handler. ContentHandlerConnection(ApplicationInstance* originator, ApplicationManager* manager, const GURL& content_handler_url, const GURL& requestor_url, const std::string& qualifier, - const CapabilityFilter& filter); + const CapabilityFilter& filter, + uint32_t id); // Closes the connection and destroys |this| object. void CloseConnection(); @@ -40,6 +42,7 @@ class ContentHandlerConnection { const std::string& content_handler_qualifier() { return content_handler_qualifier_; } + uint32_t id() const { return id_; } private: ~ContentHandlerConnection(); @@ -49,6 +52,8 @@ class ContentHandlerConnection { std::string content_handler_qualifier_; ContentHandlerPtr content_handler_; bool connection_closed_; + // The id for this content handler. + const uint32_t id_; DISALLOW_COPY_AND_ASSIGN(ContentHandlerConnection); }; |