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 "chrome/browser/metrics/extensions_metrics_provider.h" | 5 #include "chrome/browser/metrics/extensions_metrics_provider.h" |
6 | 6 |
7 #include <set> | 7 #include <set> |
8 | 8 |
9 #include "base/logging.h" | 9 #include "base/logging.h" |
10 #include "base/memory/scoped_ptr.h" | 10 #include "base/memory/scoped_ptr.h" |
11 #include "base/strings/stringprintf.h" | 11 #include "base/strings/stringprintf.h" |
12 #include "chrome/browser/browser_process.h" | 12 #include "chrome/browser/browser_process.h" |
13 #include "chrome/browser/extensions/install_verifier.h" | |
13 #include "chrome/browser/profiles/profile_manager.h" | 14 #include "chrome/browser/profiles/profile_manager.h" |
14 #include "components/metrics/metrics_log.h" | 15 #include "components/metrics/metrics_log.h" |
15 #include "components/metrics/metrics_state_manager.h" | 16 #include "components/metrics/metrics_state_manager.h" |
16 #include "components/metrics/proto/system_profile.pb.h" | 17 #include "components/metrics/proto/system_profile.pb.h" |
17 #include "extensions/browser/extension_registry.h" | 18 #include "extensions/browser/extension_registry.h" |
19 #include "extensions/browser/extension_system.h" | |
18 #include "extensions/common/extension_set.h" | 20 #include "extensions/common/extension_set.h" |
19 #include "third_party/smhasher/src/City.h" | 21 #include "third_party/smhasher/src/City.h" |
20 | 22 |
21 namespace { | 23 namespace { |
22 | 24 |
23 // The number of possible hash keys that a client may use. The UMA client_id | 25 // The number of possible hash keys that a client may use. The UMA client_id |
24 // value is reduced modulo this value to produce the key used by that | 26 // value is reduced modulo this value to produce the key used by that |
25 // particular client. | 27 // particular client. |
26 const size_t kExtensionListClientKeys = 4096; | 28 const size_t kExtensionListClientKeys = 4096; |
27 | 29 |
28 // The number of hash buckets into which extension IDs are mapped. This sets | 30 // The number of hash buckets into which extension IDs are mapped. This sets |
29 // the possible output range of the HashExtension function. | 31 // the possible output range of the HashExtension function. |
30 const size_t kExtensionListBuckets = 1024; | 32 const size_t kExtensionListBuckets = 1024; |
31 | 33 |
34 bool IsOffStoreExtension(const extensions::Extension& extension, | |
Alexei Svitkine (slow)
2014/08/11 15:01:57
Add a comment.
jwd
2014/08/11 20:06:27
Done.
| |
35 const extensions::InstallVerifier& verifier) { | |
36 if (!extension.is_extension() && !extension.is_legacy_packaged_app()) | |
37 return false; | |
38 | |
39 // Component extensions are considered safe. | |
40 if (extension.location() == extensions::Manifest::COMPONENT || | |
41 extension.location() == extensions::Manifest::EXTERNAL_COMPONENT) | |
Alexei Svitkine (slow)
2014/08/11 15:01:57
Nit: {}'s
jwd
2014/08/11 20:06:27
Done.
| |
42 return false; | |
43 | |
44 // TODO(jwd): add whitelist | |
45 | |
46 if (!extensions::InstallVerifier::FromStore(extension)) | |
47 return true; | |
48 | |
49 // Local information about the extension implies it is from the store. We try | |
50 // to use the install verifier to vereify this. | |
51 return verifier.IsInvalid(extension.id()); | |
52 } | |
53 | |
54 bool CheckForOffStore(const extensions::ExtensionSet& extensions, | |
55 const extensions::InstallVerifier& verifier) { | |
56 for (extensions::ExtensionSet::const_iterator it = extensions.begin(); | |
57 it != extensions.end(); | |
58 ++it) { | |
59 if (IsOffStoreExtension(**it, verifier)) | |
60 return true; | |
61 } | |
62 return false; | |
63 } | |
64 | |
32 } // namespace | 65 } // namespace |
33 | 66 |
34 ExtensionsMetricsProvider::ExtensionsMetricsProvider( | 67 ExtensionsMetricsProvider::ExtensionsMetricsProvider( |
35 metrics::MetricsStateManager* metrics_state_manager) | 68 metrics::MetricsStateManager* metrics_state_manager) |
36 : metrics_state_manager_(metrics_state_manager), cached_profile_(NULL) { | 69 : metrics_state_manager_(metrics_state_manager), cached_profile_(NULL) { |
37 DCHECK(metrics_state_manager_); | 70 DCHECK(metrics_state_manager_); |
38 } | 71 } |
39 | 72 |
40 ExtensionsMetricsProvider::~ExtensionsMetricsProvider() { | 73 ExtensionsMetricsProvider::~ExtensionsMetricsProvider() { |
41 } | 74 } |
(...skipping 25 matching lines...) Expand all Loading... | |
67 cached_profile_ = profile_manager->GetProfileByPath( | 100 cached_profile_ = profile_manager->GetProfileByPath( |
68 profile_manager->GetLastUsedProfileDir(profile_manager->user_data_dir())); | 101 profile_manager->GetLastUsedProfileDir(profile_manager->user_data_dir())); |
69 if (cached_profile_) { | 102 if (cached_profile_) { |
70 // Ensure that the returned profile is not an incognito profile. | 103 // Ensure that the returned profile is not an incognito profile. |
71 cached_profile_ = cached_profile_->GetOriginalProfile(); | 104 cached_profile_ = cached_profile_->GetOriginalProfile(); |
72 } | 105 } |
73 return cached_profile_; | 106 return cached_profile_; |
74 } | 107 } |
75 | 108 |
76 scoped_ptr<extensions::ExtensionSet> | 109 scoped_ptr<extensions::ExtensionSet> |
77 ExtensionsMetricsProvider::GetInstalledExtensions() { | 110 ExtensionsMetricsProvider::GetInstalledExtensions(Profile* profile) { |
78 #if defined(ENABLE_EXTENSIONS) | 111 #if defined(ENABLE_EXTENSIONS) |
79 // UMA reports do not support multiple profiles, but extensions are installed | |
80 // per-profile. We return the extensions installed in the primary profile. | |
81 // In the future, we might consider reporting data about extensions in all | |
82 // profiles. | |
83 Profile* profile = GetMetricsProfile(); | |
84 if (profile) { | 112 if (profile) { |
85 return extensions::ExtensionRegistry::Get(profile) | 113 return extensions::ExtensionRegistry::Get(profile) |
86 ->GenerateInstalledExtensionsSet(); | 114 ->GenerateInstalledExtensionsSet(); |
87 } | 115 } |
88 #endif // defined(ENABLE_EXTENSIONS) | 116 #endif // defined(ENABLE_EXTENSIONS) |
89 return scoped_ptr<extensions::ExtensionSet>(); | 117 return scoped_ptr<extensions::ExtensionSet>(); |
90 } | 118 } |
91 | 119 |
92 uint64 ExtensionsMetricsProvider::GetClientID() { | 120 uint64 ExtensionsMetricsProvider::GetClientID() { |
93 // TODO(blundell): Create a MetricsLog::ClientIDAsInt() API and call it | 121 // TODO(blundell): Create a MetricsLog::ClientIDAsInt() API and call it |
94 // here as well as in MetricsLog's population of the client_id field of | 122 // here as well as in MetricsLog's population of the client_id field of |
95 // the uma_proto. | 123 // the uma_proto. |
96 return MetricsLog::Hash(metrics_state_manager_->client_id()); | 124 return MetricsLog::Hash(metrics_state_manager_->client_id()); |
97 } | 125 } |
98 | 126 |
99 void ExtensionsMetricsProvider::ProvideSystemProfileMetrics( | 127 void ExtensionsMetricsProvider::ProvideSystemProfileMetrics( |
100 metrics::SystemProfileProto* system_profile) { | 128 metrics::SystemProfileProto* system_profile) { |
101 scoped_ptr<extensions::ExtensionSet> extensions(GetInstalledExtensions()); | 129 ProvideOffStoreMetric(system_profile); |
130 ProvideOccupiedBucketMetric(system_profile); | |
131 } | |
132 | |
133 void ExtensionsMetricsProvider::ProvideOffStoreMetric( | |
134 metrics::SystemProfileProto* system_profile) { | |
135 ProfileManager* profile_manager = g_browser_process->profile_manager(); | |
136 if (!profile_manager) | |
137 return; | |
138 | |
139 bool hasOffStore = false; | |
140 | |
141 std::vector<Profile*> profiles = profile_manager->GetLoadedProfiles(); | |
142 for (std::vector<Profile*>::const_iterator it = profiles.begin(); | |
143 it != profiles.end(); | |
144 ++it) { | |
145 extensions::InstallVerifier* verifier = | |
146 extensions::ExtensionSystem::Get(*it)->install_verifier(); | |
147 | |
148 scoped_ptr<extensions::ExtensionSet> extensions( | |
149 GetInstalledExtensions(*it)); | |
150 | |
151 hasOffStore = hasOffStore || CheckForOffStore(*extensions.get(), *verifier); | |
Alexei Svitkine (slow)
2014/08/11 15:01:57
Nit: hacker_style please
jwd
2014/08/11 20:06:27
Done.
| |
152 } | |
153 | |
154 system_profile->set_has_offstore_extensions(hasOffStore); | |
155 } | |
156 | |
157 void ExtensionsMetricsProvider::ProvideOccupiedBucketMetric( | |
158 metrics::SystemProfileProto* system_profile) { | |
159 // UMA reports do not support multiple profiles, but extensions are installed | |
160 // per-profile. We return the extensions installed in the primary profile. | |
161 // In the future, we might consider reporting data about extensions in all | |
162 // profiles. | |
163 Profile* profile = GetMetricsProfile(); | |
164 | |
165 scoped_ptr<extensions::ExtensionSet> extensions( | |
166 GetInstalledExtensions(profile)); | |
102 if (!extensions) | 167 if (!extensions) |
103 return; | 168 return; |
104 | 169 |
105 const int client_key = GetClientID() % kExtensionListClientKeys; | 170 const int client_key = GetClientID() % kExtensionListClientKeys; |
106 | 171 |
107 std::set<int> buckets; | 172 std::set<int> buckets; |
108 for (extensions::ExtensionSet::const_iterator it = extensions->begin(); | 173 for (extensions::ExtensionSet::const_iterator it = extensions->begin(); |
109 it != extensions->end(); | 174 it != extensions->end(); |
110 ++it) { | 175 ++it) { |
111 buckets.insert(HashExtension((*it)->id(), client_key)); | 176 buckets.insert(HashExtension((*it)->id(), client_key)); |
112 } | 177 } |
113 | 178 |
114 for (std::set<int>::const_iterator it = buckets.begin(); it != buckets.end(); | 179 for (std::set<int>::const_iterator it = buckets.begin(); it != buckets.end(); |
115 ++it) { | 180 ++it) { |
116 system_profile->add_occupied_extension_bucket(*it); | 181 system_profile->add_occupied_extension_bucket(*it); |
117 } | 182 } |
118 } | 183 } |
OLD | NEW |