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 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | 56 ScopedMessagePipeHandle shell_handle, |
| 57 ApplicationLoader::LoadCallback load_callback, |
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_callback_(load_callback), |
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_callback_.Run( |
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_callback_.Run( |
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(), |
(...skipping 11 matching lines...) Expand all Loading... |
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 |
147 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks_; | 145 ScopedMessagePipeHandle shell_handle_; |
| 146 ApplicationLoader::LoadCallback load_callback_; |
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, |
163 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | 162 ScopedMessagePipeHandle shell_handle, |
| 163 ApplicationLoader::LoadCallback load_callback, |
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 load_callbacks, | 168 shell_handle.Pass(), |
| 169 load_callback, |
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()); |
178 url::RawCanonOutputW<1024> output; | 179 url::RawCanonOutputW<1024> output; |
(...skipping 60 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, |
249 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | 250 ScopedMessagePipeHandle shell_handle, |
| 251 ApplicationLoader::LoadCallback load_callback, |
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, |
254 load_callbacks, | 256 shell_handle.Pass(), |
| 257 load_callback, |
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 } |
264 | 267 |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
358 | 361 |
359 DynamicApplicationLoader::~DynamicApplicationLoader() { | 362 DynamicApplicationLoader::~DynamicApplicationLoader() { |
360 } | 363 } |
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(ApplicationManager* manager, |
369 ApplicationManager* manager, | 372 const GURL& url, |
370 const GURL& url, | 373 ScopedMessagePipeHandle shell_handle, |
371 scoped_refptr<LoadCallbacks> load_callbacks) { | 374 LoadCallback load_callback) { |
372 if (url.SchemeIsFile()) { | 375 if (url.SchemeIsFile()) { |
373 loaders_.push_back(new LocalLoader(url, &mime_type_to_url_, context_, | 376 loaders_.push_back(new LocalLoader( |
374 runner_factory_.get(), load_callbacks, | 377 url, &mime_type_to_url_, context_, runner_factory_.get(), |
375 loader_complete_callback_)); | 378 shell_handle.Pass(), load_callback, loader_complete_callback_)); |
376 return; | 379 return; |
377 } | 380 } |
378 | 381 |
379 if (!network_service_) { | 382 if (!network_service_) { |
380 context_->application_manager()->ConnectToService( | 383 context_->application_manager()->ConnectToService( |
381 GURL("mojo:network_service"), &network_service_); | 384 GURL("mojo:network_service"), &network_service_); |
382 } | 385 } |
383 | 386 |
384 loaders_.push_back(new NetworkLoader( | 387 loaders_.push_back( |
385 url, network_service_.get(), &mime_type_to_url_, context_, | 388 new NetworkLoader(url, network_service_.get(), &mime_type_to_url_, |
386 runner_factory_.get(), load_callbacks, loader_complete_callback_)); | 389 context_, runner_factory_.get(), shell_handle.Pass(), |
| 390 load_callback, loader_complete_callback_)); |
387 } | 391 } |
388 | 392 |
389 void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager, | 393 void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager, |
390 const GURL& url) { | 394 const GURL& url) { |
391 // TODO(darin): What should we do about service errors? This implies that | 395 // 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? | 396 // the app closed its handle to the service manager. Maybe we don't care? |
393 } | 397 } |
394 | 398 |
395 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { | 399 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { |
396 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); | 400 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); |
397 } | 401 } |
398 | 402 |
399 } // namespace shell | 403 } // namespace shell |
400 } // namespace mojo | 404 } // namespace mojo |
OLD | NEW |