Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2014 The Chromium Authors. All rights reserved. | 1 // Copyright 2014 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "mojo/shell/dynamic_application_loader.h" | 5 #include "mojo/shell/dynamic_application_loader.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/command_line.h" | 8 #include "base/command_line.h" |
| 9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/files/file_util.h" | 10 #include "base/files/file_util.h" |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 46 // Loader's lifetime. | 46 // Loader's lifetime. |
| 47 // | 47 // |
| 48 // Async operations are done with WeakPtr to protect against | 48 // Async operations are done with WeakPtr to protect against |
| 49 // DynamicApplicationLoader going away (and taking all the Loaders with it) | 49 // DynamicApplicationLoader going away (and taking all the Loaders with it) |
| 50 // while the async operation is outstanding. | 50 // while the async operation is outstanding. |
| 51 class DynamicApplicationLoader::Loader { | 51 class DynamicApplicationLoader::Loader { |
| 52 public: | 52 public: |
| 53 Loader(MimeTypeToURLMap* mime_type_to_url, | 53 Loader(MimeTypeToURLMap* mime_type_to_url, |
| 54 Context* context, | 54 Context* context, |
| 55 DynamicServiceRunnerFactory* runner_factory, | 55 DynamicServiceRunnerFactory* runner_factory, |
| 56 ScopedMessagePipeHandle shell_handle, | |
| 56 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | 57 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, |
| 57 const LoaderCompleteCallback& loader_complete_callback) | 58 const LoaderCompleteCallback& loader_complete_callback) |
| 58 : load_callbacks_(load_callbacks), | 59 : shell_handle_(shell_handle.Pass()), |
| 60 load_callbacks_(load_callbacks), | |
| 59 loader_complete_callback_(loader_complete_callback), | 61 loader_complete_callback_(loader_complete_callback), |
| 60 context_(context), | 62 context_(context), |
| 61 mime_type_to_url_(mime_type_to_url), | 63 mime_type_to_url_(mime_type_to_url), |
| 62 runner_factory_(runner_factory), | 64 runner_factory_(runner_factory), |
| 63 weak_ptr_factory_(this) {} | 65 weak_ptr_factory_(this) {} |
| 64 | 66 |
| 65 virtual ~Loader() {} | 67 virtual ~Loader() {} |
| 66 | 68 |
| 67 protected: | 69 protected: |
| 68 virtual URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, | 70 virtual URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, |
| 69 uint32_t skip) = 0; | 71 uint32_t skip) = 0; |
| 70 | 72 |
| 71 virtual void AsPath( | 73 virtual void AsPath( |
| 72 base::TaskRunner* task_runner, | 74 base::TaskRunner* task_runner, |
| 73 base::Callback<void(const base::FilePath&, bool)> callback) = 0; | 75 base::Callback<void(const base::FilePath&, bool)> callback) = 0; |
| 74 | 76 |
| 75 virtual std::string MimeType() = 0; | 77 virtual std::string MimeType() = 0; |
| 76 | 78 |
| 77 virtual bool HasMojoMagic() = 0; | 79 virtual bool HasMojoMagic() = 0; |
| 78 | 80 |
| 79 virtual bool PeekFirstLine(std::string* line) = 0; | 81 virtual bool PeekFirstLine(std::string* line) = 0; |
| 80 | 82 |
| 81 void Load() { | 83 void Load() { |
| 82 // If the response begins with a #!mojo:<content-handler-url>, use it. | 84 // If the response begins with a #!mojo:<content-handler-url>, use it. |
| 83 GURL url; | 85 GURL url; |
| 84 std::string shebang; | 86 std::string shebang; |
| 85 if (PeekContentHandler(&shebang, &url)) { | 87 if (PeekContentHandler(&shebang, &url)) { |
| 86 load_callbacks_->LoadWithContentHandler( | 88 load_callbacks_->LoadWithContentHandler( |
| 87 url, AsURLResponse(context_->task_runners()->blocking_pool(), | 89 url, shell_handle_.Pass(), |
| 88 static_cast<int>(shebang.size()))); | 90 AsURLResponse(context_->task_runners()->blocking_pool(), |
| 91 static_cast<int>(shebang.size()))); | |
| 89 return; | 92 return; |
| 90 } | 93 } |
| 91 | 94 |
| 92 MimeTypeToURLMap::iterator iter = mime_type_to_url_->find(MimeType()); | 95 MimeTypeToURLMap::iterator iter = mime_type_to_url_->find(MimeType()); |
| 93 if (iter != mime_type_to_url_->end()) { | 96 if (iter != mime_type_to_url_->end()) { |
| 94 load_callbacks_->LoadWithContentHandler( | 97 load_callbacks_->LoadWithContentHandler( |
| 95 iter->second, | 98 iter->second, shell_handle_.Pass(), |
| 96 AsURLResponse(context_->task_runners()->blocking_pool(), 0)); | 99 AsURLResponse(context_->task_runners()->blocking_pool(), 0)); |
| 97 return; | 100 return; |
| 98 } | 101 } |
| 99 | 102 |
| 100 // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo | 103 // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo |
| 101 // application. That could either mean looking for the platform-specific dll | 104 // application. That could either mean looking for the platform-specific dll |
| 102 // header, or looking for some specific mojo signature prepended to the | 105 // header, or looking for some specific mojo signature prepended to the |
| 103 // library. | 106 // library. |
| 104 | 107 |
| 105 AsPath(context_->task_runners()->blocking_pool(), | 108 AsPath(context_->task_runners()->blocking_pool(), |
|
Aaron Boodman
2014/11/18 23:46:15
It will be great when we pull NativeContentHandler
qsr
2014/11/19 13:42:38
Acknowledged.
Aaron Boodman
2014/11/19 15:58:15
I wonder if we could do a MojoLoader too, that res
| |
| 106 base::Bind(&Loader::RunLibrary, weak_ptr_factory_.GetWeakPtr())); | 109 base::Bind(&Loader::RunLibrary, weak_ptr_factory_.GetWeakPtr())); |
| 107 } | 110 } |
| 108 | 111 |
| 109 void ReportComplete() { loader_complete_callback_.Run(this); } | 112 void ReportComplete() { loader_complete_callback_.Run(this); } |
| 110 | 113 |
| 111 private: | 114 private: |
| 112 bool PeekContentHandler(std::string* mojo_shebang, | 115 bool PeekContentHandler(std::string* mojo_shebang, |
| 113 GURL* mojo_content_handler_url) { | 116 GURL* mojo_content_handler_url) { |
| 114 std::string shebang; | 117 std::string shebang; |
| 115 if (HasMojoMagic() && PeekFirstLine(&shebang)) { | 118 if (HasMojoMagic() && PeekFirstLine(&shebang)) { |
| 116 GURL url(shebang.substr(2, std::string::npos)); | 119 GURL url(shebang.substr(2, std::string::npos)); |
| 117 if (url.is_valid()) { | 120 if (url.is_valid()) { |
| 118 *mojo_shebang = shebang; | 121 *mojo_shebang = shebang; |
| 119 *mojo_content_handler_url = url; | 122 *mojo_content_handler_url = url; |
| 120 return true; | 123 return true; |
| 121 } | 124 } |
| 122 } | 125 } |
| 123 return false; | 126 return false; |
| 124 } | 127 } |
| 125 | 128 |
| 126 void RunLibrary(const base::FilePath& path, bool path_exists) { | 129 void RunLibrary(const base::FilePath& path, bool path_exists) { |
| 127 ScopedMessagePipeHandle shell_handle = | 130 DCHECK(shell_handle_.is_valid()); |
| 128 load_callbacks_->RegisterApplication(); | |
| 129 if (!shell_handle.is_valid()) { | |
| 130 ReportComplete(); | |
| 131 return; | |
| 132 } | |
| 133 | 131 |
| 134 if (!path_exists) { | 132 if (!path_exists) { |
| 135 LOG(ERROR) << "Library not started because library path '" << path.value() | 133 LOG(ERROR) << "Library not started because library path '" << path.value() |
| 136 << "' does not exist."; | 134 << "' does not exist."; |
| 137 ReportComplete(); | 135 ReportComplete(); |
| 138 return; | 136 return; |
| 139 } | 137 } |
| 140 | 138 |
| 141 runner_ = runner_factory_->Create(context_); | 139 runner_ = runner_factory_->Create(context_); |
| 142 runner_->Start( | 140 runner_->Start( |
| 143 path, shell_handle.Pass(), | 141 path, shell_handle_.Pass(), |
| 144 base::Bind(&Loader::ReportComplete, weak_ptr_factory_.GetWeakPtr())); | 142 base::Bind(&Loader::ReportComplete, weak_ptr_factory_.GetWeakPtr())); |
| 145 } | 143 } |
| 146 | 144 |
| 145 ScopedMessagePipeHandle shell_handle_; | |
| 147 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks_; | 146 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks_; |
| 148 LoaderCompleteCallback loader_complete_callback_; | 147 LoaderCompleteCallback loader_complete_callback_; |
| 149 Context* context_; | 148 Context* context_; |
| 150 MimeTypeToURLMap* mime_type_to_url_; | 149 MimeTypeToURLMap* mime_type_to_url_; |
| 151 DynamicServiceRunnerFactory* runner_factory_; | 150 DynamicServiceRunnerFactory* runner_factory_; |
| 152 scoped_ptr<DynamicServiceRunner> runner_; | 151 scoped_ptr<DynamicServiceRunner> runner_; |
| 153 base::WeakPtrFactory<Loader> weak_ptr_factory_; | 152 base::WeakPtrFactory<Loader> weak_ptr_factory_; |
| 154 }; | 153 }; |
| 155 | 154 |
| 156 // A loader for local files. | 155 // A loader for local files. |
| 157 class DynamicApplicationLoader::LocalLoader : public Loader { | 156 class DynamicApplicationLoader::LocalLoader : public Loader { |
| 158 public: | 157 public: |
| 159 LocalLoader(const GURL& url, | 158 LocalLoader(const GURL& url, |
| 160 MimeTypeToURLMap* mime_type_to_url, | 159 MimeTypeToURLMap* mime_type_to_url, |
| 161 Context* context, | 160 Context* context, |
| 162 DynamicServiceRunnerFactory* runner_factory, | 161 DynamicServiceRunnerFactory* runner_factory, |
| 162 ScopedMessagePipeHandle shell_handle, | |
| 163 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | 163 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, |
| 164 const LoaderCompleteCallback& loader_complete_callback) | 164 const LoaderCompleteCallback& loader_complete_callback) |
| 165 : Loader(mime_type_to_url, | 165 : Loader(mime_type_to_url, |
| 166 context, | 166 context, |
| 167 runner_factory, | 167 runner_factory, |
| 168 shell_handle.Pass(), | |
| 168 load_callbacks, | 169 load_callbacks, |
| 169 loader_complete_callback), | 170 loader_complete_callback), |
| 170 url_(url), | 171 url_(url), |
| 171 path_(UrlToFile(url)) { | 172 path_(UrlToFile(url)) { |
| 172 Load(); | 173 Load(); |
| 173 } | 174 } |
| 174 | 175 |
| 175 private: | 176 private: |
| 176 static base::FilePath UrlToFile(const GURL& url) { | 177 static base::FilePath UrlToFile(const GURL& url) { |
| 177 DCHECK(url.SchemeIsFile()); | 178 DCHECK(url.SchemeIsFile()); |
| (...skipping 61 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 239 }; | 240 }; |
| 240 | 241 |
| 241 // A loader for network files. | 242 // A loader for network files. |
| 242 class DynamicApplicationLoader::NetworkLoader : public Loader { | 243 class DynamicApplicationLoader::NetworkLoader : public Loader { |
| 243 public: | 244 public: |
| 244 NetworkLoader(const GURL& url, | 245 NetworkLoader(const GURL& url, |
| 245 NetworkService* network_service, | 246 NetworkService* network_service, |
| 246 MimeTypeToURLMap* mime_type_to_url, | 247 MimeTypeToURLMap* mime_type_to_url, |
| 247 Context* context, | 248 Context* context, |
| 248 DynamicServiceRunnerFactory* runner_factory, | 249 DynamicServiceRunnerFactory* runner_factory, |
| 250 ScopedMessagePipeHandle shell_handle, | |
| 249 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | 251 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, |
| 250 const LoaderCompleteCallback& loader_complete_callback) | 252 const LoaderCompleteCallback& loader_complete_callback) |
| 251 : Loader(mime_type_to_url, | 253 : Loader(mime_type_to_url, |
| 252 context, | 254 context, |
| 253 runner_factory, | 255 runner_factory, |
| 256 shell_handle.Pass(), | |
| 254 load_callbacks, | 257 load_callbacks, |
| 255 loader_complete_callback), | 258 loader_complete_callback), |
| 256 weak_ptr_factory_(this) { | 259 weak_ptr_factory_(this) { |
| 257 StartNetworkRequest(url, network_service); | 260 StartNetworkRequest(url, network_service); |
| 258 } | 261 } |
| 259 | 262 |
| 260 ~NetworkLoader() override { | 263 ~NetworkLoader() override { |
| 261 if (!path_.empty()) | 264 if (!path_.empty()) |
| 262 base::DeleteFile(path_, false); | 265 base::DeleteFile(path_, false); |
| 263 } | 266 } |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 361 | 364 |
| 362 void DynamicApplicationLoader::RegisterContentHandler( | 365 void DynamicApplicationLoader::RegisterContentHandler( |
| 363 const std::string& mime_type, | 366 const std::string& mime_type, |
| 364 const GURL& content_handler_url) { | 367 const GURL& content_handler_url) { |
| 365 mime_type_to_url_[mime_type] = content_handler_url; | 368 mime_type_to_url_[mime_type] = content_handler_url; |
| 366 } | 369 } |
| 367 | 370 |
| 368 void DynamicApplicationLoader::Load( | 371 void DynamicApplicationLoader::Load( |
| 369 ApplicationManager* manager, | 372 ApplicationManager* manager, |
| 370 const GURL& url, | 373 const GURL& url, |
| 374 ScopedMessagePipeHandle shell_handle, | |
| 371 scoped_refptr<LoadCallbacks> load_callbacks) { | 375 scoped_refptr<LoadCallbacks> load_callbacks) { |
| 372 if (url.SchemeIsFile()) { | 376 if (url.SchemeIsFile()) { |
| 373 loaders_.push_back(new LocalLoader(url, &mime_type_to_url_, context_, | 377 loaders_.push_back(new LocalLoader( |
| 374 runner_factory_.get(), load_callbacks, | 378 url, &mime_type_to_url_, context_, runner_factory_.get(), |
| 375 loader_complete_callback_)); | 379 shell_handle.Pass(), load_callbacks, loader_complete_callback_)); |
| 376 return; | 380 return; |
| 377 } | 381 } |
| 378 | 382 |
| 379 if (!network_service_) { | 383 if (!network_service_) { |
| 380 context_->application_manager()->ConnectToService( | 384 context_->application_manager()->ConnectToService( |
| 381 GURL("mojo:network_service"), &network_service_); | 385 GURL("mojo:network_service"), &network_service_); |
| 382 } | 386 } |
| 383 | 387 |
| 384 loaders_.push_back(new NetworkLoader( | 388 loaders_.push_back( |
| 385 url, network_service_.get(), &mime_type_to_url_, context_, | 389 new NetworkLoader(url, network_service_.get(), &mime_type_to_url_, |
| 386 runner_factory_.get(), load_callbacks, loader_complete_callback_)); | 390 context_, runner_factory_.get(), shell_handle.Pass(), |
| 391 load_callbacks, loader_complete_callback_)); | |
| 387 } | 392 } |
| 388 | 393 |
| 389 void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager, | 394 void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager, |
| 390 const GURL& url) { | 395 const GURL& url) { |
| 391 // TODO(darin): What should we do about service errors? This implies that | 396 // TODO(darin): What should we do about service errors? This implies that |
| 392 // the app closed its handle to the service manager. Maybe we don't care? | 397 // the app closed its handle to the service manager. Maybe we don't care? |
| 393 } | 398 } |
| 394 | 399 |
| 395 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { | 400 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { |
| 396 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); | 401 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); |
| 397 } | 402 } |
| 398 | 403 |
| 399 } // namespace shell | 404 } // namespace shell |
| 400 } // namespace mojo | 405 } // namespace mojo |
| OLD | NEW |