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" |
11 #include "base/format_macros.h" | |
12 #include "base/logging.h" | |
11 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
12 #include "base/memory/weak_ptr.h" | 14 #include "base/memory/weak_ptr.h" |
13 #include "base/message_loop/message_loop.h" | 15 #include "base/message_loop/message_loop.h" |
14 #include "base/strings/string_util.h" | 16 #include "base/strings/string_util.h" |
17 #include "base/strings/stringprintf.h" | |
15 #include "base/strings/utf_string_conversions.h" | 18 #include "base/strings/utf_string_conversions.h" |
16 #include "mojo/common/common_type_converters.h" | 19 #include "mojo/common/common_type_converters.h" |
17 #include "mojo/common/data_pipe_utils.h" | 20 #include "mojo/common/data_pipe_utils.h" |
21 #include "mojo/public/cpp/system/data_pipe.h" | |
18 #include "mojo/services/public/interfaces/network/url_loader.mojom.h" | 22 #include "mojo/services/public/interfaces/network/url_loader.mojom.h" |
19 #include "mojo/shell/context.h" | 23 #include "mojo/shell/context.h" |
20 #include "mojo/shell/data_pipe_peek.h" | 24 #include "mojo/shell/data_pipe_peek.h" |
21 #include "mojo/shell/filename_util.h" | 25 #include "mojo/shell/filename_util.h" |
22 #include "mojo/shell/switches.h" | 26 #include "mojo/shell/switches.h" |
23 #include "url/url_util.h" | 27 #include "url/url_util.h" |
24 | 28 |
25 namespace mojo { | 29 namespace mojo { |
26 namespace shell { | 30 namespace shell { |
27 | 31 |
28 // Encapsulates loading and running one individual application. | 32 namespace { |
29 // | 33 |
30 // Loaders are owned by DynamicApplicationLoader. DynamicApplicationLoader must | 34 static const char kMojoMagic[] = "#!mojo:"; |
31 // ensure that all the parameters passed to Loader subclasses stay valid through | 35 static const size_t kMaxShebangLength = 2048; |
32 // Loader's lifetime. | 36 |
33 // | 37 void IgnoreResult(bool result) { |
34 // Async operations are done with WeakPtr to protect against | 38 } |
35 // DynamicApplicationLoader going away (and taking all the Loaders with it) | 39 |
36 // while the async operation is outstanding. | 40 // A request to load a given URL. |
37 class DynamicApplicationLoader::Loader { | 41 class LoaderRequest { |
38 public: | 42 public: |
39 Loader(Context* context, | 43 virtual ~LoaderRequest() {} |
40 DynamicServiceRunnerFactory* runner_factory, | |
41 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | |
42 const LoaderCompleteCallback& loader_complete_callback) | |
43 : load_callbacks_(load_callbacks), | |
44 loader_complete_callback_(loader_complete_callback), | |
45 context_(context), | |
46 runner_factory_(runner_factory), | |
47 weak_ptr_factory_(this) {} | |
48 | 44 |
49 virtual ~Loader() {} | 45 virtual URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, |
46 uint32_t skip) = 0; | |
47 | |
48 virtual void AsPath( | |
49 base::TaskRunner* task_runner, | |
50 base::Callback<void(const base::FilePath&, bool)> callback) = 0; | |
51 | |
52 bool PeekContentHandler(std::string* mojo_shebang, | |
Aaron Boodman
2014/11/07 08:56:27
I would prefer this function in loader, and make L
| |
53 GURL* mojo_content_handler_url) { | |
54 std::string shebang; | |
55 if (HasMojoMagic() && PeekFirstLine(&shebang)) { | |
56 GURL url(shebang.substr(2, std::string::npos)); | |
57 if (url.is_valid()) { | |
58 *mojo_shebang = shebang; | |
59 *mojo_content_handler_url = url; | |
60 return true; | |
61 } | |
62 } | |
63 return false; | |
64 } | |
65 | |
66 virtual std::string MimeType() = 0; | |
50 | 67 |
51 protected: | 68 protected: |
52 void RunLibrary(const base::FilePath& path, bool path_exists) { | 69 virtual bool HasMojoMagic() = 0; |
53 ScopedMessagePipeHandle shell_handle = | 70 virtual bool PeekFirstLine(std::string* line) = 0; |
54 load_callbacks_->RegisterApplication(); | 71 }; |
55 if (!shell_handle.is_valid()) { | 72 |
56 LoaderComplete(); | 73 // A request to load a remote URL. |
74 class NetworkLoaderRequest : public LoaderRequest { | |
75 public: | |
76 NetworkLoaderRequest(const GURL& url, | |
77 NetworkService* network_service, | |
78 const base::Callback<void(bool)>& completion_callback) | |
79 : completion_callback_(completion_callback), weak_ptr_factory_(this) { | |
80 Load(url, network_service); | |
81 } | |
82 | |
83 ~NetworkLoaderRequest() override { | |
84 if (!path_.empty()) | |
85 base::DeleteFile(path_, false); | |
86 } | |
87 | |
88 URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, | |
89 uint32_t skip) override { | |
90 if (skip != 0) { | |
91 MojoResult result = ReadDataRaw( | |
92 response_->body.get(), nullptr, &skip, | |
93 MOJO_READ_DATA_FLAG_ALL_OR_NONE | MOJO_READ_DATA_FLAG_DISCARD); | |
94 DCHECK_EQ(result, MOJO_RESULT_OK); | |
95 } | |
96 return response_.Pass(); | |
97 } | |
98 | |
99 void AsPath( | |
100 base::TaskRunner* task_runner, | |
101 base::Callback<void(const base::FilePath&, bool)> callback) override { | |
102 if (!path_.empty() || !response_) { | |
103 base::MessageLoop::current()->PostTask( | |
104 FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); | |
57 return; | 105 return; |
58 } | 106 } |
107 base::CreateTemporaryFile(&path_); | |
108 common::CopyToFile(response_->body.Pass(), path_, task_runner, | |
109 base::Bind(callback, path_)); | |
110 } | |
59 | 111 |
60 if (!path_exists) { | 112 std::string MimeType() override { |
61 LOG(ERROR) << "Library not started because library path '" << path.value() | 113 DCHECK(response_); |
62 << "' does not exist."; | 114 return response_->mime_type; |
63 LoaderComplete(); | 115 } |
116 | |
117 private: | |
118 // TODO(hansmuller): Revisit this when a real peek operation is available. | |
119 static const MojoDeadline kPeekTimeout = MOJO_DEADLINE_INDEFINITE; | |
120 | |
121 bool HasMojoMagic() override { | |
122 std::string magic; | |
123 return BlockingPeekNBytes(response_->body.get(), &magic, strlen(kMojoMagic), | |
124 kPeekTimeout) && | |
125 magic == kMojoMagic; | |
126 } | |
127 | |
128 bool PeekFirstLine(std::string* line) override { | |
129 return BlockingPeekLine(response_->body.get(), line, kMaxShebangLength, | |
130 kPeekTimeout); | |
131 } | |
132 | |
133 void Load(const GURL& url, NetworkService* network_service) { | |
134 URLRequestPtr request(URLRequest::New()); | |
135 request->url = String::From(url); | |
136 request->auto_follow_redirects = true; | |
137 | |
138 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
139 switches::kDisableCache)) { | |
140 request->bypass_cache = true; | |
141 } | |
142 | |
143 network_service->CreateURLLoader(GetProxy(&url_loader_)); | |
144 url_loader_->Start(request.Pass(), | |
145 base::Bind(&NetworkLoaderRequest::OnLoadComplete, | |
146 weak_ptr_factory_.GetWeakPtr())); | |
147 } | |
148 | |
149 void OnLoadComplete(URLResponsePtr response) { | |
150 if (response->error) { | |
151 LOG(ERROR) << "Error (" << response->error->code << ": " | |
152 << response->error->description << ") while fetching " | |
153 << response->url; | |
154 completion_callback_.Run(false); | |
64 return; | 155 return; |
65 } | 156 } |
66 | 157 response_ = response.Pass(); |
67 runner_ = runner_factory_->Create(context_); | 158 completion_callback_.Run(true); |
68 runner_->Start( | |
69 path, | |
70 shell_handle.Pass(), | |
71 base::Bind(&Loader::LoaderComplete, weak_ptr_factory_.GetWeakPtr())); | |
72 } | 159 } |
73 | 160 |
74 void LoaderComplete() { loader_complete_callback_.Run(this); } | 161 base::Callback<void(bool)> completion_callback_; |
162 URLLoaderPtr url_loader_; | |
163 URLResponsePtr response_; | |
164 base::FilePath path_; | |
165 base::WeakPtrFactory<NetworkLoaderRequest> weak_ptr_factory_; | |
75 | 166 |
76 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks_; | 167 DISALLOW_COPY_AND_ASSIGN(NetworkLoaderRequest); |
77 LoaderCompleteCallback loader_complete_callback_; | 168 }; |
78 Context* context_; | 169 |
170 // A request to load a file URL. | |
171 class LocalLoaderRequest : public LoaderRequest { | |
172 public: | |
173 LocalLoaderRequest(const GURL& url, | |
174 const base::Callback<void(bool)>& completion_callback) | |
175 : url_(url), path_(UrlToFile(url)) { | |
176 base::MessageLoop::current()->PostTask( | |
177 FROM_HERE, base::Bind(completion_callback, true)); | |
178 } | |
179 | |
180 URLResponsePtr AsURLResponse(base::TaskRunner* task_runner, | |
181 uint32_t skip) override { | |
182 URLResponsePtr response(URLResponse::New()); | |
183 response->url = String::From(url_); | |
184 DataPipe data_pipe; | |
185 response->body = data_pipe.consumer_handle.Pass(); | |
186 int64 file_size; | |
187 if (base::GetFileSize(path_, &file_size)) { | |
188 response->headers = Array<String>(1); | |
189 response->headers[0] = | |
190 base::StringPrintf("Content-Length: %" PRId64, file_size); | |
191 } | |
192 common::CopyFromFile(path_, data_pipe.producer_handle.Pass(), skip, | |
193 task_runner, base::Bind(&IgnoreResult)); | |
194 return response.Pass(); | |
195 } | |
196 | |
197 void AsPath( | |
198 base::TaskRunner* task_runner, | |
199 base::Callback<void(const base::FilePath&, bool)> callback) override { | |
200 base::MessageLoop::current()->PostTask( | |
201 FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); | |
202 } | |
203 | |
204 std::string MimeType() override { return ""; } | |
79 | 205 |
80 private: | 206 private: |
81 DynamicServiceRunnerFactory* runner_factory_; | 207 static base::FilePath UrlToFile(const GURL& url) { |
82 scoped_ptr<DynamicServiceRunner> runner_; | |
83 base::WeakPtrFactory<Loader> weak_ptr_factory_; | |
84 }; | |
85 | |
86 // A loader for local files. | |
87 class DynamicApplicationLoader::LocalLoader : public Loader { | |
88 public: | |
89 LocalLoader(const GURL& url, | |
90 Context* context, | |
91 DynamicServiceRunnerFactory* runner_factory, | |
92 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | |
93 const LoaderCompleteCallback& loader_complete_callback) | |
94 : Loader(context, | |
95 runner_factory, | |
96 load_callbacks, | |
97 loader_complete_callback), | |
98 weak_ptr_factory_(this) { | |
99 DCHECK(url.SchemeIsFile()); | 208 DCHECK(url.SchemeIsFile()); |
100 url::RawCanonOutputW<1024> output; | 209 url::RawCanonOutputW<1024> output; |
101 url::DecodeURLEscapeSequences( | 210 url::DecodeURLEscapeSequences( |
102 url.path().data(), static_cast<int>(url.path().length()), &output); | 211 url.path().data(), static_cast<int>(url.path().length()), &output); |
103 base::string16 decoded_path = | 212 base::string16 decoded_path = |
104 base::string16(output.data(), output.length()); | 213 base::string16(output.data(), output.length()); |
105 #if defined(OS_WIN) | 214 #if defined(OS_WIN) |
106 base::TrimString(decoded_path, L"/", &decoded_path); | 215 base::TrimString(decoded_path, L"/", &decoded_path); |
107 base::FilePath path(decoded_path); | 216 base::FilePath path(decoded_path); |
108 #else | 217 #else |
109 base::FilePath path(base::UTF16ToUTF8(decoded_path)); | 218 base::FilePath path(base::UTF16ToUTF8(decoded_path)); |
110 #endif | 219 #endif |
111 | 220 return path; |
112 // Async for consistency with network case. | |
113 base::MessageLoop::current()->PostTask( | |
114 FROM_HERE, | |
115 base::Bind(&LocalLoader::RunLibrary, | |
116 weak_ptr_factory_.GetWeakPtr(), | |
117 path, | |
118 base::PathExists(path))); | |
119 } | 221 } |
120 | 222 |
121 ~LocalLoader() override {} | 223 bool HasMojoMagic() override { |
224 std::string magic; | |
225 ReadFileToString(path_, &magic, strlen(kMojoMagic)); | |
226 return magic == kMojoMagic; | |
227 } | |
228 | |
229 bool PeekFirstLine(std::string* line) override { | |
230 std::string start_of_file; | |
231 ReadFileToString(path_, &start_of_file, kMaxShebangLength); | |
232 size_t return_position = start_of_file.find('\n'); | |
233 if (return_position == std::string::npos) | |
234 return false; | |
235 *line = start_of_file.substr(0, return_position + 1); | |
236 return true; | |
237 } | |
238 | |
239 GURL url_; | |
240 base::FilePath path_; | |
241 | |
242 DISALLOW_COPY_AND_ASSIGN(LocalLoaderRequest); | |
243 }; | |
244 | |
245 } // namespace | |
246 | |
247 // Encapsulates loading and running one individual application. | |
248 // | |
249 // Loaders are owned by DynamicApplicationLoader. DynamicApplicationLoader must | |
250 // ensure that all the parameters passed to Loader subclasses stay valid through | |
251 // Loader's lifetime. | |
252 // | |
253 // Async operations are done with WeakPtr to protect against | |
254 // DynamicApplicationLoader going away (and taking all the Loaders with it) | |
255 // while the async operation is outstanding. | |
256 class DynamicApplicationLoader::Loader { | |
257 public: | |
258 Loader(const GURL& url, | |
259 MimeTypeToURLMap* mime_type_to_url, | |
260 Context* context, | |
261 DynamicServiceRunnerFactory* runner_factory, | |
262 NetworkServicePtr* network_service, | |
263 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | |
264 const LoaderCompleteCallback& loader_complete_callback) | |
265 : load_callbacks_(load_callbacks), | |
266 loader_complete_callback_(loader_complete_callback), | |
267 context_(context), | |
268 mime_type_to_url_(mime_type_to_url), | |
269 runner_factory_(runner_factory), | |
270 network_service_(network_service), | |
271 weak_ptr_factory_(this) { | |
272 Load(url, network_service); | |
273 } | |
274 | |
275 virtual ~Loader() {} | |
122 | 276 |
123 private: | 277 private: |
124 base::WeakPtrFactory<LocalLoader> weak_ptr_factory_; | 278 void RunLibrary(const base::FilePath& path, bool path_exists) { |
125 }; | 279 ScopedMessagePipeHandle shell_handle = |
126 | 280 load_callbacks_->RegisterApplication(); |
127 // A loader for network files. | 281 if (!shell_handle.is_valid()) { |
128 class DynamicApplicationLoader::NetworkLoader : public Loader { | |
129 public: | |
130 NetworkLoader(const GURL& url, | |
131 MimeTypeToURLMap* mime_type_to_url, | |
132 Context* context, | |
133 DynamicServiceRunnerFactory* runner_factory, | |
134 NetworkService* network_service, | |
135 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks, | |
136 const LoaderCompleteCallback& loader_complete_callback) | |
137 : Loader(context, | |
138 runner_factory, | |
139 load_callbacks, | |
140 loader_complete_callback), | |
141 mime_type_to_url_(mime_type_to_url), | |
142 weak_ptr_factory_(this) { | |
143 URLRequestPtr request(URLRequest::New()); | |
144 request->url = String::From(url); | |
145 request->auto_follow_redirects = true; | |
146 | |
147 if (base::CommandLine::ForCurrentProcess()->HasSwitch( | |
148 switches::kDisableCache)) { | |
149 request->bypass_cache = true; | |
150 } | |
151 | |
152 network_service->CreateURLLoader(GetProxy(&url_loader_)); | |
153 url_loader_->Start(request.Pass(), | |
154 base::Bind(&NetworkLoader::OnLoadComplete, | |
155 weak_ptr_factory_.GetWeakPtr())); | |
156 } | |
157 | |
158 ~NetworkLoader() override { | |
159 if (!file_.empty()) | |
160 base::DeleteFile(file_, false); | |
161 } | |
162 | |
163 private: | |
164 bool PeekContentHandler(DataPipeConsumerHandle source, | |
165 std::string* mojo_shebang, | |
166 GURL* mojo_content_handler_url) | |
167 { | |
168 const char* kMojoMagic = "#!mojo:"; | |
169 // TODO(hansmuller): Revisit this when a real peek operation is available. | |
170 const MojoDeadline kPeekTimeout = MOJO_DEADLINE_INDEFINITE; | |
171 const size_t kMaxShebangLength = 2048; | |
172 | |
173 std::string magic; | |
174 std::string shebang; | |
175 if (BlockingPeekNBytes(source, &magic, strlen(kMojoMagic), kPeekTimeout) && | |
176 magic == kMojoMagic && | |
177 BlockingPeekLine(source, &shebang, kMaxShebangLength, kPeekTimeout)) { | |
178 GURL url(shebang.substr(2, std::string::npos)); | |
179 if (url.is_valid()) { | |
180 *mojo_shebang = shebang; | |
181 *mojo_content_handler_url = url; | |
182 return true; | |
183 } | |
184 } | |
185 return false; | |
186 } | |
187 | |
188 void OnLoadComplete(URLResponsePtr response) { | |
189 if (response->error) { | |
190 LOG(ERROR) << "Error (" << response->error->code << ": " | |
191 << response->error->description << ") while fetching " | |
192 << response->url; | |
193 LoaderComplete(); | 282 LoaderComplete(); |
194 return; | 283 return; |
195 } | 284 } |
285 | |
286 if (!path_exists) { | |
287 LOG(ERROR) << "Library not started because library path '" << path.value() | |
288 << "' does not exist."; | |
289 LoaderComplete(); | |
290 return; | |
291 } | |
292 | |
293 runner_ = runner_factory_->Create(context_); | |
294 runner_->Start( | |
295 path, shell_handle.Pass(), | |
296 base::Bind(&Loader::LoaderComplete, weak_ptr_factory_.GetWeakPtr())); | |
297 } | |
298 | |
299 void LoaderComplete() { loader_complete_callback_.Run(this); } | |
300 | |
301 void OnResponse(bool success) { | |
302 if (!success) { | |
303 LoaderComplete(); | |
304 return; | |
305 } | |
196 | 306 |
197 // If the response begins with a #!mojo:<content-handler-url>, use it. | 307 // If the response begins with a #!mojo:<content-handler-url>, use it. |
198 { | 308 { |
199 GURL url; | 309 GURL url; |
200 std::string shebang; | 310 std::string shebang; |
201 if (PeekContentHandler(response->body.get(), &shebang, &url)) { | 311 if (request_->PeekContentHandler(&shebang, &url)) { |
202 uint32_t num_skip_bytes = shebang.size(); | 312 load_callbacks_->LoadWithContentHandler( |
203 if (ReadDataRaw(response->body.get(), | 313 url, |
204 nullptr, | 314 request_->AsURLResponse(context_->task_runners()->blocking_pool(), |
205 &num_skip_bytes, | 315 shebang.size())); |
206 MOJO_READ_DATA_FLAG_ALL_OR_NONE | | 316 return; |
207 MOJO_READ_DATA_FLAG_DISCARD) == | |
208 MOJO_RESULT_OK) { | |
209 load_callbacks_->LoadWithContentHandler(url, response.Pass()); | |
210 return; | |
211 } | |
212 } | 317 } |
213 } | 318 } |
214 | 319 |
215 MimeTypeToURLMap::iterator iter = | 320 MimeTypeToURLMap::iterator iter = |
216 mime_type_to_url_->find(response->mime_type); | 321 mime_type_to_url_->find(request_->MimeType()); |
217 if (iter != mime_type_to_url_->end()) { | 322 if (iter != mime_type_to_url_->end()) { |
218 load_callbacks_->LoadWithContentHandler(iter->second, response.Pass()); | 323 load_callbacks_->LoadWithContentHandler( |
324 iter->second, request_->AsURLResponse( | |
325 context_->task_runners()->blocking_pool(), 0)); | |
219 return; | 326 return; |
220 } | 327 } |
221 | 328 |
222 // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo | 329 // TODO(aa): Sanity check that the thing we got looks vaguely like a mojo |
223 // application. That could either mean looking for the platform-specific dll | 330 // application. That could either mean looking for the platform-specific dll |
224 // header, or looking for some specific mojo signature prepended to the | 331 // header, or looking for some specific mojo signature prepended to the |
225 // library. | 332 // library. |
226 | 333 |
227 base::CreateTemporaryFile(&file_); | 334 request_->AsPath( |
228 common::CopyToFile( | |
229 response->body.Pass(), | |
230 file_, | |
231 context_->task_runners()->blocking_pool(), | 335 context_->task_runners()->blocking_pool(), |
232 base::Bind( | 336 base::Bind(&Loader::RunLibrary, weak_ptr_factory_.GetWeakPtr())); |
233 &NetworkLoader::RunLibrary, weak_ptr_factory_.GetWeakPtr(), file_)); | |
234 } | 337 } |
235 | 338 |
339 void Load(const GURL& url, NetworkServicePtr* network_service) { | |
Aaron Boodman
2014/11/07 08:56:27
second param never used.
| |
340 GURL resolved_url; | |
341 if (url.SchemeIs("mojo")) { | |
342 resolved_url = context_->mojo_url_resolver()->Resolve(url); | |
343 } else { | |
344 resolved_url = url; | |
345 } | |
346 | |
347 if (resolved_url.SchemeIsFile()) { | |
348 request_.reset(new LocalLoaderRequest( | |
349 resolved_url, | |
350 base::Bind(&DynamicApplicationLoader::Loader::OnResponse, | |
351 weak_ptr_factory_.GetWeakPtr()))); | |
352 return; | |
353 } | |
354 | |
355 if (!network_service_->get()) { | |
Aaron Boodman
2014/11/07 08:56:27
Put this back in DAL::Load() so that we share one
| |
356 context_->application_manager()->ConnectToService( | |
357 GURL("mojo:network_service"), network_service_); | |
Aaron Boodman
2014/11/07 08:56:27
network_service_ is a pointer, so I guess this pip
qsr
2014/11/07 09:33:22
I mixed 2 things here, sorry. network_service_ sho
| |
358 } | |
359 | |
360 request_.reset(new NetworkLoaderRequest( | |
361 resolved_url, network_service_->get(), | |
362 base::Bind(&DynamicApplicationLoader::Loader::OnResponse, | |
363 weak_ptr_factory_.GetWeakPtr()))); | |
364 } | |
365 | |
366 scoped_refptr<ApplicationLoader::LoadCallbacks> load_callbacks_; | |
367 LoaderCompleteCallback loader_complete_callback_; | |
368 Context* context_; | |
236 MimeTypeToURLMap* mime_type_to_url_; | 369 MimeTypeToURLMap* mime_type_to_url_; |
237 URLLoaderPtr url_loader_; | 370 DynamicServiceRunnerFactory* runner_factory_; |
238 base::FilePath file_; | 371 NetworkServicePtr* network_service_; |
239 base::WeakPtrFactory<NetworkLoader> weak_ptr_factory_; | 372 scoped_ptr<DynamicServiceRunner> runner_; |
373 scoped_ptr<LoaderRequest> request_; | |
374 base::WeakPtrFactory<Loader> weak_ptr_factory_; | |
240 }; | 375 }; |
376 | |
241 DynamicApplicationLoader::DynamicApplicationLoader( | 377 DynamicApplicationLoader::DynamicApplicationLoader( |
242 Context* context, | 378 Context* context, |
243 scoped_ptr<DynamicServiceRunnerFactory> runner_factory) | 379 scoped_ptr<DynamicServiceRunnerFactory> runner_factory) |
244 : context_(context), | 380 : context_(context), |
245 runner_factory_(runner_factory.Pass()), | 381 runner_factory_(runner_factory.Pass()), |
246 | 382 |
247 // Unretained() is correct here because DynamicApplicationLoader owns the | 383 // Unretained() is correct here because DynamicApplicationLoader owns the |
248 // loaders that we pass this callback to. | 384 // loaders that we pass this callback to. |
249 loader_complete_callback_( | 385 loader_complete_callback_( |
250 base::Bind(&DynamicApplicationLoader::LoaderComplete, | 386 base::Bind(&DynamicApplicationLoader::LoaderComplete, |
251 base::Unretained(this))) { | 387 base::Unretained(this))) { |
252 } | 388 } |
253 | 389 |
254 DynamicApplicationLoader::~DynamicApplicationLoader() { | 390 DynamicApplicationLoader::~DynamicApplicationLoader() { |
255 } | 391 } |
256 | 392 |
257 void DynamicApplicationLoader::RegisterContentHandler( | 393 void DynamicApplicationLoader::RegisterContentHandler( |
258 const std::string& mime_type, | 394 const std::string& mime_type, |
259 const GURL& content_handler_url) { | 395 const GURL& content_handler_url) { |
260 mime_type_to_url_[mime_type] = content_handler_url; | 396 mime_type_to_url_[mime_type] = content_handler_url; |
261 } | 397 } |
262 | 398 |
263 void DynamicApplicationLoader::Load( | 399 void DynamicApplicationLoader::Load( |
264 ApplicationManager* manager, | 400 ApplicationManager* manager, |
265 const GURL& url, | 401 const GURL& url, |
266 scoped_refptr<LoadCallbacks> load_callbacks) { | 402 scoped_refptr<LoadCallbacks> load_callbacks) { |
267 GURL resolved_url; | 403 loaders_.push_back(new Loader(url, &mime_type_to_url_, context_, |
268 if (url.SchemeIs("mojo")) { | 404 runner_factory_.get(), &network_service_, |
Aaron Boodman
2014/11/07 08:56:27
this is always null.
| |
269 resolved_url = context_->mojo_url_resolver()->Resolve(url); | 405 load_callbacks, loader_complete_callback_)); |
270 } else { | |
271 resolved_url = url; | |
272 } | |
273 | |
274 if (resolved_url.SchemeIsFile()) { | |
275 loaders_.push_back(new LocalLoader(resolved_url, | |
276 context_, | |
277 runner_factory_.get(), | |
278 load_callbacks, | |
279 loader_complete_callback_)); | |
280 return; | |
281 } | |
282 | |
283 if (!network_service_) { | |
284 context_->application_manager()->ConnectToService( | |
285 GURL("mojo:network_service"), &network_service_); | |
286 } | |
287 | |
288 loaders_.push_back(new NetworkLoader(resolved_url, | |
289 &mime_type_to_url_, | |
290 context_, | |
291 runner_factory_.get(), | |
292 network_service_.get(), | |
293 load_callbacks, | |
294 loader_complete_callback_)); | |
295 } | 406 } |
296 | 407 |
297 void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager, | 408 void DynamicApplicationLoader::OnApplicationError(ApplicationManager* manager, |
298 const GURL& url) { | 409 const GURL& url) { |
299 // TODO(darin): What should we do about service errors? This implies that | 410 // TODO(darin): What should we do about service errors? This implies that |
300 // the app closed its handle to the service manager. Maybe we don't care? | 411 // the app closed its handle to the service manager. Maybe we don't care? |
301 } | 412 } |
302 | 413 |
303 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { | 414 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { |
304 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); | 415 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); |
305 } | 416 } |
306 | 417 |
307 } // namespace shell | 418 } // namespace shell |
308 } // namespace mojo | 419 } // namespace mojo |
OLD | NEW |