Index: mojo/shell/dynamic_service_loader.cc |
diff --git a/mojo/shell/dynamic_service_loader.cc b/mojo/shell/dynamic_service_loader.cc |
index a8e6914ae9e5a8bb3cd18ffa4e22dc51fd75b58d..73dd6dd47ef124dba99e7a33a1d3bcdfa621ad11 100644 |
--- a/mojo/shell/dynamic_service_loader.cc |
+++ b/mojo/shell/dynamic_service_loader.cc |
@@ -20,122 +20,15 @@ |
namespace mojo { |
namespace shell { |
-namespace { |
- |
-class Loader { |
- public: |
- explicit Loader(scoped_ptr<DynamicServiceRunner> runner) |
- : runner_(runner.Pass()) { |
- } |
- |
- virtual void Start(const GURL& url, |
- ScopedMessagePipeHandle service_handle, |
- Context* context) = 0; |
- |
- void StartService(const base::FilePath& path, |
- ScopedMessagePipeHandle service_handle, |
- bool path_is_valid) { |
- if (path_is_valid) { |
- runner_->Start(path, service_handle.Pass(), |
- base::Bind(&Loader::AppCompleted, base::Unretained(this))); |
- } else { |
- AppCompleted(); |
- } |
- } |
- |
- protected: |
- virtual ~Loader() {} |
- |
- private: |
- void AppCompleted() { |
- delete this; |
- } |
- |
- scoped_ptr<DynamicServiceRunner> runner_; |
-}; |
- |
-// For loading services via file:// URLs. |
-class LocalLoader : public Loader { |
- public: |
- explicit LocalLoader(scoped_ptr<DynamicServiceRunner> runner) |
- : Loader(runner.Pass()) { |
- } |
- |
- virtual void Start(const GURL& url, |
- ScopedMessagePipeHandle service_handle, |
- Context* context) OVERRIDE { |
- base::FilePath path; |
- net::FileURLToFilePath(url, &path); |
- |
- // Complete asynchronously for consistency with NetworkServiceLoader. |
- base::MessageLoop::current()->PostTask( |
- FROM_HERE, |
- base::Bind(&Loader::StartService, |
- base::Unretained(this), |
- path, |
- base::Passed(&service_handle), |
- base::PathExists(path))); |
- } |
-}; |
- |
-// For loading services via the network stack. |
-class NetworkLoader : public Loader { |
- public: |
- explicit NetworkLoader(scoped_ptr<DynamicServiceRunner> runner, |
- NetworkService* network_service) |
- : Loader(runner.Pass()) { |
- network_service->CreateURLLoader(Get(&url_loader_)); |
- } |
- |
- virtual void Start(const GURL& url, |
- ScopedMessagePipeHandle service_handle, |
- Context* context) OVERRIDE { |
- service_handle_ = service_handle.Pass(); |
- context_ = context; |
- |
- 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; |
- } |
- |
- url_loader_->Start(request.Pass(), |
- base::Bind(&NetworkLoader::OnReceivedResponse, |
- base::Unretained(this))); |
- } |
- |
- private: |
- virtual ~NetworkLoader() { |
- if (!file_.empty()) |
- base::DeleteFile(file_, false); |
- } |
- void OnReceivedResponse(URLResponsePtr response) { |
- if (response->error) { |
- LOG(ERROR) << "Error (" << response->error->code << ": " |
- << response->error->description << ") while fetching " |
- << response->url; |
- } |
- |
- base::CreateTemporaryFile(&file_); |
- common::CopyToFile(response->body.Pass(), |
- file_, |
- context_->task_runners()->blocking_pool(), |
- base::Bind(&Loader::StartService, |
- base::Unretained(this), |
- file_, |
- base::Passed(&service_handle_))); |
- } |
+namespace { |
- Context* context_; |
- NetworkServicePtr network_service_; |
- URLLoaderPtr url_loader_; |
- ScopedMessagePipeHandle service_handle_; |
- base::FilePath file_; |
-}; |
+void RunLibraryComplete(DynamicServiceRunner* runner, |
+ const base::FilePath& temp_file) { |
+ delete runner; |
+ if (!temp_file.empty()) |
+ base::DeleteFile(temp_file, false); |
+} |
} // namespace |
@@ -143,17 +36,22 @@ DynamicServiceLoader::DynamicServiceLoader( |
Context* context, |
scoped_ptr<DynamicServiceRunnerFactory> runner_factory) |
: context_(context), |
- runner_factory_(runner_factory.Pass()) { |
+ runner_factory_(runner_factory.Pass()), |
+ weak_ptr_factory_(this) { |
} |
DynamicServiceLoader::~DynamicServiceLoader() { |
} |
-void DynamicServiceLoader::LoadService(ServiceManager* manager, |
- const GURL& url, |
- ScopedMessagePipeHandle shell_handle) { |
- scoped_ptr<DynamicServiceRunner> runner = runner_factory_->Create(context_); |
+void DynamicServiceLoader::RegisterContentHandler( |
+ const std::string& mime_type, |
+ const GURL& content_handler_url) { |
+ mime_type_to_url_[mime_type] = content_handler_url; |
+} |
+void DynamicServiceLoader::Load(ServiceManager* manager, |
+ const GURL& url, |
+ scoped_refptr<LoadCallbacks> callbacks) { |
GURL resolved_url; |
if (url.SchemeIs("mojo")) { |
resolved_url = context_->mojo_url_resolver()->Resolve(url); |
@@ -161,18 +59,109 @@ void DynamicServiceLoader::LoadService(ServiceManager* manager, |
resolved_url = url; |
} |
- Loader* loader; |
- if (resolved_url.SchemeIsFile()) { |
- loader = new LocalLoader(runner.Pass()); |
- } else { |
- if (!network_service_) { |
- context_->service_manager()->ConnectToService( |
- GURL("mojo:mojo_network_service"), |
- &network_service_); |
- } |
- loader = new NetworkLoader(runner.Pass(), network_service_.get()); |
+ if (resolved_url.SchemeIsFile()) |
+ LoadLocalService(resolved_url, callbacks); |
+ else |
+ LoadNetworkService(resolved_url, callbacks); |
+} |
+ |
+void DynamicServiceLoader::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(&DynamicServiceLoader::RunLibrary, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ path, |
+ callbacks, |
+ kDeleteFileAfter, |
+ base::PathExists(path))); |
+} |
+ |
+void DynamicServiceLoader::LoadNetworkService( |
+ const GURL& resolved_url, |
+ scoped_refptr<LoadCallbacks> callbacks) { |
+ if (!network_service_) { |
+ context_->service_manager()->ConnectToService( |
+ GURL("mojo:mojo_network_service"), |
+ &network_service_); |
} |
- loader->Start(resolved_url, shell_handle.Pass(), context_); |
+ 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(&DynamicServiceLoader::OnLoadNetworkServiceComplete, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ callbacks)); |
+} |
+ |
+void DynamicServiceLoader::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(&DynamicServiceLoader::RunLibrary, |
+ weak_ptr_factory_.GetWeakPtr(), |
+ file, |
+ callbacks, |
+ kDeleteFileAfter)); |
+} |
+ |
+void DynamicServiceLoader::RunLibrary(const base::FilePath& path, |
+ scoped_refptr<LoadCallbacks> callbacks, |
+ bool delete_file_after, |
+ bool path_exists) { |
+ // TODO(aa): We need to create a runner, even if we're not going to use it, |
+ // because it getting destroyed is what causes shell to shut down. If we don't |
+ // create this, in the case where shell never successfully creates even one |
+ // app, then shell will never shut down, because no runners are ever |
+ // destroyed. |
+ scoped_ptr<DynamicServiceRunner> runner(runner_factory_->Create(context_)); |
+ if (!path_exists) |
+ return; |
+ |
+ ScopedMessagePipeHandle shell_handle = callbacks->RegisterApplication(); |
+ if (!shell_handle.is_valid()) |
+ return; |
+ |
+ DynamicServiceRunner* runner_raw = runner.release(); |
+ runner_raw->Start(path, |
+ shell_handle.Pass(), |
+ base::Bind(&RunLibraryComplete, |
+ base::Unretained(runner_raw), |
+ delete_file_after ? path : base::FilePath())); |
} |
void DynamicServiceLoader::OnServiceError(ServiceManager* manager, |