OLD | NEW |
| (Empty) |
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. | |
4 | |
5 #include "chrome/browser/extensions/apps_promo.h" | |
6 | |
7 #include "base/base64.h" | |
8 #include "base/command_line.h" | |
9 #include "base/metrics/histogram.h" | |
10 #include "chrome/browser/browser_process.h" | |
11 #include "chrome/browser/prefs/pref_service.h" | |
12 #include "chrome/browser/profiles/profile.h" | |
13 #include "chrome/common/chrome_notification_types.h" | |
14 #include "chrome/common/chrome_switches.h" | |
15 #include "chrome/common/extensions/extension.h" | |
16 #include "chrome/common/pref_names.h" | |
17 #include "content/public/browser/notification_service.h" | |
18 #include "content/public/common/url_constants.h" | |
19 | |
20 const int AppsPromo::kDefaultAppsCounterMax = 10; | |
21 | |
22 namespace { | |
23 | |
24 // The default logo for the promo. | |
25 const char kDefaultLogo[] = "chrome://theme/IDR_WEBSTORE_ICON"; | |
26 | |
27 // The default promo data (this is only used for testing with | |
28 // --force-apps-promo-visible). | |
29 const char kDefaultHeader[] = "Browse thousands of apps and games for Chrome"; | |
30 const char kDefaultButton[] = "Visit the Chrome Web Store"; | |
31 const char kDefaultExpire[] = "No thanks"; | |
32 const char kDefaultLink[] = "https://chrome.google.com/webstore"; | |
33 | |
34 // Returns the string pref at |path|, using |fallback| as the default (if there | |
35 // is no pref value present). |fallback| is used for debugging in concert with | |
36 // --force-apps-promo-visible. | |
37 std::string GetStringPref(const char* path, const std::string& fallback) { | |
38 PrefService* local_state = g_browser_process->local_state(); | |
39 std::string retval(local_state->GetString(path)); | |
40 if (retval.empty() && CommandLine::ForCurrentProcess()->HasSwitch( | |
41 switches::kForceAppsPromoVisible)) { | |
42 retval = fallback; | |
43 } | |
44 return retval; | |
45 } | |
46 | |
47 } // namespace | |
48 | |
49 AppsPromo::PromoData::PromoData() : user_group(AppsPromo::USERS_NONE) {} | |
50 AppsPromo::PromoData::PromoData(const std::string& id, | |
51 const std::string& header, | |
52 const std::string& button, | |
53 const GURL& link, | |
54 const std::string& expire, | |
55 const GURL& logo, | |
56 const int user_group) | |
57 : id(id), | |
58 header(header), | |
59 button(button), | |
60 link(link), | |
61 expire(expire), | |
62 logo(logo), | |
63 user_group(user_group) {} | |
64 | |
65 AppsPromo::PromoData::~PromoData() {} | |
66 | |
67 // static | |
68 void AppsPromo::RegisterPrefs(PrefService* local_state) { | |
69 std::string empty; | |
70 local_state->RegisterBooleanPref(prefs::kNtpWebStoreEnabled, false); | |
71 local_state->RegisterStringPref(prefs::kNtpWebStorePromoId, empty); | |
72 local_state->RegisterStringPref(prefs::kNtpWebStorePromoHeader, empty); | |
73 local_state->RegisterStringPref(prefs::kNtpWebStorePromoButton, empty); | |
74 local_state->RegisterStringPref(prefs::kNtpWebStorePromoLink, empty); | |
75 local_state->RegisterStringPref(prefs::kNtpWebStorePromoLogo, empty); | |
76 local_state->RegisterStringPref(prefs::kNtpWebStorePromoLogoSource, empty); | |
77 local_state->RegisterStringPref(prefs::kNtpWebStorePromoExpire, empty); | |
78 local_state->RegisterIntegerPref(prefs::kNtpWebStorePromoUserGroup, 0); | |
79 } | |
80 | |
81 // static | |
82 void AppsPromo::RegisterUserPrefs(PrefService* prefs) { | |
83 // Set the default value for the counter to max+1 since we don't install | |
84 // default apps for new users. | |
85 prefs->RegisterIntegerPref(prefs::kAppsPromoCounter, | |
86 kDefaultAppsCounterMax + 1, | |
87 PrefService::UNSYNCABLE_PREF); | |
88 prefs->RegisterBooleanPref(prefs::kDefaultAppsInstalled, | |
89 false, | |
90 PrefService::UNSYNCABLE_PREF); | |
91 prefs->RegisterStringPref(prefs::kNtpWebStorePromoLastId, | |
92 std::string(), | |
93 PrefService::UNSYNCABLE_PREF); | |
94 prefs->RegisterBooleanPref(prefs::kNtpHideWebStorePromo, | |
95 false, | |
96 PrefService::UNSYNCABLE_PREF); | |
97 } | |
98 | |
99 // static | |
100 bool AppsPromo::IsPromoSupportedForLocale() { | |
101 PrefService* local_state = g_browser_process->local_state(); | |
102 // PromoResourceService will clear the promo data if the current locale is | |
103 // not supported. | |
104 return local_state->HasPrefPath(prefs::kNtpWebStorePromoId) && | |
105 local_state->HasPrefPath(prefs::kNtpWebStorePromoHeader) && | |
106 local_state->HasPrefPath(prefs::kNtpWebStorePromoButton) && | |
107 local_state->HasPrefPath(prefs::kNtpWebStorePromoLink) && | |
108 local_state->HasPrefPath(prefs::kNtpWebStorePromoLogo) && | |
109 local_state->HasPrefPath(prefs::kNtpWebStorePromoExpire) && | |
110 local_state->HasPrefPath(prefs::kNtpWebStorePromoUserGroup); | |
111 } | |
112 | |
113 // static | |
114 bool AppsPromo::IsWebStoreSupportedForLocale() { | |
115 PrefService* local_state = g_browser_process->local_state(); | |
116 return local_state->GetBoolean(prefs::kNtpWebStoreEnabled); | |
117 } | |
118 | |
119 // static | |
120 void AppsPromo::SetWebStoreSupportedForLocale(bool supported) { | |
121 PrefService* local_state = g_browser_process->local_state(); | |
122 local_state->SetBoolean(prefs::kNtpWebStoreEnabled, supported); | |
123 } | |
124 | |
125 // static | |
126 void AppsPromo::ClearPromo() { | |
127 PrefService* local_state = g_browser_process->local_state(); | |
128 local_state->ClearPref(prefs::kNtpWebStoreEnabled); | |
129 local_state->ClearPref(prefs::kNtpWebStorePromoId); | |
130 local_state->ClearPref(prefs::kNtpWebStorePromoHeader); | |
131 local_state->ClearPref(prefs::kNtpWebStorePromoButton); | |
132 local_state->ClearPref(prefs::kNtpWebStorePromoLink); | |
133 local_state->ClearPref(prefs::kNtpWebStorePromoLogo); | |
134 local_state->ClearPref(prefs::kNtpWebStorePromoLogoSource); | |
135 local_state->ClearPref(prefs::kNtpWebStorePromoExpire); | |
136 local_state->ClearPref(prefs::kNtpWebStorePromoUserGroup); | |
137 } | |
138 | |
139 // static | |
140 AppsPromo::PromoData AppsPromo::GetPromo() { | |
141 PromoData data; | |
142 PrefService* local_state = g_browser_process->local_state(); | |
143 | |
144 data.id = GetStringPref(prefs::kNtpWebStorePromoId, ""); | |
145 data.link = GURL(GetStringPref(prefs::kNtpWebStorePromoLink, kDefaultLink)); | |
146 data.user_group = local_state->GetInteger(prefs::kNtpWebStorePromoUserGroup); | |
147 data.header = GetStringPref(prefs::kNtpWebStorePromoHeader, kDefaultHeader); | |
148 data.button = GetStringPref(prefs::kNtpWebStorePromoButton, kDefaultButton); | |
149 data.expire = GetStringPref(prefs::kNtpWebStorePromoExpire, kDefaultExpire); | |
150 | |
151 GURL logo_url(local_state->GetString(prefs::kNtpWebStorePromoLogo)); | |
152 if (logo_url.is_valid() && logo_url.SchemeIs(chrome::kDataScheme)) | |
153 data.logo = logo_url; | |
154 else | |
155 data.logo = GURL(kDefaultLogo); | |
156 | |
157 return data; | |
158 } | |
159 | |
160 // static | |
161 void AppsPromo::SetPromo(const AppsPromo::PromoData& data) { | |
162 PrefService* local_state = g_browser_process->local_state(); | |
163 local_state->SetString(prefs::kNtpWebStorePromoId, data.id); | |
164 local_state->SetString(prefs::kNtpWebStorePromoButton, data.button); | |
165 local_state->SetString(prefs::kNtpWebStorePromoHeader, data.header); | |
166 local_state->SetString(prefs::kNtpWebStorePromoLink, data.link.spec()); | |
167 local_state->SetString(prefs::kNtpWebStorePromoLogo, data.logo.spec()); | |
168 local_state->SetString(prefs::kNtpWebStorePromoExpire, data.expire); | |
169 local_state->SetInteger(prefs::kNtpWebStorePromoUserGroup, data.user_group); | |
170 } | |
171 | |
172 // static | |
173 GURL AppsPromo::GetSourcePromoLogoURL() { | |
174 return GURL(GetStringPref(prefs::kNtpWebStorePromoLogoSource, "")); | |
175 } | |
176 | |
177 // static | |
178 void AppsPromo::SetSourcePromoLogoURL(const GURL& logo_source) { | |
179 PrefService* local_state = g_browser_process->local_state(); | |
180 local_state->SetString(prefs::kNtpWebStorePromoLogoSource, | |
181 logo_source.spec()); | |
182 } | |
183 | |
184 AppsPromo::AppsPromo(PrefService* prefs) | |
185 : prefs_(prefs) { | |
186 // Poppit, Entanglement | |
187 old_default_app_ids_.insert("mcbkbpnkkkipelfledbfocopglifcfmi"); | |
188 old_default_app_ids_.insert("aciahcmjmecflokailenpkdchphgkefd"); | |
189 } | |
190 | |
191 AppsPromo::~AppsPromo() {} | |
192 | |
193 bool AppsPromo::ShouldShowPromo(const extensions::ExtensionIdSet& installed_ids, | |
194 bool* just_expired) { | |
195 *just_expired = false; | |
196 | |
197 if (CommandLine::ForCurrentProcess()->HasSwitch( | |
198 switches::kForceAppsPromoVisible)) { | |
199 return true; | |
200 } | |
201 | |
202 // Don't show the promo if the policy says not to. | |
203 if (prefs_->GetBoolean(prefs::kNtpHideWebStorePromo)) { | |
204 ExpireDefaultApps(); | |
205 return false; | |
206 } | |
207 | |
208 // Don't show the promo if one wasn't served to this locale. | |
209 if (!IsPromoSupportedForLocale()) | |
210 return false; | |
211 | |
212 int promo_counter = GetPromoCounter(); | |
213 if (GetDefaultAppsInstalled() && promo_counter <= kDefaultAppsCounterMax) { | |
214 // If the default apps were installed from a previous Chrome version, we | |
215 // should still show the promo. If we don't have the exact set of default | |
216 // apps, this means that the user manually installed or uninstalled one. | |
217 // We no longer keep track of the default apps once others have been | |
218 // installed, so expire them immediately. | |
219 if (old_default_app_ids_ != installed_ids) { | |
220 ExpireDefaultApps(); | |
221 return false; | |
222 } | |
223 | |
224 if (promo_counter == kDefaultAppsCounterMax) { | |
225 *just_expired = true; | |
226 | |
227 // The default apps have expired due to inaction, so ping PROMO_EXPIRE. | |
228 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, | |
229 extension_misc::PROMO_EXPIRE, | |
230 extension_misc::PROMO_BUCKET_BOUNDARY); | |
231 | |
232 ExpireDefaultApps(); | |
233 } else { | |
234 SetPromoCounter(++promo_counter); | |
235 } | |
236 return true; | |
237 } else if (installed_ids.empty()) { | |
238 return true; | |
239 } | |
240 | |
241 return false; | |
242 } | |
243 | |
244 bool AppsPromo::ShouldShowAppLauncher( | |
245 const extensions::ExtensionIdSet& installed_ids) { | |
246 // On Chrome OS the default apps are installed via a separate mechanism that | |
247 // is always enabled. Therefore we always show the launcher. | |
248 #if defined(OS_CHROMEOS) | |
249 return true; | |
250 #else | |
251 | |
252 // Always show the app launcher if an app is installed. | |
253 if (!installed_ids.empty()) | |
254 return true; | |
255 | |
256 // Otherwise, only show the app launcher if the web store is supported for the | |
257 // current locale. | |
258 return IsWebStoreSupportedForLocale(); | |
259 #endif | |
260 } | |
261 | |
262 void AppsPromo::ExpireDefaultApps() { | |
263 SetPromoCounter(kDefaultAppsCounterMax + 1); | |
264 } | |
265 | |
266 void AppsPromo::HidePromo() { | |
267 UMA_HISTOGRAM_ENUMERATION(extension_misc::kAppsPromoHistogram, | |
268 extension_misc::PROMO_CLOSE, | |
269 extension_misc::PROMO_BUCKET_BOUNDARY); | |
270 | |
271 ExpireDefaultApps(); | |
272 } | |
273 | |
274 std::string AppsPromo::GetLastPromoId() { | |
275 return prefs_->GetString(prefs::kNtpWebStorePromoLastId); | |
276 } | |
277 | |
278 void AppsPromo::SetLastPromoId(const std::string& id) { | |
279 prefs_->SetString(prefs::kNtpWebStorePromoLastId, id); | |
280 } | |
281 | |
282 int AppsPromo::GetPromoCounter() const { | |
283 return prefs_->GetInteger(prefs::kAppsPromoCounter); | |
284 } | |
285 | |
286 void AppsPromo::SetPromoCounter(int val) { | |
287 prefs_->SetInteger(prefs::kAppsPromoCounter, val); | |
288 } | |
289 | |
290 bool AppsPromo::GetDefaultAppsInstalled() const { | |
291 return prefs_->GetBoolean(prefs::kDefaultAppsInstalled); | |
292 } | |
293 | |
294 AppsPromo::UserGroup AppsPromo::GetCurrentUserGroup() const { | |
295 const PrefService::Preference* last_promo_id | |
296 = prefs_->FindPreference(prefs::kNtpWebStorePromoLastId); | |
297 CHECK(last_promo_id); | |
298 return last_promo_id->IsDefaultValue() ? USERS_NEW : USERS_EXISTING; | |
299 } | |
OLD | NEW |