Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(147)

Side by Side Diff: chrome/browser/web_resource/promo_resource_service.cc

Issue 10539045: Purge Logo/WebstoreSignal. (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: missed a file Created 8 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/web_resource/promo_resource_service.h" 5 #include "chrome/browser/web_resource/promo_resource_service.h"
6 6
7 #include "base/command_line.h" 7 #include "base/command_line.h"
8 #include "base/rand_util.h" 8 #include "base/message_loop.h"
9 #include "base/string_number_conversions.h"
10 #include "base/threading/thread_restrictions.h" 9 #include "base/threading/thread_restrictions.h"
11 #include "base/time.h"
12 #include "base/utf_string_conversions.h"
13 #include "base/values.h" 10 #include "base/values.h"
14 #include "chrome/browser/browser_process.h" 11 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/extensions/apps_promo.h"
16 #include "chrome/browser/prefs/pref_service.h" 12 #include "chrome/browser/prefs/pref_service.h"
17 #include "chrome/browser/profiles/profile.h" 13 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/sync/sync_ui_util.h"
19 #include "chrome/common/chrome_notification_types.h" 14 #include "chrome/common/chrome_notification_types.h"
20 #include "chrome/common/chrome_switches.h" 15 #include "chrome/common/chrome_switches.h"
21 #include "chrome/common/chrome_version_info.h"
22 #include "chrome/common/pref_names.h" 16 #include "chrome/common/pref_names.h"
23 #include "content/public/browser/browser_thread.h" 17 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/notification_service.h" 18 #include "content/public/browser/notification_service.h"
25 #include "googleurl/src/gurl.h" 19 #include "googleurl/src/gurl.h"
26 20
27 namespace { 21 namespace {
28 22
29 // Delay on first fetch so we don't interfere with startup. 23 // Delay on first fetch so we don't interfere with startup.
30 static const int kStartResourceFetchDelay = 5000; 24 static const int kStartResourceFetchDelay = 5000;
31 25
32 // Delay between calls to update the cache (12 hours), and 3 min in debug mode. 26 // Delay between calls to update the cache (12 hours), and 3 min in debug mode.
33 static const int kCacheUpdateDelay = 12 * 60 * 60 * 1000; 27 static const int kCacheUpdateDelay = 12 * 60 * 60 * 1000;
34 static const int kTestCacheUpdateDelay = 3 * 60 * 1000; 28 static const int kTestCacheUpdateDelay = 3 * 60 * 1000;
35 29
36 // The version of the service (used to expire the cache when upgrading Chrome 30 // The version of the service (used to expire the cache when upgrading Chrome
37 // to versions with different types of promos). 31 // to versions with different types of promos).
38 static const int kPromoServiceVersion = 7; 32 static const int kPromoServiceVersion = 7;
39 33
40 // Properties used by the server.
41 static const char kAnswerIdProperty[] = "answer_id";
42 static const char kWebStoreHeaderProperty[] = "question";
43 static const char kWebStoreButtonProperty[] = "inproduct_target";
44 static const char kWebStoreLinkProperty[] = "inproduct";
45 static const char kWebStoreExpireProperty[] = "tooltip";
46
47 GURL GetPromoResourceURL() { 34 GURL GetPromoResourceURL() {
48 const std::string promo_server_url = CommandLine::ForCurrentProcess()-> 35 const std::string promo_server_url = CommandLine::ForCurrentProcess()->
49 GetSwitchValueASCII(switches::kPromoServerURL); 36 GetSwitchValueASCII(switches::kPromoServerURL);
50 return promo_server_url.empty() ? 37 return promo_server_url.empty() ?
51 NotificationPromo::PromoServerURL() : GURL(promo_server_url); 38 NotificationPromo::PromoServerURL() : GURL(promo_server_url);
52 } 39 }
53 40
54 bool IsTest() { 41 bool IsTest() {
55 return CommandLine::ForCurrentProcess()->HasSwitch(switches::kPromoServerURL); 42 return CommandLine::ForCurrentProcess()->HasSwitch(switches::kPromoServerURL);
56 } 43 }
57 44
58 int GetCacheUpdateDelay() { 45 int GetCacheUpdateDelay() {
59 return IsTest() ? kTestCacheUpdateDelay : kCacheUpdateDelay; 46 return IsTest() ? kTestCacheUpdateDelay : kCacheUpdateDelay;
60 } 47 }
61 48
62 } // namespace 49 } // namespace
63 50
64 // static 51 // static
65 void PromoResourceService::RegisterPrefs(PrefService* local_state) { 52 void PromoResourceService::RegisterPrefs(PrefService* local_state) {
66 local_state->RegisterIntegerPref(prefs::kNtpPromoVersion, 0); 53 local_state->RegisterIntegerPref(prefs::kNtpPromoVersion, 0);
67 local_state->RegisterStringPref(prefs::kNtpPromoLocale, std::string()); 54 local_state->RegisterStringPref(prefs::kNtpPromoLocale, std::string());
68 } 55 }
69 56
70 // static 57 // static
71 void PromoResourceService::RegisterUserPrefs(PrefService* prefs) { 58 void PromoResourceService::RegisterUserPrefs(PrefService* prefs) {
72 prefs->RegisterStringPref(prefs::kNtpPromoResourceCacheUpdate, 59 prefs->RegisterStringPref(prefs::kNtpPromoResourceCacheUpdate,
73 "0", 60 "0",
74 PrefService::UNSYNCABLE_PREF); 61 PrefService::UNSYNCABLE_PREF);
62 NotificationPromo::RegisterUserPrefs(prefs);
63
64 // TODO(achuith): Delete this in M21
Dan Beam 2012/06/08 18:49:47 M21 or M22? . and end.
achuithb 2012/06/08 22:29:08 Will fix.
75 prefs->RegisterDoublePref(prefs::kNtpCustomLogoStart, 65 prefs->RegisterDoublePref(prefs::kNtpCustomLogoStart,
76 0, 66 0,
77 PrefService::UNSYNCABLE_PREF); 67 PrefService::UNSYNCABLE_PREF);
78 prefs->RegisterDoublePref(prefs::kNtpCustomLogoEnd, 68 prefs->RegisterDoublePref(prefs::kNtpCustomLogoEnd,
79 0, 69 0,
80 PrefService::UNSYNCABLE_PREF); 70 PrefService::UNSYNCABLE_PREF);
81 NotificationPromo::RegisterUserPrefs(prefs); 71 prefs->ClearPref(prefs::kNtpCustomLogoStart);
82 } 72 prefs->ClearPref(prefs::kNtpCustomLogoEnd);
83
84 // static
85 chrome::VersionInfo::Channel PromoResourceService::GetChannel() {
86 // GetChannel hits the registry on Windows. See http://crbug.com/70898.
87 base::ThreadRestrictions::ScopedAllowIO allow_io;
88 return chrome::VersionInfo::GetChannel();
89 }
90
91 // static
92 bool PromoResourceService::IsBuildTargeted(chrome::VersionInfo::Channel channel,
93 int builds_allowed) {
94 if (builds_allowed == NO_BUILD ||
95 builds_allowed < 0 ||
96 builds_allowed > ALL_BUILDS) {
97 return false;
98 }
99 switch (channel) {
100 case chrome::VersionInfo::CHANNEL_CANARY:
101 return (CANARY_BUILD & builds_allowed) != 0;
102 case chrome::VersionInfo::CHANNEL_DEV:
103 return (DEV_BUILD & builds_allowed) != 0;
104 case chrome::VersionInfo::CHANNEL_BETA:
105 return (BETA_BUILD & builds_allowed) != 0;
106 case chrome::VersionInfo::CHANNEL_STABLE:
107 return (STABLE_BUILD & builds_allowed) != 0;
108 default:
109 // Show promos for local builds when using a custom promo URL.
110 return CommandLine::ForCurrentProcess()->HasSwitch(
111 switches::kPromoServerURL);
112 }
113 } 73 }
114 74
115 PromoResourceService::PromoResourceService(Profile* profile) 75 PromoResourceService::PromoResourceService(Profile* profile)
116 : WebResourceService(profile->GetPrefs(), 76 : WebResourceService(profile->GetPrefs(),
117 GetPromoResourceURL(), 77 GetPromoResourceURL(),
118 true, // append locale to URL 78 true, // append locale to URL
119 prefs::kNtpPromoResourceCacheUpdate, 79 prefs::kNtpPromoResourceCacheUpdate,
120 kStartResourceFetchDelay, 80 kStartResourceFetchDelay,
121 GetCacheUpdateDelay()), 81 GetCacheUpdateDelay()),
122 profile_(profile), 82 profile_(profile),
123 channel_(chrome::VersionInfo::CHANNEL_UNKNOWN), 83 ALLOW_THIS_IN_INITIALIZER_LIST(
124 ALLOW_THIS_IN_INITIALIZER_LIST(weak_ptr_factory_(this)), 84 weak_ptr_factory_(this)),
125 web_resource_update_scheduled_(false) { 85 web_resource_update_scheduled_(false) {
126 ScheduleNotificationOnInit(); 86 ScheduleNotificationOnInit();
127 } 87 }
128 88
129 PromoResourceService::~PromoResourceService() { } 89 PromoResourceService::~PromoResourceService() {
130
131 bool PromoResourceService::IsBuildTargeted(int builds_targeted) {
132 if (channel_ == chrome::VersionInfo::CHANNEL_UNKNOWN)
133 channel_ = GetChannel();
134
135 return IsBuildTargeted(channel_, builds_targeted);
136 }
137
138 void PromoResourceService::Unpack(const DictionaryValue& parsed_json) {
139 UnpackLogoSignal(parsed_json);
140 UnpackNotificationSignal(parsed_json);
141 UnpackWebStoreSignal(parsed_json);
142 } 90 }
143 91
144 void PromoResourceService::ScheduleNotification(double promo_start, 92 void PromoResourceService::ScheduleNotification(double promo_start,
145 double promo_end) { 93 double promo_end) {
146 if (promo_start > 0 && promo_end > 0) { 94 if (promo_start > 0 && promo_end > 0) {
147 int64 ms_until_start = 95 const int64 ms_until_start =
148 static_cast<int64>((base::Time::FromDoubleT( 96 static_cast<int64>((base::Time::FromDoubleT(
149 promo_start) - base::Time::Now()).InMilliseconds()); 97 promo_start) - base::Time::Now()).InMilliseconds());
150 int64 ms_until_end = 98 const int64 ms_until_end =
151 static_cast<int64>((base::Time::FromDoubleT( 99 static_cast<int64>((base::Time::FromDoubleT(
152 promo_end) - base::Time::Now()).InMilliseconds()); 100 promo_end) - base::Time::Now()).InMilliseconds());
153 if (ms_until_start > 0) 101 if (ms_until_start > 0)
154 PostNotification(ms_until_start); 102 PostNotification(ms_until_start);
155 if (ms_until_end > 0) { 103 if (ms_until_end > 0) {
156 PostNotification(ms_until_end); 104 PostNotification(ms_until_end);
157 if (ms_until_start <= 0) { 105 if (ms_until_start <= 0) {
158 // Notify immediately if time is between start and end. 106 // Notify immediately if time is between start and end.
159 PostNotification(0); 107 PostNotification(0);
160 } 108 }
161 } 109 }
162 } 110 }
163 } 111 }
164 112
165 void PromoResourceService::ScheduleNotificationOnInit() { 113 void PromoResourceService::ScheduleNotificationOnInit() {
166 std::string locale = g_browser_process->GetApplicationLocale(); 114 std::string locale = g_browser_process->GetApplicationLocale();
167 if (GetPromoServiceVersion() != kPromoServiceVersion || 115 if (GetPromoServiceVersion() != kPromoServiceVersion ||
168 GetPromoLocale() != locale) { 116 GetPromoLocale() != locale) {
169 // If the promo service has been upgraded or Chrome switched locales, 117 // If the promo service has been upgraded or Chrome switched locales,
170 // refresh the promos. 118 // refresh the promos.
171 // TODO(achuith): Mixing local_state and prefs does not work for 119 // TODO(achuith): Mixing local_state and prefs does not work for
172 // multi-profile case. We should probably store version/locale in prefs_ 120 // multi-profile case. We should probably store version/locale in prefs_
173 // as well. 121 // as well.
174 PrefService* local_state = g_browser_process->local_state(); 122 PrefService* local_state = g_browser_process->local_state();
175 local_state->SetInteger(prefs::kNtpPromoVersion, kPromoServiceVersion); 123 local_state->SetInteger(prefs::kNtpPromoVersion, kPromoServiceVersion);
176 local_state->SetString(prefs::kNtpPromoLocale, locale); 124 local_state->SetString(prefs::kNtpPromoLocale, locale);
177 prefs_->ClearPref(prefs::kNtpPromoResourceCacheUpdate); 125 prefs_->ClearPref(prefs::kNtpPromoResourceCacheUpdate);
178 AppsPromo::ClearPromo();
179 PostNotification(0); 126 PostNotification(0);
180 } else { 127 } else {
181 // If the promo start is in the future, set a notification task to 128 // If the promo start is in the future, set a notification task to
182 // invalidate the NTP cache at the time of the promo start. 129 // invalidate the NTP cache at the time of the promo start.
183 double promo_start = prefs_->GetDouble(prefs::kNtpPromoStart); 130 double promo_start = prefs_->GetDouble(prefs::kNtpPromoStart);
184 double promo_end = prefs_->GetDouble(prefs::kNtpPromoEnd); 131 double promo_end = prefs_->GetDouble(prefs::kNtpPromoEnd);
185 ScheduleNotification(promo_start, promo_end); 132 ScheduleNotification(promo_start, promo_end);
186 } 133 }
187 } 134 }
188 135
(...skipping 26 matching lines...) Expand all
215 int PromoResourceService::GetPromoServiceVersion() { 162 int PromoResourceService::GetPromoServiceVersion() {
216 PrefService* local_state = g_browser_process->local_state(); 163 PrefService* local_state = g_browser_process->local_state();
217 return local_state->GetInteger(prefs::kNtpPromoVersion); 164 return local_state->GetInteger(prefs::kNtpPromoVersion);
218 } 165 }
219 166
220 std::string PromoResourceService::GetPromoLocale() { 167 std::string PromoResourceService::GetPromoLocale() {
221 PrefService* local_state = g_browser_process->local_state(); 168 PrefService* local_state = g_browser_process->local_state();
222 return local_state->GetString(prefs::kNtpPromoLocale); 169 return local_state->GetString(prefs::kNtpPromoLocale);
223 } 170 }
224 171
225 void PromoResourceService::UnpackNotificationSignal( 172 void PromoResourceService::Unpack(const DictionaryValue& parsed_json) {
226 const DictionaryValue& parsed_json) {
227 NotificationPromo notification_promo(profile_); 173 NotificationPromo notification_promo(profile_);
228 notification_promo.InitFromJson(parsed_json); 174 notification_promo.InitFromJson(parsed_json);
229 175
230 if (notification_promo.new_notification()) { 176 if (notification_promo.new_notification()) {
231 ScheduleNotification(notification_promo.StartTimeForGroup(), 177 ScheduleNotification(notification_promo.StartTimeForGroup(),
232 notification_promo.EndTime()); 178 notification_promo.EndTime());
233 } 179 }
234 } 180 }
235 181
236 bool PromoResourceService::CanShowNotificationPromo(Profile* profile) { 182 bool PromoResourceService::CanShowNotificationPromo(Profile* profile) {
237 NotificationPromo notification_promo(profile); 183 NotificationPromo notification_promo(profile);
238 notification_promo.InitFromPrefs(); 184 notification_promo.InitFromPrefs();
239 return notification_promo.CanShow(); 185 return notification_promo.CanShow();
240 } 186 }
241
242 void PromoResourceService::UnpackWebStoreSignal(
243 const DictionaryValue& parsed_json) {
244 DictionaryValue* topic_dict;
245 ListValue* answer_list;
246
247 bool is_webstore_active = false;
248 bool signal_found = false;
249 AppsPromo::PromoData promo_data;
250 std::string promo_link = "";
251 std::string promo_logo = "";
252 int target_builds = 0;
253
254 if (!parsed_json.GetDictionary("topic", &topic_dict) ||
255 !topic_dict->GetList("answers", &answer_list))
256 return;
257
258 for (ListValue::const_iterator answer_iter = answer_list->begin();
259 answer_iter != answer_list->end(); ++answer_iter) {
260 if (!(*answer_iter)->IsType(Value::TYPE_DICTIONARY))
261 continue;
262 DictionaryValue* a_dic =
263 static_cast<DictionaryValue*>(*answer_iter);
264
265 // The "name" field has three different values packed into it, each
266 // separated by a ':'.
267 std::string name;
268 if (!a_dic->GetString("name", &name))
269 continue;
270
271 // (1) the string "webstore_promo"
272 size_t split = name.find(":");
273 if (split == std::string::npos || name.substr(0, split) != "webstore_promo")
274 continue;
275
276 // If the "webstore_promo" string was found, that's enough to activate the
277 // apps section even if the rest of the promo fails parsing.
278 is_webstore_active = true;
279
280 // (2) an integer specifying which builds the promo targets
281 name = name.substr(split+1);
282 split = name.find(':');
283 if (split == std::string::npos ||
284 !base::StringToInt(name.substr(0, split), &target_builds))
285 continue;
286
287 // (3) an integer specifying what users should maximize the promo
288 name = name.substr(split+1);
289 split = name.find(':');
290 if (split == std::string::npos ||
291 !base::StringToInt(name.substr(0, split), &promo_data.user_group))
292 continue;
293
294 // (4) optional text that specifies a URL of a logo image
295 promo_logo = name.substr(split+1);
296
297 if (!a_dic->GetString(kAnswerIdProperty, &promo_data.id) ||
298 !a_dic->GetString(kWebStoreHeaderProperty, &promo_data.header) ||
299 !a_dic->GetString(kWebStoreButtonProperty, &promo_data.button) ||
300 !a_dic->GetString(kWebStoreLinkProperty, &promo_link) ||
301 !a_dic->GetString(kWebStoreExpireProperty, &promo_data.expire))
302 continue;
303
304 if (IsBuildTargeted(target_builds)) {
305 // The downloader will set the promo prefs and send the
306 // NOTIFICATION_WEB_STORE_PROMO_LOADED notification.
307 promo_data.link = GURL(promo_link);
308 promo_data.logo = GURL(promo_logo);
309 apps_promo_logo_fetcher_.reset(
310 new AppsPromoLogoFetcher(profile_, promo_data));
311 signal_found = true;
312 break;
313 }
314 }
315
316 if (!signal_found) {
317 // If no web store promos target this build, then clear all the prefs.
318 AppsPromo::ClearPromo();
319 }
320
321 AppsPromo::SetWebStoreSupportedForLocale(is_webstore_active);
322
323 return;
324 }
325
326 void PromoResourceService::UnpackLogoSignal(
327 const DictionaryValue& parsed_json) {
328 DictionaryValue* topic_dict;
329 ListValue* answer_list;
330 double old_logo_start = 0;
331 double old_logo_end = 0;
332 double logo_start = 0;
333 double logo_end = 0;
334
335 // Check for preexisting start and end values.
336 if (prefs_->HasPrefPath(prefs::kNtpCustomLogoStart) &&
337 prefs_->HasPrefPath(prefs::kNtpCustomLogoEnd)) {
338 old_logo_start = prefs_->GetDouble(prefs::kNtpCustomLogoStart);
339 old_logo_end = prefs_->GetDouble(prefs::kNtpCustomLogoEnd);
340 }
341
342 // Check for newly received start and end values.
343 if (parsed_json.GetDictionary("topic", &topic_dict)) {
344 if (topic_dict->GetList("answers", &answer_list)) {
345 std::string logo_start_string = "";
346 std::string logo_end_string = "";
347 for (ListValue::const_iterator answer_iter = answer_list->begin();
348 answer_iter != answer_list->end(); ++answer_iter) {
349 if (!(*answer_iter)->IsType(Value::TYPE_DICTIONARY))
350 continue;
351 DictionaryValue* a_dic =
352 static_cast<DictionaryValue*>(*answer_iter);
353 std::string logo_signal;
354 if (a_dic->GetString("name", &logo_signal)) {
355 if (logo_signal == "custom_logo_start") {
356 a_dic->GetString("inproduct", &logo_start_string);
357 } else if (logo_signal == "custom_logo_end") {
358 a_dic->GetString("inproduct", &logo_end_string);
359 }
360 }
361 }
362 if (!logo_start_string.empty() &&
363 logo_start_string.length() > 0 &&
364 !logo_end_string.empty() &&
365 logo_end_string.length() > 0) {
366 base::Time start_time;
367 base::Time end_time;
368 if (base::Time::FromString(logo_start_string.c_str(), &start_time) &&
369 base::Time::FromString(logo_end_string.c_str(), &end_time)) {
370 logo_start = start_time.ToDoubleT();
371 logo_end = end_time.ToDoubleT();
372 }
373 }
374 }
375 }
376
377 // If logo start or end times have changed, trigger a new web resource
378 // notification, so that the logo on the NTP is updated. This check is
379 // outside the reading of the web resource data, because the absence of
380 // dates counts as a triggering change if there were dates before.
381 if (!(old_logo_start == logo_start) ||
382 !(old_logo_end == logo_end)) {
383 prefs_->SetDouble(prefs::kNtpCustomLogoStart, logo_start);
384 prefs_->SetDouble(prefs::kNtpCustomLogoEnd, logo_end);
385 content::NotificationService* service =
386 content::NotificationService::current();
387 service->Notify(chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED,
388 content::Source<WebResourceService>(this),
389 content::NotificationService::NoDetails());
390 }
391 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698