Update To 11.40.268.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / extensions / installed_loader.cc
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.
4
5 #include "chrome/browser/extensions/installed_loader.h"
6
7 #include "base/files/file_path.h"
8 #include "base/metrics/histogram.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/values.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/extensions/extension_action_manager.h"
16 #include "chrome/browser/extensions/extension_error_reporter.h"
17 #include "chrome/browser/extensions/extension_service.h"
18 #include "chrome/browser/extensions/extension_util.h"
19 #include "chrome/browser/profiles/profile_manager.h"
20 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/extensions/api/supervised_user_private/supervised_user_handler.h"
22 #include "chrome/common/extensions/chrome_manifest_url_handlers.h"
23 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/notification_service.h"
25 #include "content/public/browser/user_metrics.h"
26 #include "extensions/browser/extension_prefs.h"
27 #include "extensions/browser/extension_registry.h"
28 #include "extensions/browser/extension_system.h"
29 #include "extensions/browser/management_policy.h"
30 #include "extensions/common/extension.h"
31 #include "extensions/common/extension_l10n_util.h"
32 #include "extensions/common/extension_set.h"
33 #include "extensions/common/extension_urls.h"
34 #include "extensions/common/file_util.h"
35 #include "extensions/common/manifest.h"
36 #include "extensions/common/manifest_constants.h"
37 #include "extensions/common/manifest_handlers/background_info.h"
38 #include "extensions/common/manifest_url_handlers.h"
39
40 using base::UserMetricsAction;
41 using content::BrowserThread;
42
43 namespace extensions {
44
45 namespace errors = manifest_errors;
46
47 namespace {
48
49 // The following enumeration is used in histograms matching
50 // Extensions.ManifestReload*.
51 enum ManifestReloadReason {
52   NOT_NEEDED = 0,        // Reload not needed.
53   UNPACKED_DIR,          // Unpacked directory.
54   NEEDS_RELOCALIZATION,  // The locale has changed since we read this extension.
55   CORRUPT_PREFERENCES,   // The manifest in the preferences is corrupt.
56
57   // New enum values must go above here.
58   NUM_MANIFEST_RELOAD_REASONS
59 };
60
61 // Used in histogram Extension.BackgroundPageType.
62 enum BackgroundPageType {
63   NO_BACKGROUND_PAGE = 0,
64   BACKGROUND_PAGE_PERSISTENT,
65   EVENT_PAGE,
66
67   // New enum values must go above here.
68   NUM_BACKGROUND_PAGE_TYPES
69 };
70
71 // Used in histogram Extensions.ExternalItemState.
72 enum ExternalItemState {
73   DEPRECATED_EXTERNAL_ITEM_DISABLED = 0,
74   DEPRECATED_EXTERNAL_ITEM_ENABLED,
75   EXTERNAL_ITEM_WEBSTORE_DISABLED,
76   EXTERNAL_ITEM_WEBSTORE_ENABLED,
77   EXTERNAL_ITEM_NONWEBSTORE_DISABLED,
78   EXTERNAL_ITEM_NONWEBSTORE_ENABLED,
79   EXTERNAL_ITEM_WEBSTORE_UNINSTALLED,
80   EXTERNAL_ITEM_NONWEBSTORE_UNINSTALLED,
81
82   // New enum values must go above here.
83   EXTERNAL_ITEM_MAX_ITEMS
84 };
85
86 bool IsManifestCorrupt(const base::DictionaryValue* manifest) {
87   if (!manifest)
88     return false;
89
90   // Because of bug #272524 sometimes manifests got mangled in the preferences
91   // file, one particularly bad case resulting in having both a background page
92   // and background scripts values. In those situations we want to reload the
93   // manifest from the extension to fix this.
94   const base::Value* background_page;
95   const base::Value* background_scripts;
96   return manifest->Get(manifest_keys::kBackgroundPage, &background_page) &&
97       manifest->Get(manifest_keys::kBackgroundScripts, &background_scripts);
98 }
99
100 ManifestReloadReason ShouldReloadExtensionManifest(const ExtensionInfo& info) {
101   // Always reload manifests of unpacked extensions, because they can change
102   // on disk independent of the manifest in our prefs.
103   if (Manifest::IsUnpackedLocation(info.extension_location))
104     return UNPACKED_DIR;
105
106   // Reload the manifest if it needs to be relocalized.
107   if (extension_l10n_util::ShouldRelocalizeManifest(
108           info.extension_manifest.get()))
109     return NEEDS_RELOCALIZATION;
110
111   // Reload if the copy of the manifest in the preferences is corrupt.
112   if (IsManifestCorrupt(info.extension_manifest.get()))
113     return CORRUPT_PREFERENCES;
114
115   return NOT_NEEDED;
116 }
117
118 BackgroundPageType GetBackgroundPageType(const Extension* extension) {
119   if (!BackgroundInfo::HasBackgroundPage(extension))
120     return NO_BACKGROUND_PAGE;
121   if (BackgroundInfo::HasPersistentBackgroundPage(extension))
122     return BACKGROUND_PAGE_PERSISTENT;
123   return EVENT_PAGE;
124 }
125
126 // Records the creation flags of an extension grouped by
127 // Extension::InitFromValueFlags.
128 void RecordCreationFlags(const Extension* extension) {
129   for (int i = 0; i < Extension::kInitFromValueFlagBits; ++i) {
130     int flag = 1 << i;
131     if (extension->creation_flags() & flag) {
132       UMA_HISTOGRAM_ENUMERATION(
133           "Extensions.LoadCreationFlags", i, Extension::kInitFromValueFlagBits);
134     }
135   }
136 }
137
138 // Helper to record a single disable reason histogram value (see
139 // RecordDisableReasons below).
140 void RecordDisbleReasonHistogram(int reason) {
141   UMA_HISTOGRAM_SPARSE_SLOWLY("Extensions.DisableReason", reason);
142 }
143
144 // Records the disable reasons for a single extension grouped by
145 // Extension::DisableReason.
146 void RecordDisableReasons(int reasons) {
147   // |reasons| is a bitmask with values from Extension::DisabledReason
148   // which are increasing powers of 2.
149   if (reasons == Extension::DISABLE_NONE) {
150     RecordDisbleReasonHistogram(Extension::DISABLE_NONE);
151     return;
152   }
153   for (int reason = 1; reason < Extension::DISABLE_REASON_LAST; reason <<= 1) {
154     if (reasons & reason)
155       RecordDisbleReasonHistogram(reason);
156   }
157 }
158
159 }  // namespace
160
161 InstalledLoader::InstalledLoader(ExtensionService* extension_service)
162     : extension_service_(extension_service),
163       extension_registry_(ExtensionRegistry::Get(extension_service->profile())),
164       extension_prefs_(ExtensionPrefs::Get(extension_service->profile())) {}
165
166 InstalledLoader::~InstalledLoader() {
167 }
168
169 void InstalledLoader::Load(const ExtensionInfo& info, bool write_to_prefs) {
170   std::string error;
171   scoped_refptr<const Extension> extension(NULL);
172   if (info.extension_manifest) {
173     extension = Extension::Create(
174         info.extension_path,
175         info.extension_location,
176         *info.extension_manifest,
177         GetCreationFlags(&info),
178         &error);
179   } else {
180     error = errors::kManifestUnreadable;
181   }
182
183   // Once installed, non-unpacked extensions cannot change their IDs (e.g., by
184   // updating the 'key' field in their manifest).
185   // TODO(jstritar): migrate preferences when unpacked extensions change IDs.
186   if (extension.get() && !Manifest::IsUnpackedLocation(extension->location()) &&
187       info.extension_id != extension->id()) {
188     error = errors::kCannotChangeExtensionID;
189     extension = NULL;
190   }
191
192   // Check policy on every load in case an extension was blacklisted while
193   // Chrome was not running.
194   const ManagementPolicy* policy = extensions::ExtensionSystem::Get(
195       extension_service_->profile())->management_policy();
196   if (extension.get()) {
197     Extension::DisableReason disable_reason = Extension::DISABLE_NONE;
198     bool force_disabled = false;
199     if (!policy->UserMayLoad(extension.get(), NULL)) {
200       // The error message from UserMayInstall() often contains the extension ID
201       // and is therefore not well suited to this UI.
202       error = errors::kDisabledByPolicy;
203       extension = NULL;
204     } else if (!extension_prefs_->IsExtensionDisabled(extension->id()) &&
205                policy->MustRemainDisabled(
206                    extension.get(), &disable_reason, NULL)) {
207       extension_prefs_->SetExtensionState(extension->id(), Extension::DISABLED);
208       extension_prefs_->AddDisableReason(extension->id(), disable_reason);
209       force_disabled = true;
210     }
211     UMA_HISTOGRAM_BOOLEAN("ExtensionInstalledLoader.ForceDisabled",
212                           force_disabled);
213   }
214
215   if (!extension.get()) {
216     ExtensionErrorReporter::GetInstance()->ReportLoadError(
217         info.extension_path,
218         error,
219         extension_service_->profile(),
220         false);  // Be quiet.
221     return;
222   }
223
224   if (write_to_prefs)
225     extension_prefs_->UpdateManifest(extension.get());
226
227   extension_service_->AddExtension(extension.get());
228 }
229
230 void InstalledLoader::LoadAllExtensions() {
231   CHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
232
233   base::TimeTicks start_time = base::TimeTicks::Now();
234
235   Profile* profile = extension_service_->profile();
236   scoped_ptr<ExtensionPrefs::ExtensionsInfo> extensions_info(
237       extension_prefs_->GetInstalledExtensionsInfo());
238
239   std::vector<int> reload_reason_counts(NUM_MANIFEST_RELOAD_REASONS, 0);
240   bool should_write_prefs = false;
241
242   for (size_t i = 0; i < extensions_info->size(); ++i) {
243     ExtensionInfo* info = extensions_info->at(i).get();
244
245     // Skip extensions that were loaded from the command-line because we don't
246     // want those to persist across browser restart.
247     if (info->extension_location == Manifest::COMMAND_LINE)
248       continue;
249
250     ManifestReloadReason reload_reason = ShouldReloadExtensionManifest(*info);
251     ++reload_reason_counts[reload_reason];
252
253     if (reload_reason != NOT_NEEDED) {
254       // Reloading an extension reads files from disk.  We do this on the
255       // UI thread because reloads should be very rare, and the complexity
256       // added by delaying the time when the extensions service knows about
257       // all extensions is significant.  See crbug.com/37548 for details.
258       // |allow_io| disables tests that file operations run on the file
259       // thread.
260       base::ThreadRestrictions::ScopedAllowIO allow_io;
261
262       std::string error;
263       scoped_refptr<const Extension> extension(
264           file_util::LoadExtension(info->extension_path,
265                                    info->extension_location,
266                                    GetCreationFlags(info),
267                                    &error));
268
269       if (!extension.get()) {
270         ExtensionErrorReporter::GetInstance()->ReportLoadError(
271             info->extension_path,
272             error,
273             profile,
274             false);  // Be quiet.
275         continue;
276       }
277
278       extensions_info->at(i)->extension_manifest.reset(
279           static_cast<base::DictionaryValue*>(
280               extension->manifest()->value()->DeepCopy()));
281       should_write_prefs = true;
282     }
283   }
284
285   for (size_t i = 0; i < extensions_info->size(); ++i) {
286     if (extensions_info->at(i)->extension_location != Manifest::COMMAND_LINE)
287       Load(*extensions_info->at(i), should_write_prefs);
288   }
289
290   extension_service_->OnLoadedInstalledExtensions();
291
292   // The histograms Extensions.ManifestReload* allow us to validate
293   // the assumption that reloading manifest is a rare event.
294   UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadNotNeeded",
295                            reload_reason_counts[NOT_NEEDED]);
296   UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadUnpackedDir",
297                            reload_reason_counts[UNPACKED_DIR]);
298   UMA_HISTOGRAM_COUNTS_100("Extensions.ManifestReloadNeedsRelocalization",
299                            reload_reason_counts[NEEDS_RELOCALIZATION]);
300
301   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAll",
302                            extension_registry_->enabled_extensions().size());
303   UMA_HISTOGRAM_COUNTS_100("Extensions.Disabled",
304                            extension_registry_->disabled_extensions().size());
305
306   UMA_HISTOGRAM_TIMES("Extensions.LoadAllTime",
307                       base::TimeTicks::Now() - start_time);
308
309   int app_user_count = 0;
310   int app_external_count = 0;
311   int hosted_app_count = 0;
312   int legacy_packaged_app_count = 0;
313   int platform_app_count = 0;
314   int user_script_count = 0;
315   int content_pack_count = 0;
316   int extension_user_count = 0;
317   int extension_external_count = 0;
318   int theme_count = 0;
319   int page_action_count = 0;
320   int browser_action_count = 0;
321   int disabled_for_permissions_count = 0;
322   int non_webstore_ntp_override_count = 0;
323   int incognito_allowed_count = 0;
324   int incognito_not_allowed_count = 0;
325   int file_access_allowed_count = 0;
326   int file_access_not_allowed_count = 0;
327
328   const ExtensionSet& extensions = extension_registry_->enabled_extensions();
329   ExtensionActionManager* extension_action_manager =
330       ExtensionActionManager::Get(profile);
331   for (ExtensionSet::const_iterator iter = extensions.begin();
332        iter != extensions.end();
333        ++iter) {
334     const Extension* extension = iter->get();
335     Manifest::Location location = extension->location();
336     Manifest::Type type = extension->GetType();
337
338     // For the first few metrics, include all extensions and apps (component,
339     // unpacked, etc). It's good to know these locations, and it doesn't
340     // muck up any of the stats. Later, though, we want to omit component and
341     // unpacked, as they are less interesting.
342     if (extension->is_app())
343       UMA_HISTOGRAM_ENUMERATION(
344           "Extensions.AppLocation", location, Manifest::NUM_LOCATIONS);
345     else if (extension->is_extension())
346       UMA_HISTOGRAM_ENUMERATION(
347           "Extensions.ExtensionLocation", location, Manifest::NUM_LOCATIONS);
348
349     if (!ManifestURL::UpdatesFromGallery(extension)) {
350       UMA_HISTOGRAM_ENUMERATION(
351           "Extensions.NonWebstoreLocation", location, Manifest::NUM_LOCATIONS);
352
353       // Check for inconsistencies if the extension was supposedly installed
354       // from the webstore.
355       enum {
356         BAD_UPDATE_URL = 0,
357         // This value was a mistake. Turns out sideloaded extensions can
358         // have the from_webstore bit if they update from the webstore.
359         DEPRECATED_IS_EXTERNAL = 1,
360       };
361       if (extension->from_webstore()) {
362         UMA_HISTOGRAM_ENUMERATION(
363             "Extensions.FromWebstoreInconsistency", BAD_UPDATE_URL, 2);
364       }
365     }
366
367     if (Manifest::IsExternalLocation(location)) {
368       // See loop below for DISABLED.
369       if (ManifestURL::UpdatesFromGallery(extension)) {
370         UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
371                                   EXTERNAL_ITEM_WEBSTORE_ENABLED,
372                                   EXTERNAL_ITEM_MAX_ITEMS);
373       } else {
374         UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
375                                   EXTERNAL_ITEM_NONWEBSTORE_ENABLED,
376                                   EXTERNAL_ITEM_MAX_ITEMS);
377       }
378     }
379
380     // From now on, don't count component extensions, since they are only
381     // extensions as an implementation detail. Continue to count unpacked
382     // extensions for a few metrics.
383     if (location == Manifest::COMPONENT)
384       continue;
385
386     // Histogram for non-webstore extensions overriding new tab page should
387     // include unpacked extensions.
388     if (!extension->from_webstore() &&
389         URLOverrides::GetChromeURLOverrides(extension).count("newtab")) {
390       ++non_webstore_ntp_override_count;
391     }
392
393     // Don't count unpacked extensions anymore, either.
394     if (Manifest::IsUnpackedLocation(location))
395       continue;
396
397     UMA_HISTOGRAM_ENUMERATION("Extensions.ManifestVersion",
398                               extension->manifest_version(),
399                               10);  // TODO(kalman): Why 10 manifest versions?
400
401     // We might have wanted to count legacy packaged apps here, too, since they
402     // are effectively extensions. Unfortunately, it's too late, as we don't
403     // want to mess up the existing stats.
404     if (type == Manifest::TYPE_EXTENSION) {
405       UMA_HISTOGRAM_ENUMERATION("Extensions.BackgroundPageType",
406                                 GetBackgroundPageType(extension),
407                                 NUM_BACKGROUND_PAGE_TYPES);
408     }
409
410     // Using an enumeration shows us the total installed ratio across all users.
411     // Using the totals per user at each startup tells us the distribution of
412     // usage for each user (e.g. 40% of users have at least one app installed).
413     UMA_HISTOGRAM_ENUMERATION(
414         "Extensions.LoadType", type, Manifest::NUM_LOAD_TYPES);
415     switch (type) {
416       case Manifest::TYPE_THEME:
417         ++theme_count;
418         break;
419       case Manifest::TYPE_USER_SCRIPT:
420         ++user_script_count;
421         break;
422       case Manifest::TYPE_HOSTED_APP:
423         ++hosted_app_count;
424         if (Manifest::IsExternalLocation(location)) {
425           ++app_external_count;
426         } else {
427           ++app_user_count;
428         }
429         break;
430       case Manifest::TYPE_LEGACY_PACKAGED_APP:
431         ++legacy_packaged_app_count;
432         if (Manifest::IsExternalLocation(location)) {
433           ++app_external_count;
434         } else {
435           ++app_user_count;
436         }
437         break;
438       case Manifest::TYPE_PLATFORM_APP:
439         ++platform_app_count;
440         if (Manifest::IsExternalLocation(location)) {
441           ++app_external_count;
442         } else {
443           ++app_user_count;
444         }
445         break;
446       case Manifest::TYPE_EXTENSION:
447       default:
448         if (Manifest::IsExternalLocation(location)) {
449           ++extension_external_count;
450         } else {
451           ++extension_user_count;
452         }
453         break;
454     }
455
456     if (extension_action_manager->GetPageAction(*extension))
457       ++page_action_count;
458
459     if (extension_action_manager->GetBrowserAction(*extension))
460       ++browser_action_count;
461
462     if (SupervisedUserInfo::IsContentPack(extension))
463       ++content_pack_count;
464
465     RecordCreationFlags(extension);
466
467     ExtensionService::RecordPermissionMessagesHistogram(
468         extension, "Extensions.Permissions_Load2");
469
470     // For incognito and file access, skip anything that doesn't appear in
471     // settings. Also, policy-installed (and unpacked of course, checked above)
472     // extensions are boring.
473     if (extension->ShouldDisplayInExtensionSettings() &&
474         !Manifest::IsPolicyLocation(extension->location())) {
475       if (extension->can_be_incognito_enabled()) {
476         if (util::IsIncognitoEnabled(extension->id(), profile))
477           ++incognito_allowed_count;
478         else
479           ++incognito_not_allowed_count;
480       }
481       if (extension->wants_file_access()) {
482         if (util::AllowFileAccess(extension->id(), profile))
483           ++file_access_allowed_count;
484         else
485           ++file_access_not_allowed_count;
486       }
487     }
488   }
489
490   const ExtensionSet& disabled_extensions =
491       extension_registry_->disabled_extensions();
492
493   for (ExtensionSet::const_iterator ex = disabled_extensions.begin();
494        ex != disabled_extensions.end();
495        ++ex) {
496     if (extension_prefs_->DidExtensionEscalatePermissions((*ex)->id())) {
497       ++disabled_for_permissions_count;
498     }
499     RecordDisableReasons(extension_prefs_->GetDisableReasons((*ex)->id()));
500     if (Manifest::IsExternalLocation((*ex)->location())) {
501       // See loop above for ENABLED.
502       if (ManifestURL::UpdatesFromGallery(ex->get())) {
503         UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
504                                   EXTERNAL_ITEM_WEBSTORE_DISABLED,
505                                   EXTERNAL_ITEM_MAX_ITEMS);
506       } else {
507         UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
508                                   EXTERNAL_ITEM_NONWEBSTORE_DISABLED,
509                                   EXTERNAL_ITEM_MAX_ITEMS);
510       }
511     }
512   }
513
514   scoped_ptr<ExtensionPrefs::ExtensionsInfo> uninstalled_extensions_info(
515       extension_prefs_->GetUninstalledExtensionsInfo());
516   for (size_t i = 0; i < uninstalled_extensions_info->size(); ++i) {
517     ExtensionInfo* info = uninstalled_extensions_info->at(i).get();
518     if (Manifest::IsExternalLocation(info->extension_location)) {
519       std::string update_url;
520       if (info->extension_manifest->GetString("update_url", &update_url) &&
521           extension_urls::IsWebstoreUpdateUrl(GURL(update_url))) {
522         UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
523                                   EXTERNAL_ITEM_WEBSTORE_UNINSTALLED,
524                                   EXTERNAL_ITEM_MAX_ITEMS);
525       } else {
526         UMA_HISTOGRAM_ENUMERATION("Extensions.ExternalItemState",
527                                   EXTERNAL_ITEM_NONWEBSTORE_UNINSTALLED,
528                                   EXTERNAL_ITEM_MAX_ITEMS);
529       }
530     }
531   }
532
533   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadApp",
534                            app_user_count + app_external_count);
535   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAppUser", app_user_count);
536   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadAppExternal", app_external_count);
537   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadHostedApp", hosted_app_count);
538   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPackagedApp",
539                            legacy_packaged_app_count);
540   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadPlatformApp", platform_app_count);
541   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtension",
542                            extension_user_count + extension_external_count);
543   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtensionUser",
544                            extension_user_count);
545   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadExtensionExternal",
546                            extension_external_count);
547   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadUserScript", user_script_count);
548   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadTheme", theme_count);
549   // Histogram name different for legacy reasons.
550   UMA_HISTOGRAM_COUNTS_100("PageActionController.ExtensionsWithPageActions",
551                            page_action_count);
552   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadBrowserAction",
553                            browser_action_count);
554   UMA_HISTOGRAM_COUNTS_100("Extensions.LoadContentPack", content_pack_count);
555   UMA_HISTOGRAM_COUNTS_100("Extensions.DisabledForPermissions",
556                            disabled_for_permissions_count);
557   UMA_HISTOGRAM_COUNTS_100("Extensions.NonWebStoreNewTabPageOverrides",
558                            non_webstore_ntp_override_count);
559   if (incognito_allowed_count + incognito_not_allowed_count > 0) {
560     UMA_HISTOGRAM_COUNTS_100("Extensions.IncognitoAllowed",
561                              incognito_allowed_count);
562     UMA_HISTOGRAM_COUNTS_100("Extensions.IncognitoNotAllowed",
563                              incognito_not_allowed_count);
564   }
565   if (file_access_allowed_count + file_access_not_allowed_count > 0) {
566     UMA_HISTOGRAM_COUNTS_100("Extensions.FileAccessAllowed",
567                              file_access_allowed_count);
568     UMA_HISTOGRAM_COUNTS_100("Extensions.FileAccessNotAllowed",
569                              file_access_not_allowed_count);
570   }
571   UMA_HISTOGRAM_COUNTS_100("Extensions.CorruptExtensionTotalDisables",
572                            extension_prefs_->GetCorruptedDisableCount());
573 }
574
575 int InstalledLoader::GetCreationFlags(const ExtensionInfo* info) {
576   int flags = extension_prefs_->GetCreationFlags(info->extension_id);
577   if (!Manifest::IsUnpackedLocation(info->extension_location))
578     flags |= Extension::REQUIRE_KEY;
579   if (extension_prefs_->AllowFileAccess(info->extension_id))
580     flags |= Extension::ALLOW_FILE_ACCESS;
581   return flags;
582 }
583
584 }  // namespace extensions