Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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 "chrome/installer/setup/installer_metrics.h" | 5 #include "chrome/installer/setup/persistent_histogram_storage.h" |
| 6 | 6 |
| 7 #include <windows.h> // NOLINT | |
| 8 #include <atlsecurity.h> | |
| 9 | |
| 10 #include "base/files/file_enumerator.h" | |
| 11 #include "base/files/file_path.h" | 7 #include "base/files/file_path.h" |
| 12 #include "base/files/file_util.h" | 8 #include "base/files/file_util.h" |
| 13 #include "base/files/important_file_writer.h" | 9 #include "base/files/important_file_writer.h" |
| 10 #include "base/logging.h" | |
| 14 #include "base/metrics/histogram_base.h" | 11 #include "base/metrics/histogram_base.h" |
| 15 #include "base/metrics/persistent_histogram_allocator.h" | 12 #include "base/metrics/persistent_histogram_allocator.h" |
| 16 #include "base/metrics/persistent_memory_allocator.h" | 13 #include "base/metrics/persistent_memory_allocator.h" |
| 17 #include "base/strings/string_piece.h" | 14 #include "base/strings/string_piece.h" |
| 18 #include "base/strings/stringprintf.h" | 15 #include "base/strings/stringprintf.h" |
| 19 #include "base/time/time.h" | 16 #include "base/time/time.h" |
| 20 #include "chrome/installer/util/util_constants.h" | 17 #include "chrome/installer/util/util_constants.h" |
| 21 | 18 |
| 22 namespace installer { | 19 namespace installer { |
| 23 | 20 |
| 24 namespace { | 21 PersistentHistogramStorage::PersistentHistogramStorage() { |
| 25 | |
| 26 // This is duplicated from components/metrics/file_metrics_provider.h which is | |
| 27 // not accessible from setup code. | |
| 28 const base::FilePath::CharType MetricsFileExtension[] = | |
| 29 FILE_PATH_LITERAL(".pma"); | |
| 30 | |
| 31 // Add to the ACL of an object on disk. This follows the method from MSDN: | |
| 32 // https://msdn.microsoft.com/en-us/library/windows/desktop/aa379283.aspx | |
| 33 // This is done using explicit flags rather than the "security string" format | |
| 34 // because strings do not necessarily read what is written which makes it | |
| 35 // difficult to de-dup. Working with the binary format is always exact and | |
| 36 // the system libraries will properly ignore duplicate ACL entries. | |
| 37 bool AddAclToPath(const base::FilePath& path, | |
| 38 const CSid& trustee, | |
| 39 ACCESS_MASK access_mask, | |
| 40 BYTE ace_flags) { | |
| 41 DCHECK(!path.empty()); | |
| 42 DCHECK(trustee); | |
| 43 | |
| 44 // Get the existing DACL. | |
| 45 ATL::CDacl dacl; | |
| 46 if (!ATL::AtlGetDacl(path.value().c_str(), SE_FILE_OBJECT, &dacl)) { | |
| 47 DPLOG(ERROR) << "Failed getting DACL for path \"" << path.value() << "\""; | |
| 48 return false; | |
| 49 } | |
| 50 | |
| 51 // Check if the requested access already exists and return if so. | |
| 52 for (UINT i = 0; i < dacl.GetAceCount(); ++i) { | |
| 53 ATL::CSid sid; | |
| 54 ACCESS_MASK mask = 0; | |
| 55 BYTE type = 0; | |
| 56 BYTE flags = 0; | |
| 57 dacl.GetAclEntry(i, &sid, &mask, &type, &flags); | |
| 58 if (sid == trustee && type == ACCESS_ALLOWED_ACE_TYPE && | |
| 59 (flags & ace_flags) == ace_flags && | |
| 60 (mask & access_mask) == access_mask) { | |
| 61 return true; | |
| 62 } | |
| 63 } | |
| 64 | |
| 65 // Add the new access to the DACL. | |
| 66 if (!dacl.AddAllowedAce(trustee, access_mask, ace_flags)) { | |
| 67 DPLOG(ERROR) << "Failed adding ACE to DACL"; | |
| 68 return false; | |
| 69 } | |
| 70 | |
| 71 // Attach the updated ACL as the object's DACL. | |
| 72 if (!ATL::AtlSetDacl(path.value().c_str(), SE_FILE_OBJECT, dacl)) { | |
| 73 DPLOG(ERROR) << "Failed setting DACL for path \"" << path.value() << "\""; | |
| 74 return false; | |
| 75 } | |
| 76 | |
| 77 return true; | |
| 78 } | |
| 79 | |
| 80 } // namespace | |
| 81 | |
| 82 base::FilePath GetPersistentHistogramStorageDir( | |
| 83 const base::FilePath& target_path) { | |
| 84 return target_path.AppendASCII(kSetupHistogramAllocatorName); | |
| 85 } | |
| 86 | |
| 87 void BeginPersistentHistogramStorage() { | |
| 88 base::GlobalHistogramAllocator::CreateWithLocalMemory( | 22 base::GlobalHistogramAllocator::CreateWithLocalMemory( |
| 89 1 << 20, // 1 MiB | 23 1 << 20, // 1 MiB |
| 90 0, // No identifier. | 24 0, // No identifier. |
| 91 installer::kSetupHistogramAllocatorName); | 25 installer::kSetupHistogramAllocatorName); |
|
grt (UTC plus 2)
2016/09/13 19:42:59
nit: remove "installer::"
fdoray
2016/09/13 20:18:25
Done.
| |
| 92 base::GlobalHistogramAllocator::Get()->CreateTrackingHistograms( | 26 base::GlobalHistogramAllocator::Get()->CreateTrackingHistograms( |
| 93 kSetupHistogramAllocatorName); | 27 kSetupHistogramAllocatorName); |
| 94 | 28 |
| 95 // This can't be enabled until after the allocator is configured because | 29 // This can't be enabled until after the allocator is configured because there |
| 96 // there is no other reporting out of setup other than persistent memory. | 30 // is no other reporting out of setup other than persistent memory. |
| 97 base::HistogramBase::EnableActivityReportHistogram("setup"); | 31 base::HistogramBase::EnableActivityReportHistogram("setup"); |
| 98 } | 32 } |
| 99 | 33 |
| 100 void EndPersistentHistogramStorage(const base::FilePath& target_path, | 34 PersistentHistogramStorage::~PersistentHistogramStorage() { |
| 101 bool system_install) { | |
| 102 base::PersistentHistogramAllocator* allocator = | 35 base::PersistentHistogramAllocator* allocator = |
| 103 base::GlobalHistogramAllocator::Get(); | 36 base::GlobalHistogramAllocator::Get(); |
| 104 allocator->UpdateTrackingHistograms(); | 37 allocator->UpdateTrackingHistograms(); |
| 105 | 38 |
| 106 // Allocator dumps are saved to a directory that was created earlier. Stop | 39 // Stop if |storage_dir_| isn't set or does not exist. That can happen if the |
| 107 // now if that directory has been removed because an uninstall has happened. | 40 // product hasn't been installed yet or if it has been uninstalled. |
| 108 base::FilePath dir_path = GetPersistentHistogramStorageDir(target_path); | 41 if (storage_dir_.empty() || !base::DirectoryExists(storage_dir_)) |
| 109 if (!base::DirectoryExists(dir_path)) | |
| 110 return; | 42 return; |
| 111 | 43 |
| 112 // Set permissions on the directory that allows other processes, including | |
| 113 // non-privileged ones, to read and delete the files stored there. This | |
| 114 // allows the browser process to remove the metrics files once it's done | |
| 115 // reading them. This is only done for system-level installs; user-level | |
| 116 // installs already provide delete-file access to the browser process. | |
| 117 if (system_install) { | |
| 118 if (!AddAclToPath(dir_path, ATL::Sids::AuthenticatedUser(), | |
| 119 FILE_GENERIC_READ | FILE_DELETE_CHILD, | |
| 120 CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE)) { | |
| 121 PLOG(ERROR) << "Could not set \"delete\" permission for metrics directory" | |
| 122 << " \"" << dir_path.value() << "\""; | |
| 123 } | |
| 124 } | |
| 125 | |
| 126 // Remove any existing metrics file at the old (non-subdir) pathname. | |
| 127 base::DeleteFile(dir_path.AddExtension(MetricsFileExtension), false); | |
| 128 | |
| 129 // Save data using the current time as the filename. The actual filename | 44 // Save data using the current time as the filename. The actual filename |
| 130 // doesn't matter (so long as it ends with the correct extension) but this | 45 // doesn't matter (so long as it ends with the correct extension) but this |
| 131 // works as well as anything. | 46 // works as well as anything. |
| 132 base::Time::Exploded exploded; | 47 base::Time::Exploded exploded; |
| 133 base::Time::Now().LocalExplode(&exploded); | 48 base::Time::Now().LocalExplode(&exploded); |
| 134 base::FilePath file_path = | 49 const base::FilePath file_path = |
| 135 dir_path | 50 storage_dir_ |
| 136 .AppendASCII(base::StringPrintf("%04d%02d%02d%02d%02d%02d", | 51 .AppendASCII(base::StringPrintf("%04d%02d%02d%02d%02d%02d", |
| 137 exploded.year, exploded.month, | 52 exploded.year, exploded.month, |
| 138 exploded.day_of_month, exploded.hour, | 53 exploded.day_of_month, exploded.hour, |
| 139 exploded.minute, exploded.second)) | 54 exploded.minute, exploded.second)) |
| 140 .AddExtension(MetricsFileExtension); | 55 .AddExtension(base::PersistentMemoryAllocator::kFileExtension); |
| 141 | 56 |
| 142 base::StringPiece contents(static_cast<const char*>(allocator->data()), | 57 base::StringPiece contents(static_cast<const char*>(allocator->data()), |
| 143 allocator->used()); | 58 allocator->used()); |
| 144 if (base::ImportantFileWriter::WriteFileAtomically(file_path, contents)) | 59 if (base::ImportantFileWriter::WriteFileAtomically(file_path, contents)) |
| 145 VLOG(1) << "Persistent histograms saved in file: " << file_path.value(); | 60 VLOG(1) << "Persistent histograms saved in file: " << file_path.value(); |
| 146 } | 61 } |
| 147 | 62 |
| 63 base::FilePath PersistentHistogramStorage::GetStorageDir( | |
|
grt (UTC plus 2)
2016/09/13 19:42:59
nit:
// static
before this
fdoray
2016/09/13 20:18:25
Done.
| |
| 64 const base::FilePath& target_path) { | |
| 65 return target_path.AppendASCII(kSetupHistogramAllocatorName); | |
| 66 } | |
| 67 | |
| 148 } // namespace installer | 68 } // namespace installer |
| OLD | NEW |