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 "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.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 266 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
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().c_str(), url.spec().c_str()); |
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 // AppIds should be be both predictable and unique, but any crypto would work. | |
Aaron Boodman
2015/01/23 22:56:01
nit: s/crypto/hash.
| |
310 // TODO(eseidel): Use sha256 once it has an incremental API, crbug.com/451588 | |
311 // Derived from tools/android/md5sum/md5sum.cc with fstream usage removed. | |
312 static bool ComputeAppId(const base::FilePath& path, | |
313 std::string* digest_string) { | |
314 | |
315 base::File file(path, base::File::FLAG_OPEN | base::File::FLAG_READ); | |
316 if (!file.IsValid()) { | |
317 LOG(ERROR) << "Failed to open " << path.value() << " for computing AppId"; | |
318 return false; | |
319 } | |
320 base::MD5Context ctx; | |
321 base::MD5Init(&ctx); | |
322 char buf[1024]; | |
323 while (file.IsValid()) { | |
324 int bytes_read = file.ReadAtCurrentPos(buf, sizeof(buf)); | |
325 if (bytes_read == 0) | |
326 break; | |
327 base::MD5Update(&ctx, base::StringPiece(buf, bytes_read)); | |
328 } | |
329 if (!file.IsValid()) { | |
330 LOG(ERROR) << "Error reading " << path.value(); | |
331 return false; | |
332 } | |
333 base::MD5Digest digest; | |
334 base::MD5Final(&digest, &ctx); | |
335 *digest_string = base::MD5DigestToBase16(digest); | |
336 return true; | |
337 } | |
338 | |
339 static bool RenameToAppId(const base::FilePath& old_path, | |
340 base::FilePath* new_path) { | |
341 std::string app_id; | |
342 if (!ComputeAppId(old_path, &app_id)) | |
343 return false; | |
344 | |
345 base::FilePath temp_dir; | |
346 base::GetTempDir(&temp_dir); | |
347 std::string unique_name = base::StringPrintf("%s.mojo", app_id.c_str()); | |
348 *new_path = temp_dir.Append(unique_name); | |
349 return base::Move(old_path, *new_path); | |
350 } | |
351 | |
352 void CopyCompleted(base::Callback<void(const base::FilePath&, bool)> callback, | |
353 bool success) { | |
354 // The copy completed, now move to $TMP/$APP_ID.mojo before the dlopen. | |
355 if (success) { | |
356 success = false; | |
357 base::FilePath new_path; | |
358 if (RenameToAppId(path_, &new_path)) { | |
359 if (base::PathExists(new_path)) { | |
360 path_ = new_path; | |
361 success = true; | |
362 RecordCacheToURLMapping(path_, url_); | |
363 } | |
364 } | |
365 } | |
366 | |
367 base::MessageLoop::current()->PostTask( | |
368 FROM_HERE, base::Bind(callback, path_, success)); | |
369 } | |
370 | |
307 void AsPath( | 371 void AsPath( |
308 base::TaskRunner* task_runner, | 372 base::TaskRunner* task_runner, |
309 base::Callback<void(const base::FilePath&, bool)> callback) override { | 373 base::Callback<void(const base::FilePath&, bool)> callback) override { |
310 if (!path_.empty() || !response_) { | 374 if (!path_.empty() || !response_) { |
311 base::MessageLoop::current()->PostTask( | 375 base::MessageLoop::current()->PostTask( |
312 FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); | 376 FROM_HERE, base::Bind(callback, path_, base::PathExists(path_))); |
313 return; | 377 return; |
314 } | 378 } |
315 // We don't use the created file, just want the directory and random name. | 379 |
316 base::CreateTemporaryFile(&path_); | 380 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, | 381 common::CopyToFile(response_->body.Pass(), path_, task_runner, |
320 base::Bind(callback, path_)); | 382 base::Bind(&NetworkLoader::CopyCompleted, |
321 | 383 weak_ptr_factory_.GetWeakPtr(), callback)); |
322 RecordCacheToURLMapping(path_, url_); | |
323 } | 384 } |
324 | 385 |
325 std::string MimeType() override { | 386 std::string MimeType() override { |
326 DCHECK(response_); | 387 DCHECK(response_); |
327 return response_->mime_type; | 388 return response_->mime_type; |
328 } | 389 } |
329 | 390 |
330 bool HasMojoMagic() override { | 391 bool HasMojoMagic() override { |
331 std::string magic; | 392 std::string magic; |
332 return BlockingPeekNBytes(response_->body.get(), &magic, strlen(kMojoMagic), | 393 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 | 496 // 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? | 497 // the app closed its handle to the service manager. Maybe we don't care? |
437 } | 498 } |
438 | 499 |
439 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { | 500 void DynamicApplicationLoader::LoaderComplete(Loader* loader) { |
440 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); | 501 loaders_.erase(std::find(loaders_.begin(), loaders_.end(), loader)); |
441 } | 502 } |
442 | 503 |
443 } // namespace shell | 504 } // namespace shell |
444 } // namespace mojo | 505 } // namespace mojo |
OLD | NEW |