OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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/extensions/installed_loader.h" | 5 #include "chrome/browser/extensions/installed_loader.h" |
6 | 6 |
7 #include "base/files/file_path.h" | 7 #include "base/files/file_path.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/strings/stringprintf.h" | 9 #include "base/strings/stringprintf.h" |
10 #include "base/strings/utf_string_conversions.h" | 10 #include "base/strings/utf_string_conversions.h" |
(...skipping 27 matching lines...) Expand all Loading... |
38 using base::UserMetricsAction; | 38 using base::UserMetricsAction; |
39 using content::BrowserThread; | 39 using content::BrowserThread; |
40 | 40 |
41 namespace extensions { | 41 namespace extensions { |
42 | 42 |
43 namespace errors = manifest_errors; | 43 namespace errors = manifest_errors; |
44 | 44 |
45 namespace { | 45 namespace { |
46 | 46 |
47 // The following enumeration is used in histograms matching | 47 // The following enumeration is used in histograms matching |
48 // Extensions.ManifestReload* . Values may be added, as long as existing | 48 // Extensions.ManifestReload*. |
49 // values are not changed. | |
50 enum ManifestReloadReason { | 49 enum ManifestReloadReason { |
51 NOT_NEEDED = 0, // Reload not needed. | 50 NOT_NEEDED = 0, // Reload not needed. |
52 UNPACKED_DIR, // Unpacked directory. | 51 UNPACKED_DIR, // Unpacked directory. |
53 NEEDS_RELOCALIZATION, // The locale has changed since we read this extension. | 52 NEEDS_RELOCALIZATION, // The locale has changed since we read this extension. |
54 CORRUPT_PREFERENCES, // The manifest in the preferences is corrupt. | 53 CORRUPT_PREFERENCES, // The manifest in the preferences is corrupt. |
| 54 |
| 55 // New enum values must go above here. |
55 NUM_MANIFEST_RELOAD_REASONS | 56 NUM_MANIFEST_RELOAD_REASONS |
56 }; | 57 }; |
57 | 58 |
58 // Used in histogram Extension.BackgroundPageType. Values may be added, as | 59 // Used in histogram Extension.BackgroundPageType. |
59 // long as existing values are not changed. | |
60 enum BackgroundPageType { | 60 enum BackgroundPageType { |
61 NO_BACKGROUND_PAGE = 0, | 61 NO_BACKGROUND_PAGE = 0, |
62 BACKGROUND_PAGE_PERSISTENT = 1, | 62 BACKGROUND_PAGE_PERSISTENT, |
63 EVENT_PAGE = 2, | 63 EVENT_PAGE, |
| 64 |
| 65 // New enum values must go above here. |
| 66 NUM_BACKGROUND_PAGE_TYPES |
64 }; | 67 }; |
65 | 68 |
66 // Used in histogram Extensions.ExternalItemState. Values may be added, as | 69 // Used in histogram Extensions.ExternalItemState. |
67 // long as existing values are not changed. | |
68 enum ExternalItemState { | 70 enum ExternalItemState { |
69 DEPRECATED_EXTERNAL_ITEM_DISABLED = 0, | 71 DEPRECATED_EXTERNAL_ITEM_DISABLED = 0, |
70 DEPRECATED_EXTERNAL_ITEM_ENABLED = 1, | 72 DEPRECATED_EXTERNAL_ITEM_ENABLED, |
71 EXTERNAL_ITEM_WEBSTORE_DISABLED = 2, | 73 EXTERNAL_ITEM_WEBSTORE_DISABLED, |
72 EXTERNAL_ITEM_WEBSTORE_ENABLED = 3, | 74 EXTERNAL_ITEM_WEBSTORE_ENABLED, |
73 EXTERNAL_ITEM_NONWEBSTORE_DISABLED = 4, | 75 EXTERNAL_ITEM_NONWEBSTORE_DISABLED, |
74 EXTERNAL_ITEM_NONWEBSTORE_ENABLED = 5, | 76 EXTERNAL_ITEM_NONWEBSTORE_ENABLED, |
75 EXTERNAL_ITEM_WEBSTORE_UNINSTALLED = 6, | 77 EXTERNAL_ITEM_WEBSTORE_UNINSTALLED, |
76 EXTERNAL_ITEM_NONWEBSTORE_UNINSTALLED = 7, | 78 EXTERNAL_ITEM_NONWEBSTORE_UNINSTALLED, |
77 EXTERNAL_ITEM_MAX_ITEMS = 8 | 79 |
| 80 // New enum values must go above here. |
| 81 EXTERNAL_ITEM_MAX_ITEMS |
78 }; | 82 }; |
79 | 83 |
80 bool IsManifestCorrupt(const base::DictionaryValue* manifest) { | 84 bool IsManifestCorrupt(const base::DictionaryValue* manifest) { |
81 if (!manifest) | 85 if (!manifest) |
82 return false; | 86 return false; |
83 | 87 |
84 // Because of bug #272524 sometimes manifests got mangled in the preferences | 88 // Because of bug #272524 sometimes manifests got mangled in the preferences |
85 // file, one particularly bad case resulting in having both a background page | 89 // file, one particularly bad case resulting in having both a background page |
86 // and background scripts values. In those situations we want to reload the | 90 // and background scripts values. In those situations we want to reload the |
87 // manifest from the extension to fix this. | 91 // manifest from the extension to fix this. |
(...skipping 65 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
153 error = errors::kManifestUnreadable; | 157 error = errors::kManifestUnreadable; |
154 } | 158 } |
155 | 159 |
156 // Once installed, non-unpacked extensions cannot change their IDs (e.g., by | 160 // Once installed, non-unpacked extensions cannot change their IDs (e.g., by |
157 // updating the 'key' field in their manifest). | 161 // updating the 'key' field in their manifest). |
158 // TODO(jstritar): migrate preferences when unpacked extensions change IDs. | 162 // TODO(jstritar): migrate preferences when unpacked extensions change IDs. |
159 if (extension.get() && !Manifest::IsUnpackedLocation(extension->location()) && | 163 if (extension.get() && !Manifest::IsUnpackedLocation(extension->location()) && |
160 info.extension_id != extension->id()) { | 164 info.extension_id != extension->id()) { |
161 error = errors::kCannotChangeExtensionID; | 165 error = errors::kCannotChangeExtensionID; |
162 extension = NULL; | 166 extension = NULL; |
163 content::RecordAction(UserMetricsAction("Extensions.IDChangedError")); | |
164 } | 167 } |
165 | 168 |
166 // Check policy on every load in case an extension was blacklisted while | 169 // Check policy on every load in case an extension was blacklisted while |
167 // Chrome was not running. | 170 // Chrome was not running. |
168 const ManagementPolicy* policy = extensions::ExtensionSystem::Get( | 171 const ManagementPolicy* policy = extensions::ExtensionSystem::Get( |
169 extension_service_->profile())->management_policy(); | 172 extension_service_->profile())->management_policy(); |
170 if (extension.get()) { | 173 if (extension.get()) { |
171 Extension::DisableReason disable_reason = Extension::DISABLE_NONE; | 174 Extension::DisableReason disable_reason = Extension::DISABLE_NONE; |
172 bool force_disabled = false; | 175 bool force_disabled = false; |
173 if (!policy->UserMayLoad(extension.get(), NULL)) { | 176 if (!policy->UserMayLoad(extension.get(), NULL)) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
215 for (size_t i = 0; i < extensions_info->size(); ++i) { | 218 for (size_t i = 0; i < extensions_info->size(); ++i) { |
216 ExtensionInfo* info = extensions_info->at(i).get(); | 219 ExtensionInfo* info = extensions_info->at(i).get(); |
217 | 220 |
218 // Skip extensions that were loaded from the command-line because we don't | 221 // Skip extensions that were loaded from the command-line because we don't |
219 // want those to persist across browser restart. | 222 // want those to persist across browser restart. |
220 if (info->extension_location == Manifest::COMMAND_LINE) | 223 if (info->extension_location == Manifest::COMMAND_LINE) |
221 continue; | 224 continue; |
222 | 225 |
223 ManifestReloadReason reload_reason = ShouldReloadExtensionManifest(*info); | 226 ManifestReloadReason reload_reason = ShouldReloadExtensionManifest(*info); |
224 ++reload_reason_counts[reload_reason]; | 227 ++reload_reason_counts[reload_reason]; |
225 UMA_HISTOGRAM_ENUMERATION("Extensions.ManifestReloadEnumValue", | |
226 reload_reason, 100); | |
227 | 228 |
228 if (reload_reason != NOT_NEEDED) { | 229 if (reload_reason != NOT_NEEDED) { |
229 // Reloading an extension reads files from disk. We do this on the | 230 // Reloading an extension reads files from disk. We do this on the |
230 // UI thread because reloads should be very rare, and the complexity | 231 // UI thread because reloads should be very rare, and the complexity |
231 // added by delaying the time when the extensions service knows about | 232 // added by delaying the time when the extensions service knows about |
232 // all extensions is significant. See crbug.com/37548 for details. | 233 // all extensions is significant. See crbug.com/37548 for details. |
233 // |allow_io| disables tests that file operations run on the file | 234 // |allow_io| disables tests that file operations run on the file |
234 // thread. | 235 // thread. |
235 base::ThreadRestrictions::ScopedAllowIO allow_io; | 236 base::ThreadRestrictions::ScopedAllowIO allow_io; |
236 | 237 |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
287 int legacy_packaged_app_count = 0; | 288 int legacy_packaged_app_count = 0; |
288 int platform_app_count = 0; | 289 int platform_app_count = 0; |
289 int user_script_count = 0; | 290 int user_script_count = 0; |
290 int content_pack_count = 0; | 291 int content_pack_count = 0; |
291 int extension_user_count = 0; | 292 int extension_user_count = 0; |
292 int extension_external_count = 0; | 293 int extension_external_count = 0; |
293 int theme_count = 0; | 294 int theme_count = 0; |
294 int page_action_count = 0; | 295 int page_action_count = 0; |
295 int browser_action_count = 0; | 296 int browser_action_count = 0; |
296 int disabled_for_permissions_count = 0; | 297 int disabled_for_permissions_count = 0; |
297 int item_user_count = 0; | |
298 int non_webstore_ntp_override_count = 0; | 298 int non_webstore_ntp_override_count = 0; |
299 int incognito = 0; | 299 int incognito = 0; |
300 int not_incognito = 0; | 300 int not_incognito = 0; |
301 int file_access = 0; | 301 int file_access = 0; |
302 int not_file_access = 0; | 302 int not_file_access = 0; |
303 | 303 |
304 const ExtensionSet& extensions = extension_registry_->enabled_extensions(); | 304 const ExtensionSet& extensions = extension_registry_->enabled_extensions(); |
305 ExtensionActionManager* extension_action_manager = | 305 ExtensionActionManager* extension_action_manager = |
306 ExtensionActionManager::Get(profile); | 306 ExtensionActionManager::Get(profile); |
307 for (ExtensionSet::const_iterator iter = extensions.begin(); | 307 for (ExtensionSet::const_iterator iter = extensions.begin(); |
308 iter != extensions.end(); | 308 iter != extensions.end(); |
309 ++iter) { | 309 ++iter) { |
310 const Extension* extension = *iter; | 310 const Extension* extension = *iter; |
311 Manifest::Location location = extension->location(); | 311 Manifest::Location location = extension->location(); |
312 Manifest::Type type = extension->GetType(); | 312 Manifest::Type type = extension->GetType(); |
313 | 313 |
314 // For the first few metrics, include all extensions and apps (component, | 314 // For the first few metrics, include all extensions and apps (component, |
315 // unpacked, etc). It's good to know these locations, and it doesn't | 315 // unpacked, etc). It's good to know these locations, and it doesn't |
316 // muck up any of the stats. Later, though, we want to omit component and | 316 // muck up any of the stats. Later, though, we want to omit component and |
317 // unpacked, as they are less interesting. | 317 // unpacked, as they are less interesting. |
318 if (extension->is_app()) | 318 if (extension->is_app()) |
319 UMA_HISTOGRAM_ENUMERATION("Extensions.AppLocation", location, 100); | 319 UMA_HISTOGRAM_ENUMERATION( |
| 320 "Extensions.AppLocation", location, Manifest::NUM_LOCATIONS); |
320 else if (extension->is_extension()) | 321 else if (extension->is_extension()) |
321 UMA_HISTOGRAM_ENUMERATION("Extensions.ExtensionLocation", location, 100); | 322 UMA_HISTOGRAM_ENUMERATION( |
| 323 "Extensions.ExtensionLocation", location, Manifest::NUM_LOCATIONS); |
322 | 324 |
323 if (!ManifestURL::UpdatesFromGallery(extension)) { | 325 if (!ManifestURL::UpdatesFromGallery(extension)) { |
324 UMA_HISTOGRAM_ENUMERATION( | 326 UMA_HISTOGRAM_ENUMERATION( |
325 "Extensions.NonWebstoreLocation", location, 100); | 327 "Extensions.NonWebstoreLocation", location, Manifest::NUM_LOCATIONS); |
326 | 328 |
327 // Check for inconsistencies if the extension was supposedly installed | 329 // Check for inconsistencies if the extension was supposedly installed |
328 // from the webstore. | 330 // from the webstore. |
329 enum { | 331 enum { |
330 BAD_UPDATE_URL = 0, | 332 BAD_UPDATE_URL = 0, |
331 // This value was a mistake. Turns out sideloaded extensions can | 333 // This value was a mistake. Turns out sideloaded extensions can |
332 // have the from_webstore bit if they update from the webstore. | 334 // have the from_webstore bit if they update from the webstore. |
333 DEPRECATED_IS_EXTERNAL = 1, | 335 DEPRECATED_IS_EXTERNAL = 1, |
334 }; | 336 }; |
335 if (extension->from_webstore()) { | 337 if (extension->from_webstore()) { |
(...skipping 27 matching lines...) Expand all Loading... |
363 URLOverrides::GetChromeURLOverrides(extension).count("newtab")) { | 365 URLOverrides::GetChromeURLOverrides(extension).count("newtab")) { |
364 ++non_webstore_ntp_override_count; | 366 ++non_webstore_ntp_override_count; |
365 } | 367 } |
366 | 368 |
367 // Don't count unpacked extensions anymore, either. | 369 // Don't count unpacked extensions anymore, either. |
368 if (Manifest::IsUnpackedLocation(location)) | 370 if (Manifest::IsUnpackedLocation(location)) |
369 continue; | 371 continue; |
370 | 372 |
371 UMA_HISTOGRAM_ENUMERATION("Extensions.ManifestVersion", | 373 UMA_HISTOGRAM_ENUMERATION("Extensions.ManifestVersion", |
372 extension->manifest_version(), | 374 extension->manifest_version(), |
373 10); | 375 10); // TODO(kalman): Why 10 manifest versions? |
374 | 376 |
375 // We might have wanted to count legacy packaged apps here, too, since they | 377 // We might have wanted to count legacy packaged apps here, too, since they |
376 // are effectively extensions. Unfortunately, it's too late, as we don't | 378 // are effectively extensions. Unfortunately, it's too late, as we don't |
377 // want to mess up the existing stats. | 379 // want to mess up the existing stats. |
378 if (type == Manifest::TYPE_EXTENSION) { | 380 if (type == Manifest::TYPE_EXTENSION) { |
379 UMA_HISTOGRAM_ENUMERATION("Extensions.BackgroundPageType", | 381 UMA_HISTOGRAM_ENUMERATION("Extensions.BackgroundPageType", |
380 GetBackgroundPageType(extension), | 382 GetBackgroundPageType(extension), |
381 10); | 383 NUM_BACKGROUND_PAGE_TYPES); |
382 } | 384 } |
383 | 385 |
384 // Using an enumeration shows us the total installed ratio across all users. | 386 // Using an enumeration shows us the total installed ratio across all users. |
385 // Using the totals per user at each startup tells us the distribution of | 387 // Using the totals per user at each startup tells us the distribution of |
386 // usage for each user (e.g. 40% of users have at least one app installed). | 388 // usage for each user (e.g. 40% of users have at least one app installed). |
387 UMA_HISTOGRAM_ENUMERATION("Extensions.LoadType", type, 100); | 389 UMA_HISTOGRAM_ENUMERATION( |
| 390 "Extensions.LoadType", type, Manifest::NUM_LOAD_TYPES); |
388 switch (type) { | 391 switch (type) { |
389 case Manifest::TYPE_THEME: | 392 case Manifest::TYPE_THEME: |
390 ++theme_count; | 393 ++theme_count; |
391 break; | 394 break; |
392 case Manifest::TYPE_USER_SCRIPT: | 395 case Manifest::TYPE_USER_SCRIPT: |
393 ++user_script_count; | 396 ++user_script_count; |
394 break; | 397 break; |
395 case Manifest::TYPE_HOSTED_APP: | 398 case Manifest::TYPE_HOSTED_APP: |
396 ++hosted_app_count; | 399 ++hosted_app_count; |
397 if (Manifest::IsExternalLocation(location)) { | 400 if (Manifest::IsExternalLocation(location)) { |
(...skipping 20 matching lines...) Expand all Loading... |
418 break; | 421 break; |
419 case Manifest::TYPE_EXTENSION: | 422 case Manifest::TYPE_EXTENSION: |
420 default: | 423 default: |
421 if (Manifest::IsExternalLocation(location)) { | 424 if (Manifest::IsExternalLocation(location)) { |
422 ++extension_external_count; | 425 ++extension_external_count; |
423 } else { | 426 } else { |
424 ++extension_user_count; | 427 ++extension_user_count; |
425 } | 428 } |
426 break; | 429 break; |
427 } | 430 } |
428 if (!Manifest::IsExternalLocation(location)) | |
429 ++item_user_count; | |
430 | 431 |
431 if (extension_action_manager->GetPageAction(*extension)) | 432 if (extension_action_manager->GetPageAction(*extension)) |
432 ++page_action_count; | 433 ++page_action_count; |
433 | 434 |
434 if (extension_action_manager->GetBrowserAction(*extension)) | 435 if (extension_action_manager->GetBrowserAction(*extension)) |
435 ++browser_action_count; | 436 ++browser_action_count; |
436 | 437 |
437 if (ManagedModeInfo::IsContentPack(extension)) | 438 if (ManagedModeInfo::IsContentPack(extension)) |
438 ++content_pack_count; | 439 ++content_pack_count; |
439 | 440 |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
495 EXTERNAL_ITEM_WEBSTORE_UNINSTALLED, | 496 EXTERNAL_ITEM_WEBSTORE_UNINSTALLED, |
496 EXTERNAL_ITEM_MAX_ITEMS); | 497 EXTERNAL_ITEM_MAX_ITEMS); |
497 } else { | 498 } else { |
498 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState", | 499 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState", |
499 EXTERNAL_ITEM_NONWEBSTORE_UNINSTALLED, | 500 EXTERNAL_ITEM_NONWEBSTORE_UNINSTALLED, |
500 EXTERNAL_ITEM_MAX_ITEMS); | 501 EXTERNAL_ITEM_MAX_ITEMS); |
501 } | 502 } |
502 } | 503 } |
503 } | 504 } |
504 | 505 |
505 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAllUser", item_user_count); | |
506 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadApp", | 506 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadApp", |
507 app_user_count + app_external_count); | 507 app_user_count + app_external_count); |
508 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAppUser", app_user_count); | 508 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAppUser", app_user_count); |
509 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAppExternal", app_external_count); | 509 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAppExternal", app_external_count); |
510 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadHostedApp", hosted_app_count); | 510 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadHostedApp", hosted_app_count); |
511 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPackagedApp", | 511 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPackagedApp", |
512 legacy_packaged_app_count); | 512 legacy_packaged_app_count); |
513 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPlatformApp", platform_app_count); | 513 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPlatformApp", platform_app_count); |
514 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtension", | 514 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtension", |
515 extension_user_count + extension_external_count); | 515 extension_user_count + extension_external_count); |
(...skipping 20 matching lines...) Expand all Loading... |
536 int InstalledLoader::GetCreationFlags(const ExtensionInfo* info) { | 536 int InstalledLoader::GetCreationFlags(const ExtensionInfo* info) { |
537 int flags = extension_prefs_->GetCreationFlags(info->extension_id); | 537 int flags = extension_prefs_->GetCreationFlags(info->extension_id); |
538 if (!Manifest::IsUnpackedLocation(info->extension_location)) | 538 if (!Manifest::IsUnpackedLocation(info->extension_location)) |
539 flags |= Extension::REQUIRE_KEY; | 539 flags |= Extension::REQUIRE_KEY; |
540 if (extension_prefs_->AllowFileAccess(info->extension_id)) | 540 if (extension_prefs_->AllowFileAccess(info->extension_id)) |
541 flags |= Extension::ALLOW_FILE_ACCESS; | 541 flags |= Extension::ALLOW_FILE_ACCESS; |
542 return flags; | 542 return flags; |
543 } | 543 } |
544 | 544 |
545 } // namespace extensions | 545 } // namespace extensions |
OLD | NEW |