Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / extensions / default_apps.cc
blob64e260f96ac3c66a0708a75c9d9ddcd6b7e377d9
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/default_apps.h"
7 #include <set>
8 #include <string>
10 #include "base/command_line.h"
11 #include "base/prefs/pref_service.h"
12 #include "base/strings/string_util.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/first_run/first_run.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/common/chrome_switches.h"
17 #include "chrome/common/extensions/extension_constants.h"
18 #include "chrome/common/pref_names.h"
19 #include "components/pref_registry/pref_registry_syncable.h"
20 #include "components/version_info/version_info.h"
21 #include "extensions/common/extension.h"
23 namespace {
25 // Returns true if the app was a default app in Chrome 22
26 bool IsOldDefaultApp(const std::string& extension_id) {
27 return extension_id == extension_misc::kGmailAppId ||
28 extension_id == extension_misc::kGoogleSearchAppId ||
29 extension_id == extension_misc::kYoutubeAppId;
32 bool IsLocaleSupported() {
33 // Don't bother installing default apps in locales where it is known that
34 // they don't work.
35 // TODO(rogerta): Do this check dynamically once the webstore can expose
36 // an API. See http://crbug.com/101357
37 const std::string& locale = g_browser_process->GetApplicationLocale();
38 static const char* const unsupported_locales[] = {"CN", "TR", "IR"};
39 for (size_t i = 0; i < arraysize(unsupported_locales); ++i) {
40 if (base::EndsWith(locale, unsupported_locales[i],
41 base::CompareCase::INSENSITIVE_ASCII)) {
42 return false;
45 return true;
48 } // namespace
50 namespace default_apps {
52 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
53 registry->RegisterIntegerPref(prefs::kDefaultAppsInstallState, kUnknown);
56 bool Provider::ShouldInstallInProfile() {
57 // We decide to install or not install default apps based on the following
58 // criteria, from highest priority to lowest priority:
60 // - The command line option. Tests use this option to disable installation
61 // of default apps in some cases.
62 // - If the locale is not compatible with the defaults, don't install them.
63 // - The kDefaultApps preferences value in the profile. This value is
64 // usually set in the master_preferences file.
65 bool install_apps =
66 profile_->GetPrefs()->GetString(prefs::kDefaultApps) == "install";
68 InstallState state =
69 static_cast<InstallState>(profile_->GetPrefs()->GetInteger(
70 prefs::kDefaultAppsInstallState));
72 is_migration_ = (state == kProvideLegacyDefaultApps);
74 switch (state) {
75 case kUnknown: {
76 // Only new installations and profiles get default apps. In theory the
77 // new profile checks should catch new installations, but that is not
78 // always the case (http:/crbug.com/145351).
79 bool is_new_profile = profile_->WasCreatedByVersionOrLater(
80 version_info::GetVersionNumber());
81 bool is_first_run = first_run::IsChromeFirstRun();
82 if (!is_first_run && !is_new_profile)
83 install_apps = false;
84 break;
87 // The old default apps were provided as external extensions and were
88 // installed everytime Chrome was run. Thus, changing the list of default
89 // apps affected all users. Migrate old default apps to new mechanism where
90 // they are installed only once as INTERNAL.
91 // TODO(grv) : remove after Q1-2013.
92 case kProvideLegacyDefaultApps:
93 profile_->GetPrefs()->SetInteger(
94 prefs::kDefaultAppsInstallState,
95 kAlreadyInstalledDefaultApps);
96 break;
98 case kAlreadyInstalledDefaultApps:
99 case kNeverInstallDefaultApps:
100 install_apps = false;
101 break;
102 default:
103 NOTREACHED();
106 if (install_apps && !IsLocaleSupported())
107 install_apps = false;
109 // Default apps are only installed on profile creation or a new chrome
110 // download.
111 if (state == kUnknown) {
112 if (install_apps) {
113 profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState,
114 kAlreadyInstalledDefaultApps);
115 } else {
116 profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState,
117 kNeverInstallDefaultApps);
121 return install_apps;
124 Provider::Provider(Profile* profile,
125 VisitorInterface* service,
126 extensions::ExternalLoader* loader,
127 extensions::Manifest::Location crx_location,
128 extensions::Manifest::Location download_location,
129 int creation_flags)
130 : extensions::ExternalProviderImpl(service, loader, profile, crx_location,
131 download_location, creation_flags),
132 profile_(profile),
133 is_migration_(false) {
134 DCHECK(profile);
135 set_auto_acknowledge(true);
138 void Provider::VisitRegisteredExtension() {
139 if (!profile_ || !ShouldInstallInProfile()) {
140 base::DictionaryValue* prefs = new base::DictionaryValue;
141 SetPrefs(prefs);
142 return;
145 extensions::ExternalProviderImpl::VisitRegisteredExtension();
148 void Provider::SetPrefs(base::DictionaryValue* prefs) {
149 if (is_migration_) {
150 std::set<std::string> new_default_apps;
151 for (base::DictionaryValue::Iterator i(*prefs); !i.IsAtEnd(); i.Advance()) {
152 if (!IsOldDefaultApp(i.key()))
153 new_default_apps.insert(i.key());
155 // Filter out the new default apps for migrating users.
156 for (std::set<std::string>::iterator it = new_default_apps.begin();
157 it != new_default_apps.end(); ++it) {
158 prefs->Remove(*it, NULL);
162 ExternalProviderImpl::SetPrefs(prefs);
165 } // namespace default_apps