15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/extensions/default_apps.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 7c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <set> 8c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include <string> 9c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/command_line.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/prefs/pref_service.h" 12f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "chrome/browser/browser_process.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/browser/profiles/profile.h" 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_switches.h" 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/chrome_version_info.h" 161e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)#include "chrome/common/extensions/extension_constants.h" 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "chrome/common/pref_names.h" 18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "components/pref_registry/pref_registry_syncable.h" 19f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)#include "extensions/common/extension.h" 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "ui/base/l10n/l10n_util.h" 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 22c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#if !defined(OS_ANDROID) 23c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#include "chrome/browser/first_run/first_run.h" 24c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)#endif 255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)namespace { 275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns true if the app was a default app in Chrome 22 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsOldDefaultApp(const std::string& extension_id) { 30c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return extension_id == extension_misc::kGmailAppId || 31c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_id == extension_misc::kGoogleSearchAppId || 32c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) extension_id == extension_misc::kYoutubeAppId; 335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsLocaleSupported() { 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Don't bother installing default apps in locales where it is known that 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // they don't work. 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(rogerta): Do this check dynamically once the webstore can expose 395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // an API. See http://crbug.com/101357 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) const std::string& locale = g_browser_process->GetApplicationLocale(); 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static const char* unsupported_locales[] = {"CN", "TR", "IR"}; 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (size_t i = 0; i < arraysize(unsupported_locales); ++i) { 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (EndsWith(locale, unsupported_locales[i], false)) { 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return false; 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return true; 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 50c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} // namespace 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace default_apps { 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 547dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdochvoid RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { 55c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) registry->RegisterIntegerPref( 56c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) prefs::kDefaultAppsInstallState, 57c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) kUnknown, 58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool Provider::ShouldInstallInProfile() { 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // We decide to install or not install default apps based on the following 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // criteria, from highest priority to lowest priority: 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - The command line option. Tests use this option to disable installation 665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // of default apps in some cases. 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - If the locale is not compatible with the defaults, don't install them. 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // - The kDefaultApps preferences value in the profile. This value is 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // usually set in the master_preferences file. 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool install_apps = 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_->GetPrefs()->GetString(prefs::kDefaultApps) == "install"; 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) InstallState state = 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) static_cast<InstallState>(profile_->GetPrefs()->GetInteger( 755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs::kDefaultAppsInstallState)); 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_migration_ = (state == kProvideLegacyDefaultApps); 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) switch (state) { 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kUnknown: { 815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Only new installations and profiles get default apps. In theory the 825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // new profile checks should catch new installations, but that is not 835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // always the case (http:/crbug.com/145351). 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) chrome::VersionInfo version_info; 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_new_profile = 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_->WasCreatedByVersionOrLater(version_info.Version().c_str()); 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Android excludes most of the first run code, so it can't determine 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // if this is a first run. That's OK though, because Android doesn't 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // use default apps in general. 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#if defined(OS_ANDROID) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_first_run = false; 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#else 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) bool is_first_run = first_run::IsChromeFirstRun(); 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#endif 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!is_first_run && !is_new_profile) 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_apps = false; 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // The old default apps were provided as external extensions and were 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // installed everytime Chrome was run. Thus, changing the list of default 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // apps affected all users. Migrate old default apps to new mechanism where 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // they are installed only once as INTERNAL. 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // TODO(grv) : remove after Q1-2013. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kProvideLegacyDefaultApps: 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_->GetPrefs()->SetInteger( 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs::kDefaultAppsInstallState, 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kAlreadyInstalledDefaultApps); 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kAlreadyInstalledDefaultApps: 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) case kNeverInstallDefaultApps: 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_apps = false; 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) break; 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) default: 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NOTREACHED(); 1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (install_apps && !IsLocaleSupported()) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) install_apps = false; 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Default apps are only installed on profile creation or a new chrome 1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // download. 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (state == kUnknown) { 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (install_apps) { 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState, 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kAlreadyInstalledDefaultApps); 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } else { 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_->GetPrefs()->SetInteger(prefs::kDefaultAppsInstallState, 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) kNeverInstallDefaultApps); 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return install_apps; 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Provider::Provider(Profile* profile, 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) VisitorInterface* service, 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExternalLoader* loader, 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::Manifest::Location crx_location, 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) extensions::Manifest::Location download_location, 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) int creation_flags) 143868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) : extensions::ExternalProviderImpl(service, loader, profile, crx_location, 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) download_location, creation_flags), 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) profile_(profile), 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) is_migration_(false) { 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) DCHECK(profile); 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) set_auto_acknowledge(true); 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Provider::VisitRegisteredExtension() { 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (!profile_ || !ShouldInstallInProfile()) { 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) base::DictionaryValue* prefs = new base::DictionaryValue; 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) SetPrefs(prefs); 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return; 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) extensions::ExternalProviderImpl::VisitRegisteredExtension(); 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void Provider::SetPrefs(base::DictionaryValue* prefs) { 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (is_migration_) { 1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) std::set<std::string> new_default_apps; 1645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) for (base::DictionaryValue::Iterator i(*prefs); !i.IsAtEnd(); i.Advance()) { 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!IsOldDefaultApp(i.key())) 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_default_apps.insert(i.key()); 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) // Filter out the new default apps for migrating users. 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for (std::set<std::string>::iterator it = new_default_apps.begin(); 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) it != new_default_apps.end(); ++it) { 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) prefs->Remove(*it, NULL); 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) ExternalProviderImpl::SetPrefs(prefs); 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace default_apps 179