blob: 37eb85e864a91582c25aaff1182f6f3200b44959 [file] [log] [blame]
[email protected]73285952012-05-25 20:46:401// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]86c6b9e32011-10-25 17:09:102// 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/default_apps.h"
6
avia2f4804a2015-12-24 23:11:137#include <stddef.h>
8
[email protected]b8096552013-05-04 15:48:119#include <set>
10#include <string>
11
[email protected]86c6b9e32011-10-25 17:09:1012#include "base/command_line.h"
avia2f4804a2015-12-24 23:11:1313#include "base/macros.h"
[email protected]3853a4c2013-02-11 17:15:5714#include "base/prefs/pref_service.h"
[email protected]d4f52042014-08-08 22:43:5915#include "base/strings/string_util.h"
[email protected]e4452d32013-11-15 23:07:4116#include "chrome/browser/browser_process.h"
[email protected]13e062e2014-08-09 10:21:5517#include "chrome/browser/first_run/first_run.h"
[email protected]86c6b9e32011-10-25 17:09:1018#include "chrome/browser/profiles/profile.h"
19#include "chrome/common/chrome_switches.h"
[email protected]b0af4792013-10-23 09:12:1320#include "chrome/common/extensions/extension_constants.h"
[email protected]86c6b9e32011-10-25 17:09:1021#include "chrome/common/pref_names.h"
[email protected]f0c8c4992014-05-15 17:37:2622#include "components/pref_registry/pref_registry_syncable.h"
sdefresne9fb67692015-08-03 18:48:2223#include "components/version_info/version_info.h"
[email protected]e4452d32013-11-15 23:07:4124#include "extensions/common/extension.h"
[email protected]86c6b9e32011-10-25 17:09:1025
[email protected]937cf9d2012-08-30 03:51:5526namespace {
27
[email protected]937cf9d2012-08-30 03:51:5528// Returns true if the app was a default app in Chrome 22
29bool IsOldDefaultApp(const std::string& extension_id) {
[email protected]b8096552013-05-04 15:48:1130 return extension_id == extension_misc::kGmailAppId ||
[email protected]b8096552013-05-04 15:48:1131 extension_id == extension_misc::kYoutubeAppId;
[email protected]937cf9d2012-08-30 03:51:5532}
33
34bool 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();
thestig4b36dd32014-10-31 20:30:1940 static const char* const unsupported_locales[] = {"CN", "TR", "IR"};
[email protected]937cf9d2012-08-30 03:51:5541 for (size_t i = 0; i < arraysize(unsupported_locales); ++i) {
brettwa7ff1b292015-07-16 17:49:2942 if (base::EndsWith(locale, unsupported_locales[i],
43 base::CompareCase::INSENSITIVE_ASCII)) {
[email protected]937cf9d2012-08-30 03:51:5544 return false;
45 }
46 }
47 return true;
48}
49
[email protected]b8096552013-05-04 15:48:1150} // namespace
[email protected]937cf9d2012-08-30 03:51:5551
[email protected]910f72ce2012-08-24 01:38:3552namespace default_apps {
53
[email protected]37ca3fe02013-07-05 15:32:4454void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) {
raymesaa608722015-04-27 03:00:2555 registry->RegisterIntegerPref(prefs::kDefaultAppsInstallState, kUnknown);
[email protected]937cf9d2012-08-30 03:51:5556}
57
58bool Provider::ShouldInstallInProfile() {
[email protected]86c6b9e32011-10-25 17:09:1059 // We decide to install or not install default apps based on the following
60 // criteria, from highest priority to lowest priority:
61 //
[email protected]86c6b9e32011-10-25 17:09:1062 // - The command line option. Tests use this option to disable installation
63 // of default apps in some cases.
64 // - If the locale is not compatible with the defaults, don't install them.
[email protected]86c6b9e32011-10-25 17:09:1065 // - The kDefaultApps preferences value in the profile. This value is
66 // usually set in the master_preferences file.
67 bool install_apps =
[email protected]937cf9d2012-08-30 03:51:5568 profile_->GetPrefs()->GetString(prefs::kDefaultApps) == "install";
[email protected]86c6b9e32011-10-25 17:09:1069
[email protected]937cf9d2012-08-30 03:51:5570 InstallState state =
71 static_cast<InstallState>(profile_->GetPrefs()->GetInteger(
[email protected]d190cef2011-11-09 02:09:2472 prefs::kDefaultAppsInstallState));
[email protected]910f72ce2012-08-24 01:38:3573
[email protected]937cf9d2012-08-30 03:51:5574 is_migration_ = (state == kProvideLegacyDefaultApps);
75
[email protected]86c6b9e32011-10-25 17:09:1076 switch (state) {
[email protected]937cf9d2012-08-30 03:51:5577 case kUnknown: {
[email protected]2eef64f2012-08-31 23:09:1278 // Only new installations and profiles get default apps. In theory the
79 // new profile checks should catch new installations, but that is not
80 // always the case (http:/crbug.com/145351).
sdefresne9fb67692015-08-03 18:48:2281 bool is_new_profile = profile_->WasCreatedByVersionOrLater(
82 version_info::GetVersionNumber());
[email protected]2eef64f2012-08-31 23:09:1283 bool is_first_run = first_run::IsChromeFirstRun();
[email protected]2eef64f2012-08-31 23:09:1284 if (!is_first_run && !is_new_profile)
[email protected]86c6b9e32011-10-25 17:09:1085 install_apps = false;
86 break;
87 }
[email protected]910f72ce2012-08-24 01:38:3588
89 // The old default apps were provided as external extensions and were
90 // installed everytime Chrome was run. Thus, changing the list of default
91 // apps affected all users. Migrate old default apps to new mechanism where
92 // they are installed only once as INTERNAL.
93 // TODO(grv) : remove after Q1-2013.
[email protected]937cf9d2012-08-30 03:51:5594 case kProvideLegacyDefaultApps:
95 profile_->GetPrefs()->SetInteger(
[email protected]910f72ce2012-08-24 01:38:3596 prefs::kDefaultAppsInstallState,
[email protected]937cf9d2012-08-30 03:51:5597 kAlreadyInstalledDefaultApps);
[email protected]86c6b9e32011-10-25 17:09:1098 break;
[email protected]910f72ce2012-08-24 01:38:3599
[email protected]937cf9d2012-08-30 03:51:55100 case kAlreadyInstalledDefaultApps:
101 case kNeverInstallDefaultApps:
[email protected]86c6b9e32011-10-25 17:09:10102 install_apps = false;
103 break;
104 default:
105 NOTREACHED();
106 }
107
[email protected]9bf21b92012-10-04 21:01:39108 if (install_apps && !IsLocaleSupported())
[email protected]910f72ce2012-08-24 01:38:35109 install_apps = false;
[email protected]86c6b9e32011-10-25 17:09:10110
[email protected]910f72ce2012-08-24 01:38:35111 // Default apps are only installed on profile creation or a new chrome
112 // download.
[email protected]937cf9d2012-08-30 03:51:55113 if (state == kUnknown) {
[email protected]86c6b9e32011-10-25 17:09:10114 if (install_apps) {
[email protected]9bf21b92012-10-04 21:01:39115 profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState,
116 kAlreadyInstalledDefaultApps);
[email protected]86c6b9e32011-10-25 17:09:10117 } else {
[email protected]937cf9d2012-08-30 03:51:55118 profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState,
119 kNeverInstallDefaultApps);
[email protected]86c6b9e32011-10-25 17:09:10120 }
[email protected]86c6b9e32011-10-25 17:09:10121 }
122
123 return install_apps;
124}
125
[email protected]d190cef2011-11-09 02:09:24126Provider::Provider(Profile* profile,
127 VisitorInterface* service,
[email protected]5df038b2012-07-16 19:03:27128 extensions::ExternalLoader* loader,
[email protected]1d5e58b2013-01-31 08:41:40129 extensions::Manifest::Location crx_location,
130 extensions::Manifest::Location download_location,
[email protected]d190cef2011-11-09 02:09:24131 int creation_flags)
[email protected]19eac6d2013-05-30 06:51:03132 : extensions::ExternalProviderImpl(service, loader, profile, crx_location,
[email protected]5df038b2012-07-16 19:03:27133 download_location, creation_flags),
[email protected]e9a30af2012-10-04 01:56:25134 profile_(profile),
135 is_migration_(false) {
[email protected]d190cef2011-11-09 02:09:24136 DCHECK(profile);
[email protected]47fc70c2011-12-06 07:29:51137 set_auto_acknowledge(true);
[email protected]d190cef2011-11-09 02:09:24138}
139
140void Provider::VisitRegisteredExtension() {
[email protected]937cf9d2012-08-30 03:51:55141 if (!profile_ || !ShouldInstallInProfile()) {
[email protected]d190cef2011-11-09 02:09:24142 base::DictionaryValue* prefs = new base::DictionaryValue;
143 SetPrefs(prefs);
144 return;
145 }
146
[email protected]5df038b2012-07-16 19:03:27147 extensions::ExternalProviderImpl::VisitRegisteredExtension();
[email protected]d190cef2011-11-09 02:09:24148}
149
[email protected]937cf9d2012-08-30 03:51:55150void Provider::SetPrefs(base::DictionaryValue* prefs) {
151 if (is_migration_) {
152 std::set<std::string> new_default_apps;
[email protected]023b3d12013-12-23 18:46:49153 for (base::DictionaryValue::Iterator i(*prefs); !i.IsAtEnd(); i.Advance()) {
[email protected]02d9b272013-03-06 12:54:56154 if (!IsOldDefaultApp(i.key()))
155 new_default_apps.insert(i.key());
[email protected]937cf9d2012-08-30 03:51:55156 }
157 // Filter out the new default apps for migrating users.
158 for (std::set<std::string>::iterator it = new_default_apps.begin();
159 it != new_default_apps.end(); ++it) {
160 prefs->Remove(*it, NULL);
[email protected]910f72ce2012-08-24 01:38:35161 }
162 }
[email protected]937cf9d2012-08-30 03:51:55163
164 ExternalProviderImpl::SetPrefs(prefs);
[email protected]910f72ce2012-08-24 01:38:35165}
166
[email protected]86c6b9e32011-10-25 17:09:10167} // namespace default_apps