| OLD | NEW |
| 1 // Copyright 2017 The Chromium Authors. All rights reserved. | 1 // Copyright 2017 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 "components/browser_watcher/stability_paths.h" | 5 #include "components/browser_watcher/stability_paths.h" |
| 6 | 6 |
| 7 #if defined(OS_WIN) | 7 #if defined(OS_WIN) |
| 8 #include <windows.h> | 8 #include <windows.h> |
| 9 #endif // defined(OS_WIN) | 9 #endif // defined(OS_WIN) |
| 10 | 10 |
| 11 #include <memory> | 11 #include <memory> |
| 12 #include <string> | 12 #include <string> |
| 13 #include <utility> | 13 #include <utility> |
| 14 | 14 |
| 15 #include "base/debug/activity_tracker.h" | 15 #include "base/debug/activity_tracker.h" |
| 16 #include "base/feature_list.h" | 16 #include "base/feature_list.h" |
| 17 #include "base/files/file.h" | 17 #include "base/files/file.h" |
| 18 #include "base/files/file_enumerator.h" |
| 18 #include "base/files/memory_mapped_file.h" | 19 #include "base/files/memory_mapped_file.h" |
| 19 #include "base/metrics/persistent_memory_allocator.h" | 20 #include "base/metrics/persistent_memory_allocator.h" |
| 20 #include "base/strings/stringprintf.h" | 21 #include "base/strings/stringprintf.h" |
| 21 #include "base/time/time.h" | 22 #include "base/time/time.h" |
| 22 #include "components/browser_watcher/features.h" | 23 #include "components/browser_watcher/features.h" |
| 23 #include "components/browser_watcher/stability_metrics.h" | 24 #include "components/browser_watcher/stability_metrics.h" |
| 24 | 25 |
| 25 #if defined(OS_WIN) | 26 #if defined(OS_WIN) |
| 26 | 27 |
| 27 #include "third_party/crashpad/crashpad/util/win/time.h" | 28 #include "third_party/crashpad/crashpad/util/win/time.h" |
| 28 | 29 |
| 29 namespace browser_watcher { | 30 namespace browser_watcher { |
| 30 | 31 |
| 32 using base::FilePath; |
| 31 using base::FilePersistentMemoryAllocator; | 33 using base::FilePersistentMemoryAllocator; |
| 32 using base::MemoryMappedFile; | 34 using base::MemoryMappedFile; |
| 33 using base::PersistentMemoryAllocator; | 35 using base::PersistentMemoryAllocator; |
| 34 | 36 |
| 35 namespace { | 37 namespace { |
| 36 | 38 |
| 37 bool GetCreationTime(const base::Process& process, FILETIME* creation_time) { | 39 bool GetCreationTime(const base::Process& process, FILETIME* creation_time) { |
| 38 FILETIME ignore; | 40 FILETIME ignore; |
| 39 return ::GetProcessTimes(process.Handle(), creation_time, &ignore, &ignore, | 41 return ::GetProcessTimes(process.Handle(), creation_time, &ignore, &ignore, |
| 40 &ignore) != 0; | 42 &ignore) != 0; |
| 41 } | 43 } |
| 42 | 44 |
| 43 bool SetPmaFileDeleted(const base::FilePath& file_path) { | 45 bool SetPmaFileDeleted(const base::FilePath& file_path) { |
| 44 // Map the file read-write so it can guarantee consistency between | 46 // Map the file read-write so it can guarantee consistency between |
| 45 // the analyzer and any trackers that may still be active. | 47 // the analyzer and any trackers that may still be active. |
| 46 std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile()); | 48 std::unique_ptr<MemoryMappedFile> mmfile(new MemoryMappedFile()); |
| 47 mmfile->Initialize(file_path, MemoryMappedFile::READ_WRITE); | 49 mmfile->Initialize(file_path, MemoryMappedFile::READ_WRITE); |
| 48 if (!mmfile->IsValid()) | 50 if (!mmfile->IsValid()) |
| 49 return false; | 51 return false; |
| 50 if (!FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, true)) | 52 if (!FilePersistentMemoryAllocator::IsFileAcceptable(*mmfile, true)) |
| 51 return false; | 53 return false; |
| 52 FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, 0, | 54 FilePersistentMemoryAllocator allocator(std::move(mmfile), 0, 0, |
| 53 base::StringPiece(), true); | 55 base::StringPiece(), true); |
| 54 allocator.SetMemoryState(PersistentMemoryAllocator::MEMORY_DELETED); | 56 allocator.SetMemoryState(PersistentMemoryAllocator::MEMORY_DELETED); |
| 55 return true; | 57 return true; |
| 56 } | 58 } |
| 57 | 59 |
| 58 } // namespace | 60 } // namespace |
| 59 | 61 |
| 60 base::FilePath GetStabilityDir(const base::FilePath& user_data_dir) { | 62 FilePath GetStabilityDir(const FilePath& user_data_dir) { |
| 61 return user_data_dir.AppendASCII("Stability"); | 63 return user_data_dir.AppendASCII("Stability"); |
| 62 } | 64 } |
| 63 | 65 |
| 64 base::FilePath GetStabilityFileForProcess(base::ProcessId pid, | 66 FilePath GetStabilityFileForProcess(base::ProcessId pid, |
| 65 timeval creation_time, | 67 timeval creation_time, |
| 66 const base::FilePath& user_data_dir) { | 68 const FilePath& user_data_dir) { |
| 67 base::FilePath stability_dir = GetStabilityDir(user_data_dir); | 69 FilePath stability_dir = GetStabilityDir(user_data_dir); |
| 68 | 70 |
| 69 constexpr uint64_t kMicrosecondsPerSecond = static_cast<uint64_t>(1E6); | 71 constexpr uint64_t kMicrosecondsPerSecond = static_cast<uint64_t>(1E6); |
| 70 int64_t creation_time_us = | 72 int64_t creation_time_us = |
| 71 creation_time.tv_sec * kMicrosecondsPerSecond + creation_time.tv_usec; | 73 creation_time.tv_sec * kMicrosecondsPerSecond + creation_time.tv_usec; |
| 72 | 74 |
| 73 std::string file_name = base::StringPrintf("%u-%lld", pid, creation_time_us); | 75 std::string file_name = base::StringPrintf("%u-%lld", pid, creation_time_us); |
| 74 return stability_dir.AppendASCII(file_name).AddExtension( | 76 return stability_dir.AppendASCII(file_name).AddExtension( |
| 75 base::PersistentMemoryAllocator::kFileExtension); | 77 base::PersistentMemoryAllocator::kFileExtension); |
| 76 } | 78 } |
| 77 | 79 |
| 78 bool GetStabilityFileForProcess(const base::Process& process, | 80 bool GetStabilityFileForProcess(const base::Process& process, |
| 79 const base::FilePath& user_data_dir, | 81 const FilePath& user_data_dir, |
| 80 base::FilePath* file_path) { | 82 FilePath* file_path) { |
| 81 DCHECK(file_path); | 83 DCHECK(file_path); |
| 82 | 84 |
| 83 FILETIME creation_time; | 85 FILETIME creation_time; |
| 84 if (!GetCreationTime(process, &creation_time)) | 86 if (!GetCreationTime(process, &creation_time)) |
| 85 return false; | 87 return false; |
| 86 | 88 |
| 87 // We rely on Crashpad's conversion to ensure the resulting filename is the | 89 // We rely on Crashpad's conversion to ensure the resulting filename is the |
| 88 // same as on crash, when the creation time is obtained via Crashpad. | 90 // same as on crash, when the creation time is obtained via Crashpad. |
| 89 *file_path = GetStabilityFileForProcess( | 91 *file_path = GetStabilityFileForProcess( |
| 90 process.Pid(), crashpad::FiletimeToTimevalEpoch(creation_time), | 92 process.Pid(), crashpad::FiletimeToTimevalEpoch(creation_time), |
| 91 user_data_dir); | 93 user_data_dir); |
| 92 return true; | 94 return true; |
| 93 } | 95 } |
| 94 | 96 |
| 95 base::FilePath::StringType GetStabilityFilePattern() { | 97 FilePath::StringType GetStabilityFilePattern() { |
| 96 return base::FilePath::StringType(FILE_PATH_LITERAL("*-*")) + | 98 return FilePath::StringType(FILE_PATH_LITERAL("*-*")) + |
| 97 base::PersistentMemoryAllocator::kFileExtension; | 99 base::PersistentMemoryAllocator::kFileExtension; |
| 98 } | 100 } |
| 99 | 101 |
| 102 std::vector<FilePath> GetStabilityFiles( |
| 103 const FilePath& stability_dir, |
| 104 const FilePath::StringType& stability_file_pattern, |
| 105 const std::set<FilePath>& excluded_stability_files) { |
| 106 DCHECK_NE(true, stability_dir.empty()); |
| 107 DCHECK_NE(true, stability_file_pattern.empty()); |
| 108 |
| 109 std::vector<FilePath> paths; |
| 110 base::FileEnumerator enumerator(stability_dir, false /* recursive */, |
| 111 base::FileEnumerator::FILES, |
| 112 stability_file_pattern); |
| 113 FilePath path; |
| 114 for (path = enumerator.Next(); !path.empty(); path = enumerator.Next()) { |
| 115 if (excluded_stability_files.find(path) == excluded_stability_files.end()) |
| 116 paths.push_back(path); |
| 117 } |
| 118 return paths; |
| 119 } |
| 120 |
| 100 void MarkOwnStabilityFileDeleted(const base::FilePath& user_data_dir) { | 121 void MarkOwnStabilityFileDeleted(const base::FilePath& user_data_dir) { |
| 101 base::debug::GlobalActivityTracker* global_tracker = | 122 base::debug::GlobalActivityTracker* global_tracker = |
| 102 base::debug::GlobalActivityTracker::Get(); | 123 base::debug::GlobalActivityTracker::Get(); |
| 103 if (!global_tracker) | 124 if (!global_tracker) |
| 104 return; // No stability instrumentation. | 125 return; // No stability instrumentation. |
| 105 | 126 |
| 106 global_tracker->MarkDeleted(); | 127 global_tracker->MarkDeleted(); |
| 107 LogStabilityRecordEvent(StabilityRecordEvent::kMarkDeleted); | 128 LogStabilityRecordEvent(StabilityRecordEvent::kMarkDeleted); |
| 108 | 129 |
| 109 // Open (with delete) and then immediately close the file by going out of | 130 // Open (with delete) and then immediately close the file by going out of |
| (...skipping 19 matching lines...) Expand all Loading... |
| 129 | 150 |
| 130 base::File deleter(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ | | 151 base::File deleter(file_path, base::File::FLAG_OPEN | base::File::FLAG_READ | |
| 131 base::File::FLAG_DELETE_ON_CLOSE); | 152 base::File::FLAG_DELETE_ON_CLOSE); |
| 132 if (!deleter.IsValid()) | 153 if (!deleter.IsValid()) |
| 133 LogCollectOnCrashEvent(CollectOnCrashEvent::kOpenForDeleteFailed); | 154 LogCollectOnCrashEvent(CollectOnCrashEvent::kOpenForDeleteFailed); |
| 134 } | 155 } |
| 135 | 156 |
| 136 } // namespace browser_watcher | 157 } // namespace browser_watcher |
| 137 | 158 |
| 138 #endif // defined(OS_WIN) | 159 #endif // defined(OS_WIN) |
| OLD | NEW |