1 // Copyright (c) 2011 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/apps_promo.h" 6 7 #include "base/command_line.h" 8 #include "base/metrics/histogram.h" 9 #include "chrome/browser/browser_process.h" 10 #include "chrome/browser/prefs/pref_service.h" 11 #include "chrome/browser/ui/webui/shown_sections_handler.h" 12 #include "chrome/common/chrome_switches.h" 13 #include "chrome/common/extensions/extension.h" 14 #include "chrome/common/pref_names.h" 15 16 const int AppsPromo::kDefaultAppsCounterMax = 10; 17 18 // static 19 void AppsPromo::RegisterPrefs(PrefService* local_state) { 20 std::string empty; 21 local_state->RegisterStringPref(prefs::kNTPWebStorePromoId, empty); 22 local_state->RegisterStringPref(prefs::kNTPWebStorePromoHeader, empty); 23 local_state->RegisterStringPref(prefs::kNTPWebStorePromoButton, empty); 24 local_state->RegisterStringPref(prefs::kNTPWebStorePromoLink, empty); 25 local_state->RegisterStringPref(prefs::kNTPWebStorePromoExpire, empty); 26 } 27 28 // static 29 void AppsPromo::RegisterUserPrefs(PrefService* prefs) { 30 // Set the default value for the counter to max+1 since we don't install 31 // default apps for new users. 32 prefs->RegisterIntegerPref( 33 prefs::kAppsPromoCounter, kDefaultAppsCounterMax + 1); 34 prefs->RegisterBooleanPref(prefs::kDefaultAppsInstalled, false); 35 prefs->RegisterStringPref(prefs::kNTPWebStorePromoLastId, std::string()); 36 } 37 38 // static 39 void AppsPromo::ClearPromo() { 40 PrefService* local_state = g_browser_process->local_state(); 41 local_state->ClearPref(prefs::kNTPWebStorePromoId); 42 local_state->ClearPref(prefs::kNTPWebStorePromoHeader); 43 local_state->ClearPref(prefs::kNTPWebStorePromoButton); 44 local_state->ClearPref(prefs::kNTPWebStorePromoLink); 45 local_state->ClearPref(prefs::kNTPWebStorePromoExpire); 46 } 47 48 // static 49 std::string AppsPromo::GetPromoButtonText() { 50 PrefService* local_state = g_browser_process->local_state(); 51 return local_state->GetString(prefs::kNTPWebStorePromoButton); 52 } 53 54 // static 55 std::string AppsPromo::GetPromoId() { 56 PrefService* local_state = g_browser_process->local_state(); 57 return local_state->GetString(prefs::kNTPWebStorePromoId); 58 } 59 60 // static 61 std::string AppsPromo::GetPromoHeaderText() { 62 PrefService* local_state = g_browser_process->local_state(); 63 return local_state->GetString(prefs::kNTPWebStorePromoHeader); 64 } 65 66 // static 67 GURL AppsPromo::GetPromoLink() { 68 PrefService* local_state = g_browser_process->local_state(); 69 return GURL(local_state->GetString(prefs::kNTPWebStorePromoLink)); 70 } 71 72 // static 73 std::string AppsPromo::GetPromoExpireText() { 74 PrefService* local_state = g_browser_process->local_state(); 75 return local_state->GetString(prefs::kNTPWebStorePromoExpire); 76 } 77 78 // static 79 void AppsPromo::SetPromo(const std::string& id, 80 const std::string& header_text, 81 const std::string& button_text, 82 const GURL& link, 83 const std::string& expire_text) { 84 PrefService* local_state = g_browser_process->local_state(); 85 local_state->SetString(prefs::kNTPWebStorePromoId, id); 86 local_state->SetString(prefs::kNTPWebStorePromoButton, button_text); 87 local_state->SetString(prefs::kNTPWebStorePromoHeader, header_text); 88 local_state->SetString(prefs::kNTPWebStorePromoLink, link.spec()); 89 local_state->SetString(prefs::kNTPWebStorePromoExpire, expire_text); 90 } 91 92 // static 93 bool AppsPromo::IsPromoSupportedForLocale() { 94 PrefService* local_state = g_browser_process->local_state(); 95 // PromoResourceService will clear the promo data if the current locale is 96 // not supported. 97 return local_state->HasPrefPath(prefs::kNTPWebStorePromoId) && 98 local_state->HasPrefPath(prefs::kNTPWebStorePromoHeader) && 99 local_state->HasPrefPath(prefs::kNTPWebStorePromoButton) && 100 local_state->HasPrefPath(prefs::kNTPWebStorePromoLink) && 101 local_state->HasPrefPath(prefs::kNTPWebStorePromoExpire); 102 } 103 104 AppsPromo::AppsPromo(PrefService* prefs) 105 : prefs_(prefs) { 106 // Poppit, Entanglement 107 old_default_app_ids_.insert("mcbkbpnkkkipelfledbfocopglifcfmi"); 108 old_default_app_ids_.insert("aciahcmjmecflokailenpkdchphgkefd"); 109 } 110 111 AppsPromo::~AppsPromo() {} 112 113 bool AppsPromo::ShouldShowPromo(const ExtensionIdSet& installed_ids, 114 bool* just_expired) { 115 *just_expired = false; 116 117 if (CommandLine::ForCurrentProcess()->HasSwitch( 118 switches::kForceAppsPromoVisible)) { 119 return true; 120 } 121 122 // Don't show the promo if one wasn't served to this locale. 123 if (!IsPromoSupportedForLocale()) 124 return false; 125 126 int promo_counter = GetPromoCounter(); 127 if (GetDefaultAppsInstalled() && promo_counter <= kDefaultAppsCounterMax) { 128 // If the default apps were installed from a previous Chrome version, we 129 // should still show the promo. If we don't have the exact set of default 130 // apps, this means that the user manually installed or uninstalled one. 131 // We no longer keep track of the default apps once others have been 132 // installed, so expire them immediately. 133 if (old_default_app_ids_ != installed_ids) { 134 ExpireDefaultApps(); 135 return false; 136 } 137 138 if (promo_counter == kDefaultAppsCounterMax) { 139 *just_expired = true; 140 141 // The default apps have expired due to inaction, so ping PROMO_EXPIRE. 142 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, 143 extension_misc::PROMO_EXPIRE, 144 extension_misc::PROMO_BUCKET_BOUNDARY); 145 146 ExpireDefaultApps(); 147 return true; 148 } else { 149 SetPromoCounter(++promo_counter); 150 return true; 151 } 152 } else if (installed_ids.empty()) { 153 return true; 154 } 155 156 return false; 157 } 158 159 bool AppsPromo::ShouldShowAppLauncher(const ExtensionIdSet& installed_ids) { 160 // On Chrome OS the default apps are installed via a separate mechanism that 161 // is always enabled. Therefore we always show the launcher. 162 #if defined(OS_CHROME) 163 return true; 164 #else 165 166 // Always show the app launcher if an app is installed. 167 if (!installed_ids.empty()) 168 return true; 169 170 // Otherwise, only show the app launcher if there's a promo for this locale. 171 return IsPromoSupportedForLocale(); 172 #endif 173 } 174 175 void AppsPromo::ExpireDefaultApps() { 176 SetPromoCounter(kDefaultAppsCounterMax + 1); 177 } 178 179 void AppsPromo::MaximizeAppsIfFirstView() { 180 std::string promo_id = GetPromoId(); 181 182 // Maximize the apps section of the NTP if this is the first time viewing the 183 // specific promo. 184 if (GetLastPromoId() != promo_id) { 185 prefs_->SetString(prefs::kNTPWebStorePromoLastId, promo_id); 186 ShownSectionsHandler::SetShownSection(prefs_, APPS); 187 } 188 } 189 190 void AppsPromo::HidePromo() { 191 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, 192 extension_misc::PROMO_CLOSE, 193 extension_misc::PROMO_BUCKET_BOUNDARY); 194 195 // Put the apps section into menu mode, and maximize the recent section. 196 ShownSectionsHandler::SetShownSection(prefs_, MENU_APPS); 197 ShownSectionsHandler::SetShownSection(prefs_, THUMB); 198 199 ExpireDefaultApps(); 200 } 201 202 std::string AppsPromo::GetLastPromoId() { 203 return prefs_->GetString(prefs::kNTPWebStorePromoLastId); 204 } 205 206 void AppsPromo::SetLastPromoId(const std::string& id) { 207 prefs_->SetString(prefs::kNTPWebStorePromoLastId, id); 208 } 209 210 int AppsPromo::GetPromoCounter() const { 211 return prefs_->GetInteger(prefs::kAppsPromoCounter); 212 } 213 214 void AppsPromo::SetPromoCounter(int val) { 215 prefs_->SetInteger(prefs::kAppsPromoCounter, val); 216 prefs_->ScheduleSavePersistentPrefs(); 217 } 218 219 bool AppsPromo::GetDefaultAppsInstalled() const { 220 return prefs_->GetBoolean(prefs::kDefaultAppsInstalled); 221 } 222