Make default apps cache multiprofile friendly
[chromium-blink-merge.git] / chrome / browser / extensions / default_apps.cc
blob957a9354764c3064ac06f4c967e8ecd4bf0cbeea
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 "chrome/browser/browser_process.h"
12 #include "components/user_prefs/pref_registry_syncable.h"
13 #include "base/prefs/pref_service.h"
14 #include "chrome/browser/profiles/profile.h"
15 #include "chrome/common/chrome_switches.h"
16 #include "chrome/common/chrome_version_info.h"
17 #include "chrome/common/extensions/extension.h"
18 #include "chrome/common/pref_names.h"
19 #include "ui/base/l10n/l10n_util.h"
21 #if !defined(OS_ANDROID)
22 #include "chrome/browser/first_run/first_run.h"
23 #endif
25 namespace {
27 // Returns true if the app was a default app in Chrome 22
28 bool IsOldDefaultApp(const std::string& extension_id) {
29 return extension_id == extension_misc::kGmailAppId ||
30 extension_id == extension_misc::kGoogleSearchAppId ||
31 extension_id == extension_misc::kYoutubeAppId;
34 bool IsLocaleSupported() {
35 // Don't bother installing default apps in locales where it is known that
36 // they don't work.
37 // TODO(rogerta): Do this check dynamically once the webstore can expose
38 // an API. See http://crbug.com/101357
39 const std::string& locale = g_browser_process->GetApplicationLocale();
40 static const char* unsupported_locales[] = {"CN", "TR", "IR"};
41 for (size_t i = 0; i < arraysize(unsupported_locales); ++i) {
42 if (EndsWith(locale, unsupported_locales[i], false)) {
43 return false;
46 return true;
49 } // namespace
51 namespace default_apps {
53 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
54 registry->RegisterIntegerPref(
55 prefs::kDefaultAppsInstallState,
56 kUnknown,
57 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
60 bool Provider::ShouldInstallInProfile() {
61 // We decide to install or not install default apps based on the following
62 // criteria, from highest priority to lowest priority:
64 // - The command line option. Tests use this option to disable installation
65 // of default apps in some cases.
66 // - If the locale is not compatible with the defaults, don't install them.
67 // - The kDefaultApps preferences value in the profile. This value is
68 // usually set in the master_preferences file.
69 bool install_apps =
70 profile_->GetPrefs()->GetString(prefs::kDefaultApps) == "install";
72 InstallState state =
73 static_cast<InstallState>(profile_->GetPrefs()->GetInteger(
74 prefs::kDefaultAppsInstallState));
76 is_migration_ = (state == kProvideLegacyDefaultApps);
78 switch (state) {
79 case kUnknown: {
80 // Only new installations and profiles get default apps. In theory the
81 // new profile checks should catch new installations, but that is not
82 // always the case (http:/crbug.com/145351).
83 chrome::VersionInfo version_info;
84 bool is_new_profile =
85 profile_->WasCreatedByVersionOrLater(version_info.Version().c_str());
86 // Android excludes most of the first run code, so it can't determine
87 // if this is a first run. That's OK though, because Android doesn't
88 // use default apps in general.
89 #if defined(OS_ANDROID)
90 bool is_first_run = false;
91 #else
92 bool is_first_run = first_run::IsChromeFirstRun();
93 #endif
94 if (!is_first_run && !is_new_profile)
95 install_apps = false;
96 break;
99 // The old default apps were provided as external extensions and were
100 // installed everytime Chrome was run. Thus, changing the list of default
101 // apps affected all users. Migrate old default apps to new mechanism where
102 // they are installed only once as INTERNAL.
103 // TODO(grv) : remove after Q1-2013.
104 case kProvideLegacyDefaultApps:
105 profile_->GetPrefs()->SetInteger(
106 prefs::kDefaultAppsInstallState,
107 kAlreadyInstalledDefaultApps);
108 break;
110 case kAlreadyInstalledDefaultApps:
111 case kNeverInstallDefaultApps:
112 install_apps = false;
113 break;
114 default:
115 NOTREACHED();
118 if (install_apps && !IsLocaleSupported())
119 install_apps = false;
121 // Default apps are only installed on profile creation or a new chrome
122 // download.
123 if (state == kUnknown) {
124 if (install_apps) {
125 profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState,
126 kAlreadyInstalledDefaultApps);
127 } else {
128 profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState,
129 kNeverInstallDefaultApps);
133 return install_apps;
136 Provider::Provider(Profile* profile,
137 VisitorInterface* service,
138 extensions::ExternalLoader* loader,
139 extensions::Manifest::Location crx_location,
140 extensions::Manifest::Location download_location,
141 int creation_flags)
142 : extensions::ExternalProviderImpl(service, loader, profile, crx_location,
143 download_location, creation_flags),
144 profile_(profile),
145 is_migration_(false) {
146 DCHECK(profile);
147 set_auto_acknowledge(true);
150 void Provider::VisitRegisteredExtension() {
151 if (!profile_ || !ShouldInstallInProfile()) {
152 base::DictionaryValue* prefs = new base::DictionaryValue;
153 SetPrefs(prefs);
154 return;
157 extensions::ExternalProviderImpl::VisitRegisteredExtension();
160 void Provider::SetPrefs(base::DictionaryValue* prefs) {
161 if (is_migration_) {
162 std::set<std::string> new_default_apps;
163 for (DictionaryValue::Iterator i(*prefs); !i.IsAtEnd(); i.Advance()) {
164 if (!IsOldDefaultApp(i.key()))
165 new_default_apps.insert(i.key());
167 // Filter out the new default apps for migrating users.
168 for (std::set<std::string>::iterator it = new_default_apps.begin();
169 it != new_default_apps.end(); ++it) {
170 prefs->Remove(*it, NULL);
174 ExternalProviderImpl::SetPrefs(prefs);
177 } // namespace default_apps