diff options
-rw-r--r-- | mojo/application_manager/application_loader.cc | 2 | ||||
-rw-r--r-- | mojo/application_manager/application_loader.h | 2 | ||||
-rw-r--r-- | mojo/application_manager/application_manager.cc | 11 | ||||
-rw-r--r-- | mojo/application_manager/application_manager.h | 2 | ||||
-rw-r--r-- | mojo/examples/content_handler_demo/content_handler_demo.cc | 14 | ||||
-rw-r--r-- | mojo/services/public/interfaces/content_handler/content_handler.mojom | 6 | ||||
-rw-r--r-- | mojo/shell/dynamic_application_loader.cc | 304 | ||||
-rw-r--r-- | mojo/shell/dynamic_application_loader.h | 24 |
8 files changed, 218 insertions, 147 deletions
diff --git a/mojo/application_manager/application_loader.cc b/mojo/application_manager/application_loader.cc index 0c78c32..60dec669 100644 --- a/mojo/application_manager/application_loader.cc +++ b/mojo/application_manager/application_loader.cc @@ -23,7 +23,7 @@ ApplicationLoader::SimpleLoadCallbacks::RegisterApplication() { void ApplicationLoader::SimpleLoadCallbacks::LoadWithContentHandler( const GURL& content_handle_url, - URLResponsePtr content) { + URLResponsePtr url_response) { NOTREACHED(); } diff --git a/mojo/application_manager/application_loader.h b/mojo/application_manager/application_loader.h index 5e89a06..d0e6fee 100644 --- a/mojo/application_manager/application_loader.h +++ b/mojo/application_manager/application_loader.h @@ -34,7 +34,7 @@ class MOJO_APPLICATION_MANAGER_EXPORT ApplicationLoader { // Load the requested application with a content handler. virtual void LoadWithContentHandler(const GURL& content_handler_url, - URLResponsePtr response) = 0; + URLResponsePtr url_response) = 0; protected: friend base::RefCounted<LoadCallbacks>; diff --git a/mojo/application_manager/application_manager.cc b/mojo/application_manager/application_manager.cc index 3281681..b0a300e 100644 --- a/mojo/application_manager/application_manager.cc +++ b/mojo/application_manager/application_manager.cc @@ -66,12 +66,12 @@ class ApplicationManager::LoadCallbacksImpl } virtual void LoadWithContentHandler(const GURL& content_handler_url, - URLResponsePtr content) OVERRIDE { + URLResponsePtr url_response) OVERRIDE { if (manager_) { manager_->LoadWithContentHandler(requested_url_, requestor_url_, content_handler_url, - content.Pass(), + url_response.Pass(), service_provider_.Pass()); } } @@ -232,7 +232,7 @@ void ApplicationManager::LoadWithContentHandler( const GURL& content_url, const GURL& requestor_url, const GURL& content_handler_url, - URLResponsePtr content, + URLResponsePtr url_response, ServiceProviderPtr service_provider) { ContentHandlerConnection* connection = NULL; URLToContentHandlerMap::iterator iter = @@ -243,8 +243,11 @@ void ApplicationManager::LoadWithContentHandler( connection = new ContentHandlerConnection(this, content_handler_url); url_to_content_handler_[content_handler_url] = connection; } + + InterfaceRequest<ServiceProvider> spir; + spir.Bind(service_provider.PassMessagePipe()); connection->content_handler->OnConnect( - content_url.spec(), content.Pass(), service_provider.Pass()); + content_url.spec(), url_response.Pass(), spir.Pass()); } void ApplicationManager::SetLoaderForURL(scoped_ptr<ApplicationLoader> loader, diff --git a/mojo/application_manager/application_manager.h b/mojo/application_manager/application_manager.h index 66a6c08..bb988a0 100644 --- a/mojo/application_manager/application_manager.h +++ b/mojo/application_manager/application_manager.h @@ -123,7 +123,7 @@ class MOJO_APPLICATION_MANAGER_EXPORT ApplicationManager { void LoadWithContentHandler(const GURL& content_url, const GURL& requestor_url, const GURL& content_handler_url, - URLResponsePtr content, + URLResponsePtr url_response, ServiceProviderPtr service_provider); // Returns the Loader to use for a url (using default if not overridden.) diff --git a/mojo/examples/content_handler_demo/content_handler_demo.cc b/mojo/examples/content_handler_demo/content_handler_demo.cc index 21864f7..bddcb22 100644 --- a/mojo/examples/content_handler_demo/content_handler_demo.cc +++ b/mojo/examples/content_handler_demo/content_handler_demo.cc @@ -23,8 +23,9 @@ class ContentHandlerImpl : public InterfaceImpl<ContentHandler> { private: virtual void OnConnect(const mojo::String& url, - URLResponsePtr content, - ServiceProviderPtr service_provider) MOJO_OVERRIDE; + URLResponsePtr response, + InterfaceRequest<ServiceProvider> service_provider) + MOJO_OVERRIDE; ContentHandlerApp* content_handler_app_; }; @@ -71,12 +72,13 @@ class ContentHandlerApp : public ApplicationDelegate { ContentHandlerApp> content_handler_factory_; }; -void ContentHandlerImpl::OnConnect(const mojo::String& url, - URLResponsePtr content, - ServiceProviderPtr service_provider) { +void ContentHandlerImpl::OnConnect( + const mojo::String& url, + URLResponsePtr response, + InterfaceRequest<ServiceProvider> service_provider) { printf("ContentHandler::OnConnect - url:%s - body follows\n\n", url.To<std::string>().c_str()); - content_handler_app_->PrintResponse(content->body.Pass()); + content_handler_app_->PrintResponse(response->body.Pass()); } } // namespace examples diff --git a/mojo/services/public/interfaces/content_handler/content_handler.mojom b/mojo/services/public/interfaces/content_handler/content_handler.mojom index 1a0ce07..4383401 100644 --- a/mojo/services/public/interfaces/content_handler/content_handler.mojom +++ b/mojo/services/public/interfaces/content_handler/content_handler.mojom @@ -8,9 +8,9 @@ import "mojo/services/public/interfaces/network/url_loader.mojom" module mojo { interface ContentHandler { - OnConnect(string? url, - URLResponse? url_response, - ServiceProvider? service_provider); + OnConnect(string url, + URLResponse response, + ServiceProvider&? service_provider); }; } diff --git a/mojo/shell/dynamic_application_loader.cc b/mojo/shell/dynamic_application_loader.cc index 718ece4..a5fa0e7 100644 --- a/mojo/shell/dynamic_application_loader.cc +++ b/mojo/shell/dynamic_application_loader.cc @@ -9,6 +9,7 @@ #include "base/file_util.h" #include "base/files/file_path.h" #include "base/memory/scoped_ptr.h" +#include "base/memory/weak_ptr.h" #include "base/message_loop/message_loop.h" #include "mojo/common/common_type_converters.h" #include "mojo/common/data_pipe_utils.h" @@ -20,12 +21,175 @@ namespace mojo { namespace shell { +// Encapsulates loading and running one individual application. +// +// Loaders are owned by DynamicApplicationLoader. DynamicApplicationLoader must +// ensure that all the parameters passed to Loader subclasses stay valid through +// Loader's lifetime. +// +// Async operations are done with WeakPtr to protect against +// DynamicApplicationLoader going away (and taking all the Loaders with it) +// while the async operation is outstanding. +class DynamicApplicationLoader::Loader { + public: + Loader(Context* context, + DynamicServiceRunnerFactory* runner_factory, + scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, + const LoaderCompleteCallback& loader_complete_callback) + : load_callbacks_(load_callbacks), + loader_complete_callback_(loader_complete_callback), + context_(context), + runner_factory_(runner_factory), + weak_ptr_factory_(this) {} + + virtual ~Loader() {} + + protected: + void RunLibrary(const base::FilePath& path, bool path_exists) { + ScopedMessagePipeHandle shell_handle = + load_callbacks_->RegisterApplication(); + if (!shell_handle.is_valid()) { + LoaderComplete(); + return; + } + + if (!path_exists) { + DVLOG(1) << "Library not started because library path '" << path.value() + << "' does not exist."; + LoaderComplete(); + return; + } + + runner_ = runner_factory_->Create(context_); + runner_->Start( + path, + shell_handle.Pass(), + base::Bind(&Loader::LoaderComplete, weak_ptr_factory_.GetWeakPtr())); + } + + void LoaderComplete() { loader_complete_callback_.Run(this); } + + scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks_; + LoaderCompleteCallback loader_complete_callback_; + Context* context_; + + private: + DynamicServiceRunnerFactory* runner_factory_; + scoped_ptr<DynamicServiceRunner> runner_; + base::WeakPtrFactory<Loader> weak_ptr_factory_; +}; + +// A loader for local files. +class DynamicApplicationLoader::LocalLoader : public Loader { + public: + LocalLoader(const GURL& url, + Context* context, + DynamicServiceRunnerFactory* runner_factory, + scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, + const LoaderCompleteCallback& loader_complete_callback) + : Loader(context, + runner_factory, + load_callbacks, + loader_complete_callback), + weak_ptr_factory_(this) { + base::FilePath path; + net::FileURLToFilePath(url, &path); + + // Async for consistency with network case. + base::MessageLoop::current()->PostTask( + FROM_HERE, + base::Bind(&LocalLoader::RunLibrary, + weak_ptr_factory_.GetWeakPtr(), + path, + base::PathExists(path))); + } + + virtual ~LocalLoader() {} + + private: + base::WeakPtrFactory<LocalLoader> weak_ptr_factory_; +}; + +// A loader for network files. +class DynamicApplicationLoader::NetworkLoader : public Loader { + public: + NetworkLoader(const GURL& url, + MimeTypeToURLMap* mime_type_to_url, + Context* context, + DynamicServiceRunnerFactory* runner_factory, + NetworkService* network_service, + scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, + const LoaderCompleteCallback& loader_complete_callback) + : Loader(context, + runner_factory, + load_callbacks, + loader_complete_callback), + mime_type_to_url_(mime_type_to_url), + weak_ptr_factory_(this) { + URLRequestPtr request(URLRequest::New()); + request->url = String::From(url); + request->auto_follow_redirects = true; + + if (base::CommandLine::ForCurrentProcess()->HasSwitch( + switches::kDisableCache)) { + request->bypass_cache = true; + } + + network_service->CreateURLLoader(Get(&url_loader_)); + url_loader_->Start(request.Pass(), + base::Bind(&NetworkLoader::OnLoadComplete, + weak_ptr_factory_.GetWeakPtr())); + } + + virtual ~NetworkLoader() { + if (!file_.empty()) + base::DeleteFile(file_, false); + } + + private: + void OnLoadComplete(URLResponsePtr response) { + if (response->error) { + LOG(ERROR) << "Error (" << response->error->code << ": " + << response->error->description << ") while fetching " + << response->url; + LoaderComplete(); + return; + } + + MimeTypeToURLMap::iterator iter = + mime_type_to_url_->find(response->mime_type); + if (iter != mime_type_to_url_->end()) { + load_callbacks_->LoadWithContentHandler(iter->second, response.Pass()); + LoaderComplete(); + return; + } + + base::CreateTemporaryFile(&file_); + common::CopyToFile( + response->body.Pass(), + file_, + context_->task_runners()->blocking_pool(), + base::Bind( + &NetworkLoader::RunLibrary, weak_ptr_factory_.GetWeakPtr(), file_)); + } + + MimeTypeToURLMap* mime_type_to_url_; + URLLoaderPtr url_loader_; + base::FilePath file_; + base::WeakPtrFactory<NetworkLoader> weak_ptr_factory_; +}; + DynamicApplicationLoader::DynamicApplicationLoader( Context* context, scoped_ptr<DynamicServiceRunnerFactory> runner_factory) : context_(context), runner_factory_(runner_factory.Pass()), - weak_ptr_factory_(this) { + + // Unretained() is correct here because DynamicApplicationLoader owns the + // loaders that we pass this callback to. + loader_complete_callback_( + base::Bind(&DynamicApplicationLoader::LoaderComplete, + base::Unretained(this))) { } DynamicApplicationLoader::~DynamicApplicationLoader() { @@ -37,9 +201,10 @@ void DynamicApplicationLoader::RegisterContentHandler( mime_type_to_url_[mime_type] = content_handler_url; } -void DynamicApplicationLoader::Load(ApplicationManager* manager, - const GURL& url, - scoped_refptr<LoadCallbacks> callbacks) { +void DynamicApplicationLoader::Load( + ApplicationManager* manager, + const GURL& url, + scoped_refptr<LoadCallbacks> load_callbacks) { GURL resolved_url; if (url.SchemeIs("mojo")) { resolved_url = context_->mojo_url_resolver()->Resolve(url); @@ -47,124 +212,27 @@ void DynamicApplicationLoader::Load(ApplicationManager* manager, resolved_url = url; } - if (resolved_url.SchemeIsFile()) - LoadLocalService(resolved_url, callbacks); - else - LoadNetworkService(resolved_url, callbacks); -} - -void DynamicApplicationLoader::LoadLocalService( - const GURL& resolved_url, - scoped_refptr<LoadCallbacks> callbacks) { - base::FilePath path; - net::FileURLToFilePath(resolved_url, &path); - const bool kDeleteFileAfter = false; - - // Async for consistency with network case. - base::MessageLoop::current()->PostTask( - FROM_HERE, - base::Bind(&DynamicApplicationLoader::RunLibrary, - weak_ptr_factory_.GetWeakPtr(), - path, - callbacks, - kDeleteFileAfter, - base::PathExists(path))); -} + if (resolved_url.SchemeIsFile()) { + loaders_.push_back(new LocalLoader(resolved_url, + context_, + runner_factory_.get(), + load_callbacks, + loader_complete_callback_)); + return; + } -void DynamicApplicationLoader::LoadNetworkService( - const GURL& resolved_url, - scoped_refptr<LoadCallbacks> callbacks) { if (!network_service_) { context_->application_manager()->ConnectToService( GURL("mojo:mojo_network_service"), &network_service_); } - if (!url_loader_) - network_service_->CreateURLLoader(Get(&url_loader_)); - - URLRequestPtr request(URLRequest::New()); - request->url = String::From(resolved_url); - request->auto_follow_redirects = true; - - if (base::CommandLine::ForCurrentProcess()->HasSwitch( - switches::kDisableCache)) { - request->bypass_cache = true; - } - - url_loader_->Start( - request.Pass(), - base::Bind(&DynamicApplicationLoader::OnLoadNetworkServiceComplete, - weak_ptr_factory_.GetWeakPtr(), - callbacks)); -} - -void DynamicApplicationLoader::OnLoadNetworkServiceComplete( - scoped_refptr<LoadCallbacks> callbacks, - URLResponsePtr response) { - if (response->error) { - LOG(ERROR) << "Error (" << response->error->code << ": " - << response->error->description << ") while fetching " - << response->url; - } - - MimeTypeToURLMap::iterator iter = mime_type_to_url_.find(response->mime_type); - if (iter != mime_type_to_url_.end()) { - callbacks->LoadWithContentHandler(iter->second, response.Pass()); - return; - } - - base::FilePath file; - base::CreateTemporaryFile(&file); - - const bool kDeleteFileAfter = true; - common::CopyToFile(response->body.Pass(), - file, - context_->task_runners()->blocking_pool(), - base::Bind(&DynamicApplicationLoader::RunLibrary, - weak_ptr_factory_.GetWeakPtr(), - file, - callbacks, - kDeleteFileAfter)); -} - -void DynamicApplicationLoader::RunLibrary( - const base::FilePath& path, - scoped_refptr<LoadCallbacks> callbacks, - bool delete_file_after, - bool path_exists) { - - ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication(); - if (!shell_handle.is_valid()) - return; - - if (!path_exists) { - DVLOG(1) << "Library not started because library path '" - << path.value() << "' does not exist."; - return; - } - scoped_ptr<DynamicServiceRunner> runner = - runner_factory_->Create(context_).Pass(); - runner->Start(path, - shell_handle.Pass(), - base::Bind(&DynamicApplicationLoader::OnRunLibraryComplete, - weak_ptr_factory_.GetWeakPtr(), - base::Unretained(runner.get()), - delete_file_after ? path : base::FilePath())); - runners_.push_back(runner.release()); -} - -void DynamicApplicationLoader::OnRunLibraryComplete( - DynamicServiceRunner* runner, - const base::FilePath& temp_file) { - for (ScopedVector<DynamicServiceRunner>::iterator it = runners_.begin(); - it != runners_.end(); ++it) { - if (*it == runner) { - runners_.erase(it); - if (!temp_file.empty()) - base::DeleteFile(temp_file, false); - return; - } - } + loaders_.push_back(new NetworkLoader(resolved_url, + &mime_type_to_url_, + context_, + runner_factory_.get(), + network_service_.get(), + load_callbacks, + loader_complete_callback_)); } void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager, @@ -173,5 +241,9 @@ void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager, // the app closed its handle to the service manager. Maybe we don't care? } +void DynamicApplicationLoader::LoaderComplete(Loader* loader) { + loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); +} + } // namespace shell } // namespace mojo diff --git a/mojo/shell/dynamic_application_loader.h b/mojo/shell/dynamic_application_loader.h index 36546e9..77867a6 100644 --- a/mojo/shell/dynamic_application_loader.h +++ b/mojo/shell/dynamic_application_loader.h @@ -7,6 +7,7 @@ #include <map> +#include "base/callback.h" #include "base/macros.h" #include "base/memory/scoped_vector.h" #include "base/memory/weak_ptr.h" @@ -44,28 +45,21 @@ class DynamicApplicationLoader : public ApplicationLoader { const GURL& url) OVERRIDE; private: + class Loader; + class LocalLoader; + class NetworkLoader; + typedef std::map<std::string, GURL> MimeTypeToURLMap; + typedef base::Callback<void(Loader*)> LoaderCompleteCallback; - void LoadLocalService(const GURL& resolved_url, - scoped_refptr<LoadCallbacks> callbacks); - void LoadNetworkService(const GURL& resolved_url, - scoped_refptr<LoadCallbacks> callbacks); - void OnLoadNetworkServiceComplete(scoped_refptr<LoadCallbacks> callbacks, - URLResponsePtr url_response); - void RunLibrary(const base::FilePath& response_file, - scoped_refptr<LoadCallbacks> callbacks, - bool delete_file_after, - bool response_path_exists); - void OnRunLibraryComplete(DynamicServiceRunner* runner, - const base::FilePath& temp_file); + void LoaderComplete(Loader* loader); Context* const context_; scoped_ptr<DynamicServiceRunnerFactory> runner_factory_; - ScopedVector<DynamicServiceRunner> runners_; NetworkServicePtr network_service_; - URLLoaderPtr url_loader_; MimeTypeToURLMap mime_type_to_url_; - base::WeakPtrFactory<DynamicApplicationLoader> weak_ptr_factory_; + ScopedVector<Loader> loaders_; + LoaderCompleteCallback loader_complete_callback_; DISALLOW_COPY_AND_ASSIGN(DynamicApplicationLoader); }; |