OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 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 | 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/rand_util.h" |
9 #include "base/string_number_conversions.h" | 9 #include "base/string_number_conversions.h" |
10 #include "base/threading/thread_restrictions.h" | 10 #include "base/threading/thread_restrictions.h" |
(...skipping 19 matching lines...) Expand all Loading... |
30 static const int kStartResourceFetchDelay = 5000; | 30 static const int kStartResourceFetchDelay = 5000; |
31 | 31 |
32 // Delay between calls to update the cache (48 hours), and 3 min in debug mode. | 32 // Delay between calls to update the cache (48 hours), and 3 min in debug mode. |
33 static const int kCacheUpdateDelay = 48 * 60 * 60 * 1000; | 33 static const int kCacheUpdateDelay = 48 * 60 * 60 * 1000; |
34 static const int kTestCacheUpdateDelay = 3 * 60 * 1000; | 34 static const int kTestCacheUpdateDelay = 3 * 60 * 1000; |
35 | 35 |
36 // The version of the service (used to expire the cache when upgrading Chrome | 36 // The version of the service (used to expire the cache when upgrading Chrome |
37 // to versions with different types of promos). | 37 // to versions with different types of promos). |
38 static const int kPromoServiceVersion = 2; | 38 static const int kPromoServiceVersion = 2; |
39 | 39 |
40 // The number of groups sync promo users will be divided into (which gives us a | 40 // The number of groups sign-in promo users will be divided into (which gives us |
41 // 1/N granularity when targeting more groups). | 41 // a 1/N granularity when targeting more groups). |
42 static const int kSyncPromoNumberOfGroups = 100; | 42 static const int kNTPSignInPromoNumberOfGroups = 100; |
43 | 43 |
44 // Properties used by the server. | 44 // Properties used by the server. |
45 static const char kAnswerIdProperty[] = "answer_id"; | 45 static const char kAnswerIdProperty[] = "answer_id"; |
46 static const char kWebStoreHeaderProperty[] = "question"; | 46 static const char kWebStoreHeaderProperty[] = "question"; |
47 static const char kWebStoreButtonProperty[] = "inproduct_target"; | 47 static const char kWebStoreButtonProperty[] = "inproduct_target"; |
48 static const char kWebStoreLinkProperty[] = "inproduct"; | 48 static const char kWebStoreLinkProperty[] = "inproduct"; |
49 static const char kWebStoreExpireProperty[] = "tooltip"; | 49 static const char kWebStoreExpireProperty[] = "tooltip"; |
50 | 50 |
51 const char* GetPromoResourceURL() { | 51 const char* GetPromoResourceURL() { |
52 std::string promo_server_url = CommandLine::ForCurrentProcess()-> | 52 std::string promo_server_url = CommandLine::ForCurrentProcess()-> |
(...skipping 24 matching lines...) Expand all Loading... |
77 } | 77 } |
78 | 78 |
79 // static | 79 // static |
80 void PromoResourceService::RegisterUserPrefs(PrefService* prefs) { | 80 void PromoResourceService::RegisterUserPrefs(PrefService* prefs) { |
81 prefs->RegisterDoublePref(prefs::kNTPCustomLogoStart, | 81 prefs->RegisterDoublePref(prefs::kNTPCustomLogoStart, |
82 0, | 82 0, |
83 PrefService::UNSYNCABLE_PREF); | 83 PrefService::UNSYNCABLE_PREF); |
84 prefs->RegisterDoublePref(prefs::kNTPCustomLogoEnd, | 84 prefs->RegisterDoublePref(prefs::kNTPCustomLogoEnd, |
85 0, | 85 0, |
86 PrefService::UNSYNCABLE_PREF); | 86 PrefService::UNSYNCABLE_PREF); |
87 prefs->RegisterIntegerPref(prefs::kNTPSyncPromoGroup, | 87 prefs->RegisterIntegerPref(prefs::kNTPSignInPromoGroup, |
88 0, | 88 0, |
89 PrefService::UNSYNCABLE_PREF); | 89 PrefService::UNSYNCABLE_PREF); |
90 prefs->RegisterIntegerPref(prefs::kNTPSyncPromoGroupMax, | 90 prefs->RegisterIntegerPref(prefs::kNTPSignInPromoGroupMax, |
91 0, | 91 0, |
92 PrefService::UNSYNCABLE_PREF); | 92 PrefService::UNSYNCABLE_PREF); |
93 NotificationPromo::RegisterUserPrefs(prefs); | 93 NotificationPromo::RegisterUserPrefs(prefs); |
94 } | 94 } |
95 | 95 |
96 // static | 96 // static |
97 chrome::VersionInfo::Channel PromoResourceService::GetChannel() { | 97 chrome::VersionInfo::Channel PromoResourceService::GetChannel() { |
98 // GetChannel hits the registry on Windows. See http://crbug.com/70898. | 98 // GetChannel hits the registry on Windows. See http://crbug.com/70898. |
99 base::ThreadRestrictions::ScopedAllowIO allow_io; | 99 base::ThreadRestrictions::ScopedAllowIO allow_io; |
100 return chrome::VersionInfo::GetChannel(); | 100 return chrome::VersionInfo::GetChannel(); |
(...skipping 46 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
147 if (channel_ == chrome::VersionInfo::CHANNEL_UNKNOWN) | 147 if (channel_ == chrome::VersionInfo::CHANNEL_UNKNOWN) |
148 channel_ = GetChannel(); | 148 channel_ = GetChannel(); |
149 | 149 |
150 return IsBuildTargeted(channel_, builds_targeted); | 150 return IsBuildTargeted(channel_, builds_targeted); |
151 } | 151 } |
152 | 152 |
153 void PromoResourceService::Unpack(const DictionaryValue& parsed_json) { | 153 void PromoResourceService::Unpack(const DictionaryValue& parsed_json) { |
154 UnpackLogoSignal(parsed_json); | 154 UnpackLogoSignal(parsed_json); |
155 UnpackNotificationSignal(parsed_json); | 155 UnpackNotificationSignal(parsed_json); |
156 UnpackWebStoreSignal(parsed_json); | 156 UnpackWebStoreSignal(parsed_json); |
157 UnpackSyncPromoSignal(parsed_json); | 157 UnpackNTPSignInPromoSignal(parsed_json); |
158 } | 158 } |
159 | 159 |
160 void PromoResourceService::OnNewNotification(double start, double end) { | 160 void PromoResourceService::OnNewNotification(double start, double end) { |
161 ScheduleNotification(start, end); | 161 ScheduleNotification(start, end); |
162 } | 162 } |
163 | 163 |
164 void PromoResourceService::ScheduleNotification(double promo_start, | 164 void PromoResourceService::ScheduleNotification(double promo_start, |
165 double promo_end) { | 165 double promo_end) { |
166 if (promo_start > 0 && promo_end > 0) { | 166 if (promo_start > 0 && promo_end > 0) { |
167 int64 ms_until_start = | 167 int64 ms_until_start = |
(...skipping 201 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
369 prefs_->SetDouble(prefs::kNTPCustomLogoStart, logo_start); | 369 prefs_->SetDouble(prefs::kNTPCustomLogoStart, logo_start); |
370 prefs_->SetDouble(prefs::kNTPCustomLogoEnd, logo_end); | 370 prefs_->SetDouble(prefs::kNTPCustomLogoEnd, logo_end); |
371 content::NotificationService* service = | 371 content::NotificationService* service = |
372 content::NotificationService::current(); | 372 content::NotificationService::current(); |
373 service->Notify(chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED, | 373 service->Notify(chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED, |
374 content::Source<WebResourceService>(this), | 374 content::Source<WebResourceService>(this), |
375 content::NotificationService::NoDetails()); | 375 content::NotificationService::NoDetails()); |
376 } | 376 } |
377 } | 377 } |
378 | 378 |
379 void PromoResourceService::UnpackSyncPromoSignal( | 379 void PromoResourceService::UnpackNTPSignInPromoSignal( |
380 const DictionaryValue& parsed_json) { | 380 const DictionaryValue& parsed_json) { |
381 #if defined(OS_CHROMEOS) | 381 #if defined(OS_CHROMEOS) |
382 // Don't bother with this signal on ChromeOS. Users are already synced. | 382 // Don't bother with this signal on ChromeOS. Users are already synced. |
383 return; | 383 return; |
384 #endif | 384 #endif |
385 | 385 |
386 DictionaryValue* topic_dict; | 386 DictionaryValue* topic_dict; |
387 if (!parsed_json.GetDictionary("topic", &topic_dict)) | 387 if (!parsed_json.GetDictionary("topic", &topic_dict)) |
388 return; | 388 return; |
389 | 389 |
390 ListValue* answer_list; | 390 ListValue* answer_list; |
391 if (!topic_dict->GetList("answers", &answer_list)) | 391 if (!topic_dict->GetList("answers", &answer_list)) |
392 return; | 392 return; |
393 | 393 |
394 std::string question; | 394 std::string question; |
395 for (ListValue::const_iterator answer_iter = answer_list->begin(); | 395 for (ListValue::const_iterator answer_iter = answer_list->begin(); |
396 answer_iter != answer_list->end(); ++answer_iter) { | 396 answer_iter != answer_list->end(); ++answer_iter) { |
397 if (!(*answer_iter)->IsType(Value::TYPE_DICTIONARY)) | 397 if (!(*answer_iter)->IsType(Value::TYPE_DICTIONARY)) |
398 continue; | 398 continue; |
399 DictionaryValue* a_dic = static_cast<DictionaryValue*>(*answer_iter); | 399 DictionaryValue* a_dic = static_cast<DictionaryValue*>(*answer_iter); |
400 std::string name; | 400 std::string name; |
401 if (a_dic->GetString("name", &name) && name == "sync_promo") { | 401 if (a_dic->GetString("name", &name) && name == "sign_in_promo") { |
402 a_dic->GetString("question", &question); | 402 a_dic->GetString("question", &question); |
403 break; | 403 break; |
404 } | 404 } |
405 } | 405 } |
406 | 406 |
407 int new_build; | 407 int new_build; |
408 int new_group_max; | 408 int new_group_max; |
409 size_t build_index = question.find(":"); | 409 size_t build_index = question.find(":"); |
410 if (std::string::npos == build_index || | 410 if (std::string::npos == build_index || |
411 !base::StringToInt(question.substr(0, build_index), &new_build) || | 411 !base::StringToInt(question.substr(0, build_index), &new_build) || |
412 !IsBuildTargeted(new_build) || | 412 !IsBuildTargeted(new_build) || |
413 !base::StringToInt(question.substr(build_index + 1), &new_group_max)) { | 413 !base::StringToInt(question.substr(build_index + 1), &new_group_max)) { |
414 // If anything about the response was invalid or this build is no longer | 414 // If anything about the response was invalid or this build is no longer |
415 // targeted and there are existing prefs, clear them and notify. | 415 // targeted and there are existing prefs, clear them and notify. |
416 if (prefs_->HasPrefPath(prefs::kNTPSyncPromoGroup) || | 416 if (prefs_->HasPrefPath(prefs::kNTPSignInPromoGroup) || |
417 prefs_->HasPrefPath(prefs::kNTPSyncPromoGroupMax)) { | 417 prefs_->HasPrefPath(prefs::kNTPSignInPromoGroupMax)) { |
418 // Make sure we clear first, as the following notification may possibly | 418 // Make sure we clear first, as the following notification may possibly |
419 // depend on calling CanShowSyncPromo synchronously. | 419 // depend on calling CanShowNTPSignInPromo synchronously. |
420 prefs_->ClearPref(prefs::kNTPSyncPromoGroup); | 420 prefs_->ClearPref(prefs::kNTPSignInPromoGroup); |
421 prefs_->ClearPref(prefs::kNTPSyncPromoGroupMax); | 421 prefs_->ClearPref(prefs::kNTPSignInPromoGroupMax); |
422 // Notify the NTP resource cache if the promo has been disabled. | 422 // Notify the NTP resource cache if the promo has been disabled. |
423 content::NotificationService::current()->Notify( | 423 content::NotificationService::current()->Notify( |
424 chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED, | 424 chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED, |
425 content::Source<WebResourceService>(this), | 425 content::Source<WebResourceService>(this), |
426 content::NotificationService::NoDetails()); | 426 content::NotificationService::NoDetails()); |
427 } | 427 } |
428 return; | 428 return; |
429 } | 429 } |
430 | 430 |
431 // TODO(dbeam): Add automagic hour group bumper to parsing? | 431 // TODO(dbeam): Add automagic hour group bumper to parsing? |
432 | 432 |
433 // If we successfully parsed a response and it differs from our user prefs, | 433 // If we successfully parsed a response and it differs from our user prefs, |
434 // set pref for next time to compare. | 434 // set pref for next time to compare. |
435 if (new_group_max != prefs_->GetInteger(prefs::kNTPSyncPromoGroupMax)) | 435 if (new_group_max != prefs_->GetInteger(prefs::kNTPSignInPromoGroupMax)) |
436 prefs_->SetInteger(prefs::kNTPSyncPromoGroupMax, new_group_max); | 436 prefs_->SetInteger(prefs::kNTPSignInPromoGroupMax, new_group_max); |
437 } | 437 } |
438 | 438 |
439 // static | 439 // static |
440 bool PromoResourceService::CanShowSyncPromo(Profile* profile) { | 440 bool PromoResourceService::CanShowNTPSignInPromo(Profile* profile) { |
441 DCHECK(profile); | 441 DCHECK(profile); |
442 PrefService* prefs = profile->GetPrefs(); | 442 PrefService* prefs = profile->GetPrefs(); |
443 | 443 |
444 if (!prefs->HasPrefPath(prefs::kNTPSyncPromoGroupMax)) | 444 if (!prefs->HasPrefPath(prefs::kNTPSignInPromoGroupMax)) |
445 return false; | 445 return false; |
446 | 446 |
447 // If there's a max group set and the user hasn't been bucketed yet, do it. | 447 // If there's a max group set and the user hasn't been bucketed yet, do it. |
448 if (!prefs->HasPrefPath(prefs::kNTPSyncPromoGroup)) { | 448 if (!prefs->HasPrefPath(prefs::kNTPSignInPromoGroup)) { |
449 prefs->SetInteger(prefs::kNTPSyncPromoGroup, | 449 prefs->SetInteger(prefs::kNTPSignInPromoGroup, |
450 base::RandInt(1, kSyncPromoNumberOfGroups)); | 450 base::RandInt(1, kNTPSignInPromoNumberOfGroups)); |
451 } | 451 } |
452 | 452 |
453 // A response is not kept if the build wasn't targeted, so the only thing | 453 // A response is not kept if the build wasn't targeted, so the only thing |
454 // required to check is the group this client has been tagged in. | 454 // required to check is the group this client has been tagged in. |
455 return prefs->GetInteger(prefs::kNTPSyncPromoGroupMax) >= | 455 return prefs->GetInteger(prefs::kNTPSignInPromoGroupMax) >= |
456 prefs->GetInteger(prefs::kNTPSyncPromoGroup); | 456 prefs->GetInteger(prefs::kNTPSignInPromoGroup); |
457 } | 457 } |
OLD | NEW |