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 "shell/dynamic_application_loader.h" | 5 #include "shell/dynamic_application_loader.h" |
6 | 6 |
7 #include <fstream> | |
Aaron Boodman
2015/01/23 21:56:40
We don't typically use stl's stream support in Chr
eseidel
2015/01/23 22:12:21
Yeah, ComputeAppId is lifted directly from android
Aaron Boodman
2015/01/23 22:29:00
How about base::File::Read() and friends?
| |
7 #include "base/bind.h" | 8 #include "base/bind.h" |
8 #include "base/command_line.h" | 9 #include "base/command_line.h" |
9 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
10 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
11 #include "base/format_macros.h" | 12 #include "base/format_macros.h" |
12 #include "base/logging.h" | 13 #include "base/logging.h" |
14 #include "base/md5.h" | |
13 #include "base/memory/scoped_ptr.h" | 15 #include "base/memory/scoped_ptr.h" |
14 #include "base/memory/weak_ptr.h" | 16 #include "base/memory/weak_ptr.h" |
15 #include "base/message_loop/message_loop.h" | 17 #include "base/message_loop/message_loop.h" |
16 #include "base/process/process.h" | 18 #include "base/process/process.h" |
17 #include "base/strings/string_util.h" | 19 #include "base/strings/string_util.h" |
18 #include "base/strings/stringprintf.h" | 20 #include "base/strings/stringprintf.h" |
19 #include "base/strings/utf_string_conversions.h" | 21 #include "base/strings/utf_string_conversions.h" |
20 #include "mojo/common/common_type_converters.h" | 22 #include "mojo/common/common_type_converters.h" |
21 #include "mojo/common/data_pipe_utils.h" | 23 #include "mojo/common/data_pipe_utils.h" |
22 #include "mojo/public/cpp/system/data_pipe.h" | 24 #include "mojo/public/cpp/system/data_pipe.h" |
(...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
275 uint32_t skip) override { | 277 uint32_t skip) override { |
276 if (skip != 0) { | 278 if (skip != 0) { |
277 MojoResult result = ReadDataRaw( | 279 MojoResult result = ReadDataRaw( |
278 response_->body.get(), nullptr, &skip, | 280 response_->body.get(), nullptr, &skip, |
279 MOJO_READ_DATA_FLAG_ALL_OR_NONE | MOJO_READ_DATA_FLAG_DISCARD); | 281 MOJO_READ_DATA_FLAG_ALL_OR_NONE | MOJO_READ_DATA_FLAG_DISCARD); |
280 DCHECK_EQ(result, MOJO_RESULT_OK); | 282 DCHECK_EQ(result, MOJO_RESULT_OK); |
281 } | 283 } |
282 return response_.Pass(); | 284 return response_.Pass(); |
283 } | 285 } |
284 | 286 |
285 static void RecordCacheToURLMapping(const base::FilePath& path, | 287 static void RecordCacheToURLMapping(const base::FilePath& path, |
Aaron Boodman
2015/01/23 21:56:40
We do not need this anymore, right?
| |
286 const GURL& url) { | 288 const GURL& url) { |
287 // This is used to extract symbols on android. | 289 // This is used to extract symbols on android. |
288 // TODO(eseidel): All users of this log should move to using the map file. | 290 // TODO(eseidel): All users of this log should move to using the map file. |
289 LOG(INFO) << "Caching mojo app " << url << " at " << path.value(); | 291 LOG(INFO) << "Caching mojo app " << url << " at " << path.value(); |
290 | 292 |
291 base::FilePath temp_dir; | 293 base::FilePath temp_dir; |
292 base::GetTempDir(&temp_dir); | 294 base::GetTempDir(&temp_dir); |
293 base::ProcessId pid = base::Process::Current().pid(); | 295 base::ProcessId pid = base::Process::Current().pid(); |
294 std::string map_name = base::StringPrintf("mojo_shell.%d.maps", pid); | 296 std::string map_name = base::StringPrintf("mojo_shell.%d.maps", pid); |
295 base::FilePath map_path = temp_dir.Append(map_name); | 297 base::FilePath map_path = temp_dir.Append(map_name); |
296 | 298 |
297 // TODO(eseidel): Paths or URLs with spaces will need quoting. | 299 // TODO(eseidel): Paths or URLs with spaces will need quoting. |
298 std::string map_entry = | 300 std::string map_entry = |
299 base::StringPrintf("%s %s\n", path.value().data(), url.spec().data()); | 301 base::StringPrintf("%s %s\n", path.value().data(), url.spec().data()); |
300 // TODO(eseidel): AppendToFile is missing O_CREAT, crbug.com/450696 | 302 // TODO(eseidel): AppendToFile is missing O_CREAT, crbug.com/450696 |
301 if (!PathExists(map_path)) | 303 if (!PathExists(map_path)) |
302 base::WriteFile(map_path, map_entry.data(), map_entry.length()); | 304 base::WriteFile(map_path, map_entry.data(), map_entry.length()); |
303 else | 305 else |
304 base::AppendToFile(map_path, map_entry.data(), map_entry.length()); | 306 base::AppendToFile(map_path, map_entry.data(), map_entry.length()); |
305 } | 307 } |
306 | 308 |
309 // Using MD5 because base/md5.h has an incremental API, any crypto would work. | |
Aaron Boodman
2015/01/23 21:56:41
Yeah it would be better to use sha256 I think, if
eseidel
2015/01/23 22:12:21
Agreed. I'll change it to say TODO, sadly md5 is
| |
310 // Derived from android/md5sum.cc | |
311 static bool ComputeAppId(const base::FilePath& path, | |
312 std::string* digest_string) { | |
313 std::ifstream stream(path.value().data()); | |
314 if (!stream.good()) { | |
315 LOG(ERROR) << "Failed to open " << path.value() << " for computing AppId"; | |
316 return false; | |
317 } | |
318 base::MD5Context ctx; | |
319 base::MD5Init(&ctx); | |
320 char buf[1024]; | |
321 while (stream.good()) { | |
322 std::streamsize bytes_read = stream.readsome(buf, sizeof(buf)); | |
323 if (bytes_read == 0) | |
324 break; | |
325 base::MD5Update(&ctx, base::StringPiece(buf, bytes_read)); | |
326 } | |
327 if (stream.fail()) { | |
328 LOG(ERROR) << "Error reading " << path.value(); | |
329 return false; | |
330 } | |
331 base::MD5Digest digest; | |
332 base::MD5Final(&digest, &ctx); | |
333 *digest_string = base::MD5DigestToBase16(digest); | |
334 return true; | |
335 } | |
336 | |
337 void RenameToAppId(base::Callback<void(const base::FilePath&, bool)> callback, | |
338 bool copy_success) { | |
339 // The copy has completed move to a predictable location $TMP/$APP_ID.mojo. | |
Aaron Boodman
2015/01/23 21:56:40
I don't think this comment is true .. we haven't m
eseidel
2015/01/23 22:12:21
Yeah, sorry I was trying to explain what the metho
| |
340 if (copy_success) { | |
Aaron Boodman
2015/01/23 21:56:41
If the copy failed, we're SOL. Should not do anymo
eseidel
2015/01/23 22:12:21
We already send false if the copy failed (by skipp
Aaron Boodman
2015/01/23 22:29:00
I mean we should not call RecordCacheToURLMapping(
| |
341 std::string app_id; | |
342 if (ComputeAppId(path_, &app_id)) { | |
343 base::FilePath temp_dir; | |
344 base::GetTempDir(&temp_dir); | |
345 std::string map_name = base::StringPrintf("%s.mojo", app_id.data()); | |
Aaron Boodman
2015/01/23 21:56:40
app_id.c_str()
Aaron Boodman
2015/01/23 21:56:40
I think 'mapped_name' might be a better name for t
eseidel
2015/01/23 22:12:21
Done.
| |
346 base::FilePath new_path = temp_dir.Append(map_name); | |
347 if (base::Move(path_, new_path)) | |
348 path_ = new_path; | |
349 } | |
350 } | |
351 RecordCacheToURLMapping(path_, url_); | |
352 | |
353 copy_success = copy_success && base::PathExists(path_); | |
354 base::MessageLoop::current()->PostTask( | |
355 FROM_HERE, base::Bind(callback, path_, copy_success)); | |
356 } | |
357 | |
307 void AsPath( | 358 void AsPath( |
308 base::TaskRunner* task_runner, | 359 base::TaskRunner* task_runner, |
309 base::Callback<void(const base::FilePath&, bool)> callback) override { | 360 base::Callback<void(const base::FilePath&, bool)> callback) override { |
310 if (!path_.empty() || !response_) { | 361 if (!path_.empty() || !response_) { |
311 base::MessageLoop::current()->PostTask( | 362 base::MessageLoop::current()->PostTask( |
312 FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); | 363 FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); |
313 return; | 364 return; |
314 } | 365 } |
366 | |
315 // We don't use the created file, just want the directory and random name. | 367 // We don't use the created file, just want the directory and random name. |
Aaron Boodman
2015/01/23 21:56:41
I think this comment is incorrect ... we do use th
eseidel
2015/01/23 22:12:21
Well, CreateTempFile creates and empty file and th
Aaron Boodman
2015/01/23 22:29:00
I see. Can you just delete it then.
| |
316 base::CreateTemporaryFile(&path_); | 368 base::CreateTemporaryFile(&path_); |
317 base::DeleteFile(path_, false); | |
318 path_ = path_.AddExtension(".mojo"); // Make libraries easy to spot. | |
319 common::CopyToFile(response_->body.Pass(), path_, task_runner, | 369 common::CopyToFile(response_->body.Pass(), path_, task_runner, |
320 base::Bind(callback, path_)); | 370 base::Bind(&NetworkLoader::RenameToAppId, |
321 | 371 base::Unretained(this), callback)); |
Aaron Boodman
2015/01/23 21:56:40
Add a comment explaining why unretained is ok?
eseidel
2015/01/23 22:12:21
I'm not sure unretained is OK. If the copy for so
Aaron Boodman
2015/01/23 22:29:00
It actually looks to me like NetworkLoader cannot
| |
322 RecordCacheToURLMapping(path_, url_); | |
323 } | 372 } |
324 | 373 |
325 std::string MimeType() override { | 374 std::string MimeType() override { |
326 DCHECK(response_); | 375 DCHECK(response_); |
327 return response_->mime_type; | 376 return response_->mime_type; |
328 } | 377 } |
329 | 378 |
330 bool HasMojoMagic() override { | 379 bool HasMojoMagic() override { |
331 std::string magic; | 380 std::string magic; |
332 return BlockingPeekNBytes(response_->body.get(), &magic, strlen(kMojoMagic), | 381 return BlockingPeekNBytes(response_->body.get(), &magic, strlen(kMojoMagic), |
(...skipping 102 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
435 // TODO(darin): What should we do about service errors? This implies that | 484 // TODO(darin): What should we do about service errors? This implies that |
436 // the app closed its handle to the service manager. Maybe we don't care? | 485 // the app closed its handle to the service manager. Maybe we don't care? |
437 } | 486 } |
438 | 487 |
439 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { | 488 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { |
440 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); | 489 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); |
441 } | 490 } |
442 | 491 |
443 } // namespace shell | 492 } // namespace shell |
444 } // namespace mojo | 493 } // namespace mojo |
OLD | NEW |