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 |