summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorsky <sky@chromium.org>2015-08-31 17:58:50 -0700
committerCommit bot <commit-bot@chromium.org>2015-09-01 00:59:26 +0000
commit6e094e866fc853c369d2cf27fc947bd0708c6840 (patch)
tree242a733e7122b71e4ea686a4e045a2c91ae6ee20
parent2b15299836d8c046ac3315e87ce3cd5f3af9ce50 (diff)
downloadchromium_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}
-rw-r--r--components/font_service/public/cpp/font_loader.cc11
-rw-r--r--components/html_viewer/media_factory.cc5
-rw-r--r--components/pdf_viewer/pdf_viewer.cc4
-rw-r--r--components/resource_provider/public/cpp/resource_loader.cc7
-rw-r--r--content/browser/frame_host/frame_mojo_shell.cc5
-rw-r--r--content/browser/frame_host/frame_mojo_shell.h3
-rw-r--r--content/browser/mojo/mojo_app_connection_impl.cc8
-rw-r--r--content/browser/mojo/mojo_shell_context.cc19
-rw-r--r--content/browser/mojo/mojo_shell_context.h7
-rw-r--r--content/renderer/render_frame_impl.cc5
-rw-r--r--mandoline/ui/aura/surface_binding.cc10
-rw-r--r--mojo/application/public/cpp/application_connection.h11
-rw-r--r--mojo/application/public/cpp/lib/application_impl.cc9
-rw-r--r--mojo/application/public/cpp/lib/service_registry.cc35
-rw-r--r--mojo/application/public/cpp/lib/service_registry.h14
-rw-r--r--mojo/application/public/interfaces/shell.mojom11
-rw-r--r--mojo/runner/about_fetcher_unittest.cc2
-rw-r--r--mojo/runner/context.cc15
-rw-r--r--mojo/runner/native_runner_unittest.cc2
-rw-r--r--mojo/runner/shell_test_base.cc2
-rw-r--r--mojo/shell/application_instance.cc40
-rw-r--r--mojo/shell/application_instance.h25
-rw-r--r--mojo/shell/application_manager.cc87
-rw-r--r--mojo/shell/application_manager.h83
-rw-r--r--mojo/shell/application_manager_unittest.cc209
-rw-r--r--mojo/shell/capability_filter_unittest.cc2
-rw-r--r--mojo/shell/content_handler_connection.cc8
-rw-r--r--mojo/shell/content_handler_connection.h7
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);
};