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
3 // found in the LICENSE file.
5 #include "chrome/browser/extensions/installed_loader.h"
7 #include "base/files/file_path.h"
8 #include "base/metrics/histogram_macros.h"
9 #include "base/metrics/sparse_histogram.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "base/threading/thread_restrictions.h"
13 #include "base/trace_event/trace_event.h"
14 #include "base/values.h"
15 #include "chrome/browser/browser_process.h"
16 #include "chrome/browser/extensions/extension_action_manager.h"
17 #include "chrome/browser/extensions/extension_error_reporter.h"
18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/extensions/extension_util.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/extensions/chrome_manifest_url_handlers.h"
23 #include "components/crx_file/id_util.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/notification_service.h"
26 #include "content/public/browser/user_metrics.h"
27 #include "extensions/browser/event_router.h"
28 #include "extensions/browser/extension_prefs.h"
29 #include "extensions/browser/extension_registry.h"
30 #include "extensions/browser/extension_system.h"
31 #include "extensions/browser/management_policy.h"
32 #include "extensions/common/extension.h"
33 #include "extensions/common/extension_l10n_util.h"
34 #include "extensions/common/extension_set.h"
35 #include "extensions/common/extension_urls.h"
36 #include "extensions/common/file_util.h"
37 #include "extensions/common/manifest.h"
38 #include "extensions/common/manifest_constants.h"
39 #include "extensions/common/manifest_handlers/background_info.h"
40 #include "extensions/common/manifest_url_handlers.h"
42 using base::UserMetricsAction
;
43 using content::BrowserThread
;
45 namespace extensions
{
47 namespace errors
= manifest_errors
;
51 // The following enumeration is used in histograms matching
52 // Extensions.ManifestReload*.
53 enum ManifestReloadReason
{
54 NOT_NEEDED
= 0, // Reload not needed.
55 UNPACKED_DIR
, // Unpacked directory.
56 NEEDS_RELOCALIZATION
, // The locale has changed since we read this extension.
57 CORRUPT_PREFERENCES
, // The manifest in the preferences is corrupt.
59 // New enum values must go above here.
60 NUM_MANIFEST_RELOAD_REASONS
63 // Used in histogram Extension.BackgroundPageType.
64 enum BackgroundPageType
{
65 NO_BACKGROUND_PAGE
= 0,
66 BACKGROUND_PAGE_PERSISTENT
,
69 // New enum values must go above here.
70 NUM_BACKGROUND_PAGE_TYPES
73 // Used in histogram Extensions.ExternalItemState.
74 enum ExternalItemState
{
75 DEPRECATED_EXTERNAL_ITEM_DISABLED
= 0,
76 DEPRECATED_EXTERNAL_ITEM_ENABLED
,
77 EXTERNAL_ITEM_WEBSTORE_DISABLED
,
78 EXTERNAL_ITEM_WEBSTORE_ENABLED
,
79 EXTERNAL_ITEM_NONWEBSTORE_DISABLED
,
80 EXTERNAL_ITEM_NONWEBSTORE_ENABLED
,
81 EXTERNAL_ITEM_WEBSTORE_UNINSTALLED
,
82 EXTERNAL_ITEM_NONWEBSTORE_UNINSTALLED
,
84 // New enum values must go above here.
85 EXTERNAL_ITEM_MAX_ITEMS
88 bool IsManifestCorrupt(const base::DictionaryValue
* manifest
) {
92 // Because of bug #272524 sometimes manifests got mangled in the preferences
93 // file, one particularly bad case resulting in having both a background page
94 // and background scripts values. In those situations we want to reload the
95 // manifest from the extension to fix this.
96 const base::Value
* background_page
;
97 const base::Value
* background_scripts
;
98 return manifest
->Get(manifest_keys::kBackgroundPage
, &background_page
) &&
99 manifest
->Get(manifest_keys::kBackgroundScripts
, &background_scripts
);
102 ManifestReloadReason
ShouldReloadExtensionManifest(const ExtensionInfo
& info
) {
103 // Always reload manifests of unpacked extensions, because they can change
104 // on disk independent of the manifest in our prefs.
105 if (Manifest::IsUnpackedLocation(info
.extension_location
))
108 // Reload the manifest if it needs to be relocalized.
109 if (extension_l10n_util::ShouldRelocalizeManifest(
110 info
.extension_manifest
.get()))
111 return NEEDS_RELOCALIZATION
;
113 // Reload if the copy of the manifest in the preferences is corrupt.
114 if (IsManifestCorrupt(info
.extension_manifest
.get()))
115 return CORRUPT_PREFERENCES
;
120 BackgroundPageType
GetBackgroundPageType(const Extension
* extension
) {
121 if (!BackgroundInfo::HasBackgroundPage(extension
))
122 return NO_BACKGROUND_PAGE
;
123 if (BackgroundInfo::HasPersistentBackgroundPage(extension
))
124 return BACKGROUND_PAGE_PERSISTENT
;
128 // Records the creation flags of an extension grouped by
129 // Extension::InitFromValueFlags.
130 void RecordCreationFlags(const Extension
* extension
) {
131 for (int i
= 0; i
< Extension::kInitFromValueFlagBits
; ++i
) {
133 if (extension
->creation_flags() & flag
) {
134 UMA_HISTOGRAM_ENUMERATION(
135 "Extensions.LoadCreationFlags", i
, Extension::kInitFromValueFlagBits
);
140 // Helper to record a single disable reason histogram value (see
141 // RecordDisableReasons below).
142 void RecordDisbleReasonHistogram(int reason
) {
143 UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.DisableReason", reason
);
146 // Records the disable reasons for a single extension grouped by
147 // Extension::DisableReason.
148 void RecordDisableReasons(int reasons
) {
149 // |reasons| is a bitmask with values from Extension::DisabledReason
150 // which are increasing powers of 2.
151 if (reasons
== Extension::DISABLE_NONE
) {
152 RecordDisbleReasonHistogram(Extension::DISABLE_NONE
);
155 for (int reason
= 1; reason
< Extension::DISABLE_REASON_LAST
; reason
<<= 1) {
156 if (reasons
& reason
)
157 RecordDisbleReasonHistogram(reason
);
163 InstalledLoader::InstalledLoader(ExtensionService
* extension_service
)
164 : extension_service_(extension_service
),
165 extension_registry_(ExtensionRegistry::Get(extension_service
->profile())),
166 extension_prefs_(ExtensionPrefs::Get(extension_service
->profile())) {}
168 InstalledLoader::~InstalledLoader() {
171 void InstalledLoader::Load(const ExtensionInfo
& info
, bool write_to_prefs
) {
172 // TODO(asargent): add a test to confirm that we can't load extensions if
173 // their ID in preferences does not match the extension's actual ID.
174 if (invalid_extensions_
.find(info
.extension_path
) !=
175 invalid_extensions_
.end())
179 scoped_refptr
<const Extension
> extension(NULL
);
180 if (info
.extension_manifest
) {
181 extension
= Extension::Create(
183 info
.extension_location
,
184 *info
.extension_manifest
,
185 GetCreationFlags(&info
),
188 error
= errors::kManifestUnreadable
;
191 // Once installed, non-unpacked extensions cannot change their IDs (e.g., by
192 // updating the 'key' field in their manifest).
193 // TODO(jstritar): migrate preferences when unpacked extensions change IDs.
194 if (extension
.get() && !Manifest::IsUnpackedLocation(extension
->location()) &&
195 info
.extension_id
!= extension
->id()) {
196 error
= errors::kCannotChangeExtensionID
;
200 // Check policy on every load in case an extension was blacklisted while
201 // Chrome was not running.
202 const ManagementPolicy
* policy
= extensions::ExtensionSystem::Get(
203 extension_service_
->profile())->management_policy();
204 if (extension
.get()) {
205 Extension::DisableReason disable_reason
= Extension::DISABLE_NONE
;
206 bool force_disabled
= false;
207 if (!policy
->UserMayLoad(extension
.get(), NULL
)) {
208 // The error message from UserMayInstall() often contains the extension ID
209 // and is therefore not well suited to this UI.
210 error
= errors::kDisabledByPolicy
;
212 } else if (!extension_prefs_
->IsExtensionDisabled(extension
->id()) &&
213 policy
->MustRemainDisabled(
214 extension
.get(), &disable_reason
, NULL
)) {
215 extension_prefs_
->SetExtensionState(extension
->id(), Extension::DISABLED
);
216 extension_prefs_
->AddDisableReason(extension
->id(), disable_reason
);
217 force_disabled
= true;
219 UMA_HISTOGRAM_BOOLEAN("ExtensionInstalledLoader.ForceDisabled",
223 if (!extension
.get()) {
224 ExtensionErrorReporter::GetInstance()->ReportLoadError(
227 extension_service_
->profile(),
233 extension_prefs_
->UpdateManifest(extension
.get());
235 extension_service_
->AddExtension(extension
.get());
238 void InstalledLoader::LoadAllExtensions() {
239 DCHECK_CURRENTLY_ON(BrowserThread::UI
);
240 TRACE_EVENT0("browser,startup", "InstalledLoader::LoadAllExtensions");
241 SCOPED_UMA_HISTOGRAM_TIMER("Extensions.LoadAllTime2");
242 base::TimeTicks start_time
= base::TimeTicks::Now();
244 Profile
* profile
= extension_service_
->profile();
245 scoped_ptr
<ExtensionPrefs::ExtensionsInfo
> extensions_info(
246 extension_prefs_
->GetInstalledExtensionsInfo());
248 std::vector
<int> reload_reason_counts(NUM_MANIFEST_RELOAD_REASONS
, 0);
249 bool should_write_prefs
= false;
251 for (size_t i
= 0; i
< extensions_info
->size(); ++i
) {
252 ExtensionInfo
* info
= extensions_info
->at(i
).get();
254 // Skip extensions that were loaded from the command-line because we don't
255 // want those to persist across browser restart.
256 if (info
->extension_location
== Manifest::COMMAND_LINE
)
259 ManifestReloadReason reload_reason
= ShouldReloadExtensionManifest(*info
);
260 ++reload_reason_counts
[reload_reason
];
262 if (reload_reason
!= NOT_NEEDED
) {
263 // Reloading an extension reads files from disk. We do this on the
264 // UI thread because reloads should be very rare, and the complexity
265 // added by delaying the time when the extensions service knows about
266 // all extensions is significant. See crbug.com/37548 for details.
267 // |allow_io| disables tests that file operations run on the file
269 base::ThreadRestrictions::ScopedAllowIO allow_io
;
272 scoped_refptr
<const Extension
> extension(
273 file_util::LoadExtension(info
->extension_path
,
274 info
->extension_location
,
275 GetCreationFlags(info
),
278 if (!extension
.get() || extension
->id() != info
->extension_id
) {
279 invalid_extensions_
.insert(info
->extension_path
);
280 ExtensionErrorReporter::GetInstance()->ReportLoadError(
281 info
->extension_path
,
288 extensions_info
->at(i
)->extension_manifest
.reset(
289 static_cast<base::DictionaryValue
*>(
290 extension
->manifest()->value()->DeepCopy()));
291 should_write_prefs
= true;
295 for (size_t i
= 0; i
< extensions_info
->size(); ++i
) {
296 if (extensions_info
->at(i
)->extension_location
!= Manifest::COMMAND_LINE
)
297 Load(*extensions_info
->at(i
), should_write_prefs
);
300 extension_service_
->OnLoadedInstalledExtensions();
302 // The histograms Extensions.ManifestReload* allow us to validate
303 // the assumption that reloading manifest is a rare event.
304 UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadNotNeeded",
305 reload_reason_counts
[NOT_NEEDED
]);
306 UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadUnpackedDir",
307 reload_reason_counts
[UNPACKED_DIR
]);
308 UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadNeedsRelocalization",
309 reload_reason_counts
[NEEDS_RELOCALIZATION
]);
311 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAll",
312 extension_registry_
->enabled_extensions().size());
313 UMA_HISTOGRAM_COUNTS_100("Extensions.Disabled",
314 extension_registry_
->disabled_extensions().size());
316 // TODO(rkaplow): Obsolete this when verified similar to LoadAllTime2.
317 UMA_HISTOGRAM_TIMES("Extensions.LoadAllTime",
318 base::TimeTicks::Now() - start_time
);
319 RecordExtensionsMetrics();
322 void InstalledLoader::RecordExtensionsMetrics() {
323 Profile
* profile
= extension_service_
->profile();
325 int app_user_count
= 0;
326 int app_external_count
= 0;
327 int hosted_app_count
= 0;
328 int legacy_packaged_app_count
= 0;
329 int platform_app_count
= 0;
330 int user_script_count
= 0;
331 int extension_user_count
= 0;
332 int extension_external_count
= 0;
334 int page_action_count
= 0;
335 int browser_action_count
= 0;
336 int disabled_for_permissions_count
= 0;
337 int non_webstore_ntp_override_count
= 0;
338 int incognito_allowed_count
= 0;
339 int incognito_not_allowed_count
= 0;
340 int file_access_allowed_count
= 0;
341 int file_access_not_allowed_count
= 0;
342 int eventless_event_pages_count
= 0;
344 const ExtensionSet
& extensions
= extension_registry_
->enabled_extensions();
345 ExtensionActionManager
* extension_action_manager
=
346 ExtensionActionManager::Get(profile
);
347 for (ExtensionSet::const_iterator iter
= extensions
.begin();
348 iter
!= extensions
.end();
350 const Extension
* extension
= iter
->get();
351 Manifest::Location location
= extension
->location();
352 Manifest::Type type
= extension
->GetType();
354 // For the first few metrics, include all extensions and apps (component,
355 // unpacked, etc). It's good to know these locations, and it doesn't
356 // muck up any of the stats. Later, though, we want to omit component and
357 // unpacked, as they are less interesting.
358 if (extension
->is_app())
359 UMA_HISTOGRAM_ENUMERATION(
360 "Extensions.AppLocation", location
, Manifest::NUM_LOCATIONS
);
361 else if (extension
->is_extension())
362 UMA_HISTOGRAM_ENUMERATION(
363 "Extensions.ExtensionLocation", location
, Manifest::NUM_LOCATIONS
);
365 if (!ManifestURL::UpdatesFromGallery(extension
)) {
366 UMA_HISTOGRAM_ENUMERATION(
367 "Extensions.NonWebstoreLocation", location
, Manifest::NUM_LOCATIONS
);
369 // Check for inconsistencies if the extension was supposedly installed
370 // from the webstore.
373 // This value was a mistake. Turns out sideloaded extensions can
374 // have the from_webstore bit if they update from the webstore.
375 DEPRECATED_IS_EXTERNAL
= 1,
377 if (extension
->from_webstore()) {
378 UMA_HISTOGRAM_ENUMERATION(
379 "Extensions.FromWebstoreInconsistency", BAD_UPDATE_URL
, 2);
383 if (Manifest::IsExternalLocation(location
)) {
384 // See loop below for DISABLED.
385 if (ManifestURL::UpdatesFromGallery(extension
)) {
386 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
387 EXTERNAL_ITEM_WEBSTORE_ENABLED
,
388 EXTERNAL_ITEM_MAX_ITEMS
);
390 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
391 EXTERNAL_ITEM_NONWEBSTORE_ENABLED
,
392 EXTERNAL_ITEM_MAX_ITEMS
);
396 // From now on, don't count component extensions, since they are only
397 // extensions as an implementation detail. Continue to count unpacked
398 // extensions for a few metrics.
399 if (Manifest::IsComponentLocation(location
))
402 // Histogram for non-webstore extensions overriding new tab page should
403 // include unpacked extensions.
404 if (!extension
->from_webstore() &&
405 URLOverrides::GetChromeURLOverrides(extension
).count("newtab")) {
406 ++non_webstore_ntp_override_count
;
409 // Don't count unpacked extensions anymore, either.
410 if (Manifest::IsUnpackedLocation(location
))
413 UMA_HISTOGRAM_ENUMERATION("Extensions.ManifestVersion",
414 extension
->manifest_version(),
415 10); // TODO(kalman): Why 10 manifest versions?
417 // We might have wanted to count legacy packaged apps here, too, since they
418 // are effectively extensions. Unfortunately, it's too late, as we don't
419 // want to mess up the existing stats.
420 if (type
== Manifest::TYPE_EXTENSION
) {
421 UMA_HISTOGRAM_ENUMERATION("Extensions.BackgroundPageType",
422 GetBackgroundPageType(extension
),
423 NUM_BACKGROUND_PAGE_TYPES
);
425 if (GetBackgroundPageType(extension
) == EVENT_PAGE
) {
426 size_t num_registered_events
=
427 EventRouter::Get(extension_service_
->profile())
428 ->GetRegisteredEvents(extension
->id())
430 // Count extension event pages with no registered events. Either the
431 // event page is badly designed, or there may be a bug where the event
432 // page failed to start after an update (crbug.com/469361).
433 if (num_registered_events
== 0u) {
434 ++eventless_event_pages_count
;
435 VLOG(1) << "Event page without registered event listeners: "
436 << extension
->id() << " " << extension
->name();
438 // Count the number of event listeners the Enhanced Bookmarks Manager
439 // has for crbug.com/469361, but only if it's using an event page (not
440 // necessarily the case). This should always be > 0, because that's how
441 // the bookmarks extension works, but Chrome may have a bug - it has in
442 // the past. In fact, this metric may generally be useful for tracking
443 // the frequency of event page bugs.
444 std::string hashed_id
=
445 crx_file::id_util::HashedIdInHex(extension
->id());
446 if (hashed_id
== "D5736E4B5CF695CB93A2FB57E4FDC6E5AFAB6FE2") {
447 UMA_HISTOGRAM_CUSTOM_COUNTS(
448 "Extensions.EnhancedBookmarksManagerNumEventListeners",
449 num_registered_events
, 1, 10, 10);
454 // Using an enumeration shows us the total installed ratio across all users.
455 // Using the totals per user at each startup tells us the distribution of
456 // usage for each user (e.g. 40% of users have at least one app installed).
457 UMA_HISTOGRAM_ENUMERATION(
458 "Extensions.LoadType", type
, Manifest::NUM_LOAD_TYPES
);
460 case Manifest::TYPE_THEME
:
463 case Manifest::TYPE_USER_SCRIPT
:
466 case Manifest::TYPE_HOSTED_APP
:
468 if (Manifest::IsExternalLocation(location
)) {
469 ++app_external_count
;
474 case Manifest::TYPE_LEGACY_PACKAGED_APP
:
475 ++legacy_packaged_app_count
;
476 if (Manifest::IsExternalLocation(location
)) {
477 ++app_external_count
;
482 case Manifest::TYPE_PLATFORM_APP
:
483 ++platform_app_count
;
484 if (Manifest::IsExternalLocation(location
)) {
485 ++app_external_count
;
490 case Manifest::TYPE_EXTENSION
:
492 if (Manifest::IsExternalLocation(location
)) {
493 ++extension_external_count
;
495 ++extension_user_count
;
500 if (extension_action_manager
->GetPageAction(*extension
))
503 if (extension_action_manager
->GetBrowserAction(*extension
))
504 ++browser_action_count
;
506 RecordCreationFlags(extension
);
508 ExtensionService::RecordPermissionMessagesHistogram(extension
, "Load");
510 // For incognito and file access, skip anything that doesn't appear in
511 // settings. Also, policy-installed (and unpacked of course, checked above)
512 // extensions are boring.
513 if (extension
->ShouldDisplayInExtensionSettings() &&
514 !Manifest::IsPolicyLocation(extension
->location())) {
515 if (extension
->can_be_incognito_enabled()) {
516 if (util::IsIncognitoEnabled(extension
->id(), profile
))
517 ++incognito_allowed_count
;
519 ++incognito_not_allowed_count
;
521 if (extension
->wants_file_access()) {
522 if (util::AllowFileAccess(extension
->id(), profile
))
523 ++file_access_allowed_count
;
525 ++file_access_not_allowed_count
;
530 const ExtensionSet
& disabled_extensions
=
531 extension_registry_
->disabled_extensions();
533 for (ExtensionSet::const_iterator ex
= disabled_extensions
.begin();
534 ex
!= disabled_extensions
.end();
536 if (extension_prefs_
->DidExtensionEscalatePermissions((*ex
)->id())) {
537 ++disabled_for_permissions_count
;
539 RecordDisableReasons(extension_prefs_
->GetDisableReasons((*ex
)->id()));
540 if (Manifest::IsExternalLocation((*ex
)->location())) {
541 // See loop above for ENABLED.
542 if (ManifestURL::UpdatesFromGallery(ex
->get())) {
543 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
544 EXTERNAL_ITEM_WEBSTORE_DISABLED
,
545 EXTERNAL_ITEM_MAX_ITEMS
);
547 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
548 EXTERNAL_ITEM_NONWEBSTORE_DISABLED
,
549 EXTERNAL_ITEM_MAX_ITEMS
);
554 scoped_ptr
<ExtensionPrefs::ExtensionsInfo
> uninstalled_extensions_info(
555 extension_prefs_
->GetUninstalledExtensionsInfo());
556 for (size_t i
= 0; i
< uninstalled_extensions_info
->size(); ++i
) {
557 ExtensionInfo
* info
= uninstalled_extensions_info
->at(i
).get();
558 if (Manifest::IsExternalLocation(info
->extension_location
)) {
559 std::string update_url
;
560 if (info
->extension_manifest
->GetString("update_url", &update_url
) &&
561 extension_urls::IsWebstoreUpdateUrl(GURL(update_url
))) {
562 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
563 EXTERNAL_ITEM_WEBSTORE_UNINSTALLED
,
564 EXTERNAL_ITEM_MAX_ITEMS
);
566 UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
567 EXTERNAL_ITEM_NONWEBSTORE_UNINSTALLED
,
568 EXTERNAL_ITEM_MAX_ITEMS
);
573 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadApp",
574 app_user_count
+ app_external_count
);
575 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAppUser", app_user_count
);
576 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAppExternal", app_external_count
);
577 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadHostedApp", hosted_app_count
);
578 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPackagedApp",
579 legacy_packaged_app_count
);
580 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPlatformApp", platform_app_count
);
581 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtension",
582 extension_user_count
+ extension_external_count
);
583 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtensionUser",
584 extension_user_count
);
585 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtensionExternal",
586 extension_external_count
);
587 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadUserScript", user_script_count
);
588 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadTheme", theme_count
);
589 // Histogram name different for legacy reasons.
590 UMA_HISTOGRAM_COUNTS_100("PageActionController.ExtensionsWithPageActions",
592 UMA_HISTOGRAM_COUNTS_100("Extensions.LoadBrowserAction",
593 browser_action_count
);
594 UMA_HISTOGRAM_COUNTS_100("Extensions.DisabledForPermissions",
595 disabled_for_permissions_count
);
596 UMA_HISTOGRAM_COUNTS_100("Extensions.NonWebStoreNewTabPageOverrides",
597 non_webstore_ntp_override_count
);
598 if (incognito_allowed_count
+ incognito_not_allowed_count
> 0) {
599 UMA_HISTOGRAM_COUNTS_100("Extensions.IncognitoAllowed",
600 incognito_allowed_count
);
601 UMA_HISTOGRAM_COUNTS_100("Extensions.IncognitoNotAllowed",
602 incognito_not_allowed_count
);
604 if (file_access_allowed_count
+ file_access_not_allowed_count
> 0) {
605 UMA_HISTOGRAM_COUNTS_100("Extensions.FileAccessAllowed",
606 file_access_allowed_count
);
607 UMA_HISTOGRAM_COUNTS_100("Extensions.FileAccessNotAllowed",
608 file_access_not_allowed_count
);
610 UMA_HISTOGRAM_COUNTS_100("Extensions.CorruptExtensionTotalDisables",
611 extension_prefs_
->GetCorruptedDisableCount());
612 UMA_HISTOGRAM_COUNTS_100("Extensions.EventlessEventPages",
613 eventless_event_pages_count
);
616 int InstalledLoader::GetCreationFlags(const ExtensionInfo
* info
) {
617 int flags
= extension_prefs_
->GetCreationFlags(info
->extension_id
);
618 if (!Manifest::IsUnpackedLocation(info
->extension_location
))
619 flags
|= Extension::REQUIRE_KEY
;
620 if (extension_prefs_
->AllowFileAccess(info
->extension_id
))
621 flags
|= Extension::ALLOW_FILE_ACCESS
;
625 } // namespace extensions