| OLD | NEW |
| 1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 2013 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 "gin/v8_initializer.h" | 5 #include "gin/v8_initializer.h" |
| 6 | 6 |
| 7 #include "base/basictypes.h" | 7 #include "base/basictypes.h" |
| 8 #include "base/files/file.h" | 8 #include "base/files/file.h" |
| 9 #include "base/files/file_path.h" | 9 #include "base/files/file_path.h" |
| 10 #include "base/files/memory_mapped_file.h" | 10 #include "base/files/memory_mapped_file.h" |
| 11 #include "base/logging.h" | 11 #include "base/logging.h" |
| 12 #include "base/memory/scoped_ptr.h" | 12 #include "base/memory/scoped_ptr.h" |
| 13 #include "base/metrics/histogram.h" | 13 #include "base/metrics/histogram.h" |
| 14 #include "base/rand_util.h" | 14 #include "base/rand_util.h" |
| 15 #include "base/strings/sys_string_conversions.h" | 15 #include "base/strings/sys_string_conversions.h" |
| 16 #include "base/threading/platform_thread.h" | 16 #include "base/threading/platform_thread.h" |
| 17 #include "base/time/time.h" | 17 #include "base/time/time.h" |
| 18 #include "crypto/sha2.h" | 18 #include "crypto/sha2.h" |
| 19 | 19 |
| 20 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) | 20 #if defined(V8_USE_EXTERNAL_STARTUP_DATA) |
| 21 #if defined(OS_ANDROID) |
| 22 #include "base/android/apk_assets.h" |
| 23 #endif |
| 21 #if defined(OS_MACOSX) | 24 #if defined(OS_MACOSX) |
| 22 #include "base/mac/foundation_util.h" | 25 #include "base/mac/foundation_util.h" |
| 23 #endif // OS_MACOSX | 26 #endif // OS_MACOSX |
| 24 #include "base/path_service.h" | 27 #include "base/path_service.h" |
| 25 #endif // V8_USE_EXTERNAL_STARTUP_DATA | 28 #endif // V8_USE_EXTERNAL_STARTUP_DATA |
| 26 | 29 |
| 27 namespace gin { | 30 namespace gin { |
| 28 | 31 |
| 29 namespace { | 32 namespace { |
| 30 | 33 |
| (...skipping 11 matching lines...) Expand all Loading... |
| 42 #endif | 45 #endif |
| 43 | 46 |
| 44 // File handles intentionally never closed. Not using File here because its | 47 // File handles intentionally never closed. Not using File here because its |
| 45 // Windows implementation guards against two instances owning the same | 48 // Windows implementation guards against two instances owning the same |
| 46 // PlatformFile (which we allow since we know it is never freed). | 49 // PlatformFile (which we allow since we know it is never freed). |
| 47 base::PlatformFile g_natives_pf = kInvalidPlatformFile; | 50 base::PlatformFile g_natives_pf = kInvalidPlatformFile; |
| 48 base::PlatformFile g_snapshot_pf = kInvalidPlatformFile; | 51 base::PlatformFile g_snapshot_pf = kInvalidPlatformFile; |
| 49 base::MemoryMappedFile::Region g_natives_region; | 52 base::MemoryMappedFile::Region g_natives_region; |
| 50 base::MemoryMappedFile::Region g_snapshot_region; | 53 base::MemoryMappedFile::Region g_snapshot_region; |
| 51 | 54 |
| 52 #if !defined(OS_MACOSX) | |
| 53 const int kV8SnapshotBasePathKey = | |
| 54 #if defined(OS_ANDROID) | |
| 55 base::DIR_ANDROID_APP_DATA; | |
| 56 #elif defined(OS_POSIX) | |
| 57 base::DIR_EXE; | |
| 58 #elif defined(OS_WIN) | |
| 59 base::DIR_MODULE; | |
| 60 #endif // OS_ANDROID | |
| 61 #endif // !OS_MACOSX | |
| 62 | |
| 63 const char kNativesFileName[] = "natives_blob.bin"; | 55 const char kNativesFileName[] = "natives_blob.bin"; |
| 64 const char kSnapshotFileName[] = "snapshot_blob.bin"; | 56 const char kSnapshotFileName[] = "snapshot_blob.bin"; |
| 65 | 57 |
| 66 // Constants for snapshot loading retries taken from: | |
| 67 // https://support.microsoft.com/en-us/kb/316609. | |
| 68 const int kMaxOpenAttempts = 5; | |
| 69 const int kOpenRetryDelayMillis = 250; | |
| 70 | |
| 71 void GetV8FilePath(const char* file_name, base::FilePath* path_out) { | 58 void GetV8FilePath(const char* file_name, base::FilePath* path_out) { |
| 72 #if !defined(OS_MACOSX) | 59 #if !defined(OS_MACOSX) |
| 73 base::FilePath data_path; | 60 base::FilePath data_path; |
| 74 PathService::Get(kV8SnapshotBasePathKey, &data_path); | 61 #if defined(OS_ANDROID) |
| 62 // This is the path within the .apk. |
| 63 data_path = base::FilePath(FILE_PATH_LITERAL("assets")); |
| 64 #elif defined(OS_POSIX) |
| 65 PathService::Get(base::DIR_EXE, &data_path); |
| 66 #elif defined(OS_WIN) |
| 67 PathService::Get(base::DIR_MODULE, &data_path); |
| 68 #endif |
| 75 DCHECK(!data_path.empty()); | 69 DCHECK(!data_path.empty()); |
| 76 | 70 |
| 77 *path_out = data_path.AppendASCII(file_name); | 71 *path_out = data_path.AppendASCII(file_name); |
| 78 #else // !defined(OS_MACOSX) | 72 #else // !defined(OS_MACOSX) |
| 79 base::ScopedCFTypeRef<CFStringRef> natives_file_name( | 73 base::ScopedCFTypeRef<CFStringRef> natives_file_name( |
| 80 base::SysUTF8ToCFStringRef(file_name)); | 74 base::SysUTF8ToCFStringRef(file_name)); |
| 81 *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name); | 75 *path_out = base::mac::PathForFrameworkBundleResource(natives_file_name); |
| 82 #endif // !defined(OS_MACOSX) | 76 #endif // !defined(OS_MACOSX) |
| 83 DCHECK(!path_out->empty()); | 77 DCHECK(!path_out->empty()); |
| 84 } | 78 } |
| (...skipping 16 matching lines...) Expand all Loading... |
| 101 // for A/V on Windows (https://support.microsoft.com/en-us/kb/316609). | 95 // for A/V on Windows (https://support.microsoft.com/en-us/kb/316609). |
| 102 | 96 |
| 103 // These match tools/metrics/histograms.xml | 97 // These match tools/metrics/histograms.xml |
| 104 enum OpenV8FileResult { | 98 enum OpenV8FileResult { |
| 105 OPENED = 0, | 99 OPENED = 0, |
| 106 OPENED_RETRY, | 100 OPENED_RETRY, |
| 107 FAILED_IN_USE, | 101 FAILED_IN_USE, |
| 108 FAILED_OTHER, | 102 FAILED_OTHER, |
| 109 MAX_VALUE | 103 MAX_VALUE |
| 110 }; | 104 }; |
| 111 | |
| 112 base::FilePath path; | 105 base::FilePath path; |
| 113 GetV8FilePath(file_name, &path); | 106 GetV8FilePath(file_name, &path); |
| 114 | 107 |
| 108 #if defined(OS_ANDROID) |
| 109 base::File file(base::android::OpenApkAsset(path.value(), region_out)); |
| 110 OpenV8FileResult result = file.IsValid() ? OpenV8FileResult::OPENED |
| 111 : OpenV8FileResult::FAILED_OTHER; |
| 112 #else |
| 113 // Re-try logic here is motivated by http://crbug.com/479537 |
| 114 // for A/V on Windows (https://support.microsoft.com/en-us/kb/316609). |
| 115 const int kMaxOpenAttempts = 5; |
| 116 const int kOpenRetryDelayMillis = 250; |
| 117 |
| 115 OpenV8FileResult result = OpenV8FileResult::FAILED_IN_USE; | 118 OpenV8FileResult result = OpenV8FileResult::FAILED_IN_USE; |
| 116 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; | 119 int flags = base::File::FLAG_OPEN | base::File::FLAG_READ; |
| 117 base::File file; | 120 base::File file; |
| 118 for (int attempt = 0; attempt < kMaxOpenAttempts; attempt++) { | 121 for (int attempt = 0; attempt < kMaxOpenAttempts; attempt++) { |
| 119 file.Initialize(path, flags); | 122 file.Initialize(path, flags); |
| 120 if (file.IsValid()) { | 123 if (file.IsValid()) { |
| 121 *region_out = base::MemoryMappedFile::Region::kWholeFile; | 124 *region_out = base::MemoryMappedFile::Region::kWholeFile; |
| 122 if (attempt == 0) { | 125 if (attempt == 0) { |
| 123 result = OpenV8FileResult::OPENED; | 126 result = OpenV8FileResult::OPENED; |
| 124 break; | 127 break; |
| 125 } else { | 128 } else { |
| 126 result = OpenV8FileResult::OPENED_RETRY; | 129 result = OpenV8FileResult::OPENED_RETRY; |
| 127 break; | 130 break; |
| 128 } | 131 } |
| 129 } else if (file.error_details() != base::File::FILE_ERROR_IN_USE) { | 132 } else if (file.error_details() != base::File::FILE_ERROR_IN_USE) { |
| 130 result = OpenV8FileResult::FAILED_OTHER; | 133 result = OpenV8FileResult::FAILED_OTHER; |
| 131 break; | 134 break; |
| 132 } else if (kMaxOpenAttempts - 1 != attempt) { | 135 } else if (kMaxOpenAttempts - 1 != attempt) { |
| 133 base::PlatformThread::Sleep( | 136 base::PlatformThread::Sleep( |
| 134 base::TimeDelta::FromMilliseconds(kOpenRetryDelayMillis)); | 137 base::TimeDelta::FromMilliseconds(kOpenRetryDelayMillis)); |
| 135 } | 138 } |
| 136 } | 139 } |
| 140 #endif // defined(OS_ANDROID) |
| 137 | 141 |
| 138 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", | 142 UMA_HISTOGRAM_ENUMERATION("V8.Initializer.OpenV8File.Result", |
| 139 result, | 143 result, |
| 140 OpenV8FileResult::MAX_VALUE); | 144 OpenV8FileResult::MAX_VALUE); |
| 141 return file.TakePlatformFile(); | 145 return file.TakePlatformFile(); |
| 142 } | 146 } |
| 143 | 147 |
| 144 void OpenNativesFileIfNecessary() { | 148 void OpenNativesFileIfNecessary() { |
| 145 if (g_natives_pf == kInvalidPlatformFile) { | 149 if (g_natives_pf == kInvalidPlatformFile) { |
| 146 g_natives_pf = OpenV8File(kNativesFileName, &g_natives_region); | 150 g_natives_pf = OpenV8File(kNativesFileName, &g_natives_region); |
| (...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 363 *snapshot_data_out = | 367 *snapshot_data_out = |
| 364 reinterpret_cast<const char*>(g_mapped_snapshot->data()); | 368 reinterpret_cast<const char*>(g_mapped_snapshot->data()); |
| 365 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); | 369 *snapshot_size_out = static_cast<int>(g_mapped_snapshot->length()); |
| 366 } else { | 370 } else { |
| 367 *snapshot_data_out = NULL; | 371 *snapshot_data_out = NULL; |
| 368 *snapshot_size_out = 0; | 372 *snapshot_size_out = 0; |
| 369 } | 373 } |
| 370 } | 374 } |
| 371 | 375 |
| 372 } // namespace gin | 376 } // namespace gin |
| OLD | NEW |