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

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

Issue 6313009: Add possibility to divide chrome users into groups of equal size, and change ... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: '' Created 9 years, 11 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) 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/web_resource_service.h" 5 #include "chrome/browser/web_resource/web_resource_service.h"
6 6
7 #include <string>
8
7 #include "base/command_line.h" 9 #include "base/command_line.h"
8 #include "base/file_path.h" 10 #include "base/file_path.h"
9 #include "base/string_util.h" 11 #include "base/string_util.h"
10 #include "base/string_number_conversions.h" 12 #include "base/string_number_conversions.h"
11 #include "base/time.h" 13 #include "base/time.h"
12 #include "base/utf_string_conversions.h" 14 #include "base/utf_string_conversions.h"
13 #include "base/values.h" 15 #include "base/values.h"
14 #include "chrome/browser/browser_process.h" 16 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/browser_thread.h" 17 #include "chrome/browser/browser_thread.h"
16 #include "chrome/browser/extensions/extension_service.h" 18 #include "chrome/browser/extensions/extension_service.h"
19 #include "chrome/browser/platform_util.h"
17 #include "chrome/browser/profiles/profile.h" 20 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/sync/sync_ui_util.h" 21 #include "chrome/browser/sync/sync_ui_util.h"
19 #include "chrome/common/chrome_switches.h" 22 #include "chrome/common/chrome_switches.h"
20 #include "chrome/common/extensions/extension.h" 23 #include "chrome/common/extensions/extension.h"
21 #include "chrome/common/net/url_fetcher.h" 24 #include "chrome/common/net/url_fetcher.h"
22 #include "chrome/common/notification_service.h" 25 #include "chrome/common/notification_service.h"
23 #include "chrome/common/notification_type.h" 26 #include "chrome/common/notification_type.h"
24 #include "chrome/common/pref_names.h" 27 #include "chrome/common/pref_names.h"
25 #include "googleurl/src/gurl.h" 28 #include "googleurl/src/gurl.h"
26 #include "net/base/load_flags.h" 29 #include "net/base/load_flags.h"
27 #include "net/url_request/url_request_status.h" 30 #include "net/url_request/url_request_status.h"
28 31
29 namespace { 32 namespace {
30 33
31 // Delay on first fetch so we don't interfere with startup. 34 // Delay on first fetch so we don't interfere with startup.
32 static const int kStartResourceFetchDelay = 5000; 35 static const int kStartResourceFetchDelay = 5000;
33 36
34 // Delay between calls to update the cache (48 hours). 37 // Delay between calls to update the cache (48 hours).
35 static const int kCacheUpdateDelay = 48 * 60 * 60 * 1000; 38 static const int kCacheUpdateDelay = 48 * 60 * 60 * 1000;
36 39
40 // Users are randomly assigned to one of kNTPPromoGroupSize buckets, in order
41 // to be able to roll out promos slowly, or display different promos to
42 // different groups.
43 static const int kNTPPromoGroupSize = 16;
44
45 // Maximum number of hours for each time slice (4 weeks).
46 static const int kMaxTimeSliceHours = 24 * 7 * 4;
47
48 // Used to determine which build type should be shown a given promo.
49 enum BuildType {
50 DEV_BUILD = 1,
51 BETA_BUILD = 1 << 1,
52 STABLE_BUILD = 1 << 2,
53 };
54
37 } // namespace 55 } // namespace
38 56
39 const char* WebResourceService::kCurrentTipPrefName = "current_tip"; 57 const char* WebResourceService::kCurrentTipPrefName = "current_tip";
40 const char* WebResourceService::kTipCachePrefName = "tips"; 58 const char* WebResourceService::kTipCachePrefName = "tips";
41 59
42 class WebResourceService::WebResourceFetcher 60 class WebResourceService::WebResourceFetcher
43 : public URLFetcher::Delegate { 61 : public URLFetcher::Delegate {
44 public: 62 public:
45 explicit WebResourceFetcher(WebResourceService* web_resource_service) : 63 explicit WebResourceFetcher(WebResourceService* web_resource_service) :
46 ALLOW_THIS_IN_INITIALIZER_LIST(fetcher_factory_(this)), 64 ALLOW_THIS_IN_INITIALIZER_LIST(fetcher_factory_(this)),
(...skipping 173 matching lines...) Expand 10 before | Expand all | Expand 10 after
220 cache_update_delay_ = kCacheUpdateDelay; 238 cache_update_delay_ = kCacheUpdateDelay;
221 resource_dispatcher_host_ = g_browser_process->resource_dispatcher_host(); 239 resource_dispatcher_host_ = g_browser_process->resource_dispatcher_host();
222 web_resource_fetcher_.reset(new WebResourceFetcher(this)); 240 web_resource_fetcher_.reset(new WebResourceFetcher(this));
223 prefs_->RegisterStringPref(prefs::kNTPWebResourceCacheUpdate, "0"); 241 prefs_->RegisterStringPref(prefs::kNTPWebResourceCacheUpdate, "0");
224 prefs_->RegisterRealPref(prefs::kNTPCustomLogoStart, 0); 242 prefs_->RegisterRealPref(prefs::kNTPCustomLogoStart, 0);
225 prefs_->RegisterRealPref(prefs::kNTPCustomLogoEnd, 0); 243 prefs_->RegisterRealPref(prefs::kNTPCustomLogoEnd, 0);
226 prefs_->RegisterRealPref(prefs::kNTPPromoStart, 0); 244 prefs_->RegisterRealPref(prefs::kNTPPromoStart, 0);
227 prefs_->RegisterRealPref(prefs::kNTPPromoEnd, 0); 245 prefs_->RegisterRealPref(prefs::kNTPPromoEnd, 0);
228 prefs_->RegisterStringPref(prefs::kNTPPromoLine, std::string()); 246 prefs_->RegisterStringPref(prefs::kNTPPromoLine, std::string());
229 prefs_->RegisterBooleanPref(prefs::kNTPPromoClosed, false); 247 prefs_->RegisterBooleanPref(prefs::kNTPPromoClosed, false);
248 prefs_->RegisterIntegerPref(prefs::kNTPPromoGroup, -1);
249 prefs_->RegisterIntegerPref(prefs::kNTPPromoBuild,
250 DEV_BUILD | BETA_BUILD | STABLE_BUILD);
251 prefs_->RegisterIntegerPref(prefs::kNTPPromoGroupTimeSlice, 0);
230 252
231 // If the promo start is in the future, set a notification task to invalidate 253 // If the promo start is in the future, set a notification task to invalidate
232 // the NTP cache at the time of the promo start. 254 // the NTP cache at the time of the promo start.
233 double promo_start = prefs_->GetReal(prefs::kNTPPromoStart); 255 double promo_start = prefs_->GetReal(prefs::kNTPPromoStart);
234 double promo_end = prefs_->GetReal(prefs::kNTPPromoEnd); 256 double promo_end = prefs_->GetReal(prefs::kNTPPromoEnd);
235 ScheduleNotification(promo_start, promo_end); 257 ScheduleNotification(promo_start, promo_end);
236 } 258 }
237 259
238 void WebResourceService::EndFetch() { 260 void WebResourceService::EndFetch() {
239 in_fetch_ = false; 261 in_fetch_ = false;
240 } 262 }
241 263
242 void WebResourceService::OnWebResourceUnpacked( 264 void WebResourceService::OnWebResourceUnpacked(
243 const DictionaryValue& parsed_json) { 265 const DictionaryValue& parsed_json) {
244 UnpackLogoSignal(parsed_json); 266 UnpackLogoSignal(parsed_json);
245 if (WebResourceServiceUtil::CanShowPromo(profile_)) 267 UnpackPromoSignal(parsed_json);
246 UnpackPromoSignal(parsed_json);
247 EndFetch(); 268 EndFetch();
248 } 269 }
249 270
250 void WebResourceService::WebResourceStateChange() { 271 void WebResourceService::WebResourceStateChange() {
251 web_resource_update_scheduled_ = false; 272 web_resource_update_scheduled_ = false;
252 NotificationService* service = NotificationService::current(); 273 NotificationService* service = NotificationService::current();
253 service->Notify(NotificationType::WEB_RESOURCE_STATE_CHANGED, 274 service->Notify(NotificationType::WEB_RESOURCE_STATE_CHANGED,
254 Source<WebResourceService>(this), 275 Source<WebResourceService>(this),
255 NotificationService::NoDetails()); 276 NotificationService::NoDetails());
256 } 277 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 old_promo_start = prefs_->GetReal(prefs::kNTPPromoStart); 391 old_promo_start = prefs_->GetReal(prefs::kNTPPromoStart);
371 old_promo_end = prefs_->GetReal(prefs::kNTPPromoEnd); 392 old_promo_end = prefs_->GetReal(prefs::kNTPPromoEnd);
372 } 393 }
373 394
374 // Check for newly received start and end values. 395 // Check for newly received start and end values.
375 if (parsed_json.GetDictionary("topic", &topic_dict)) { 396 if (parsed_json.GetDictionary("topic", &topic_dict)) {
376 if (topic_dict->GetList("answers", &answer_list)) { 397 if (topic_dict->GetList("answers", &answer_list)) {
377 std::string promo_start_string = ""; 398 std::string promo_start_string = "";
378 std::string promo_end_string = ""; 399 std::string promo_end_string = "";
379 std::string promo_string = ""; 400 std::string promo_string = "";
401 std::string promo_build = "";
402 int promo_build_type;
403 int time_slice_hrs;
380 for (ListValue::const_iterator tip_iter = answer_list->begin(); 404 for (ListValue::const_iterator tip_iter = answer_list->begin();
381 tip_iter != answer_list->end(); ++tip_iter) { 405 tip_iter != answer_list->end(); ++tip_iter) {
382 if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY)) 406 if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY))
383 continue; 407 continue;
384 DictionaryValue* a_dic = 408 DictionaryValue* a_dic =
385 static_cast<DictionaryValue*>(*tip_iter); 409 static_cast<DictionaryValue*>(*tip_iter);
386 std::string promo_signal; 410 std::string promo_signal;
387 if (a_dic->GetString("name", &promo_signal)) { 411 if (a_dic->GetString("name", &promo_signal)) {
388 if (promo_signal == "promo_start") { 412 if (promo_signal == "promo_start") {
413 a_dic->GetString("question", &promo_build);
414 size_t split = promo_build.find(":");
415 if (split != std::string::npos &&
416 base::StringToInt(promo_build.substr(0, split),
417 &promo_build_type) &&
418 base::StringToInt(promo_build.substr(split+1),
419 &time_slice_hrs) &&
420 promo_build_type >= 0 &&
421 promo_build_type <= (DEV_BUILD | BETA_BUILD | STABLE_BUILD) &&
422 time_slice_hrs >= 0 &&
423 time_slice_hrs <= kMaxTimeSliceHours) {
424 prefs_->SetInteger(prefs::kNTPPromoBuild, promo_build_type);
425 prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice,
426 time_slice_hrs);
427 } else {
428 // If no time data or bad time data are set, show promo on all
429 // builds with no time slicing.
430 prefs_->SetInteger(prefs::kNTPPromoBuild,
431 DEV_BUILD | BETA_BUILD | STABLE_BUILD);
432 prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice, 0);
433 }
389 a_dic->GetString("inproduct", &promo_start_string); 434 a_dic->GetString("inproduct", &promo_start_string);
390 a_dic->GetString("tooltip", &promo_string); 435 a_dic->GetString("tooltip", &promo_string);
391 prefs_->SetString(prefs::kNTPPromoLine, promo_string); 436 prefs_->SetString(prefs::kNTPPromoLine, promo_string);
437 srand(static_cast<uint32>(time(NULL)));
438 prefs_->SetInteger(prefs::kNTPPromoGroup,
439 rand() % kNTPPromoGroupSize);
392 } else if (promo_signal == "promo_end") { 440 } else if (promo_signal == "promo_end") {
393 a_dic->GetString("inproduct", &promo_end_string); 441 a_dic->GetString("inproduct", &promo_end_string);
394 } 442 }
395 } 443 }
396 } 444 }
397 if (!promo_start_string.empty() && 445 if (!promo_start_string.empty() &&
398 promo_start_string.length() > 0 && 446 promo_start_string.length() > 0 &&
399 !promo_end_string.empty() && 447 !promo_end_string.empty() &&
400 promo_end_string.length() > 0) { 448 promo_end_string.length() > 0) {
401 base::Time start_time; 449 base::Time start_time;
402 base::Time end_time; 450 base::Time end_time;
403 if (base::Time::FromString( 451 if (base::Time::FromString(
404 ASCIIToWide(promo_start_string).c_str(), &start_time) && 452 ASCIIToWide(promo_start_string).c_str(), &start_time) &&
405 base::Time::FromString( 453 base::Time::FromString(
406 ASCIIToWide(promo_end_string).c_str(), &end_time)) { 454 ASCIIToWide(promo_end_string).c_str(), &end_time)) {
407 promo_start = start_time.ToDoubleT(); 455 // Add group time slice, adjusted from hours to seconds.
456 promo_start = start_time.ToDoubleT() +
457 (prefs_->FindPreference(prefs::kNTPPromoGroup) ?
arv (Not doing code reviews) 2011/01/24 18:15:11 useless parentheses
Miranda Callahan 2011/01/24 18:39:22 I wish they were, because they're kind of ugly --
458 prefs_->GetInteger(prefs::kNTPPromoGroup) *
459 time_slice_hrs * 60 * 60 : 0);
408 promo_end = end_time.ToDoubleT(); 460 promo_end = end_time.ToDoubleT();
409 } 461 }
410 } 462 }
411 } 463 }
412 } 464 }
413 465
414 // If start or end times have changed, trigger a new web resource 466 // If start or end times have changed, trigger a new web resource
415 // notification, so that the logo on the NTP is updated. This check is 467 // notification, so that the logo on the NTP is updated. This check is
416 // outside the reading of the web resource data, because the absence of 468 // outside the reading of the web resource data, because the absence of
417 // dates counts as a triggering change if there were dates before. 469 // dates counts as a triggering change if there were dates before.
470 // Also reset the promo closed preference, to signal a new promo.
418 if (!(old_promo_start == promo_start) || 471 if (!(old_promo_start == promo_start) ||
419 !(old_promo_end == promo_end)) { 472 !(old_promo_end == promo_end)) {
420 prefs_->SetReal(prefs::kNTPPromoStart, promo_start); 473 prefs_->SetReal(prefs::kNTPPromoStart, promo_start);
421 prefs_->SetReal(prefs::kNTPPromoEnd, promo_end); 474 prefs_->SetReal(prefs::kNTPPromoEnd, promo_end);
475 prefs_->SetBoolean(prefs::kNTPPromoClosed, false);
422 ScheduleNotification(promo_start, promo_end); 476 ScheduleNotification(promo_start, promo_end);
423 } 477 }
424 } 478 }
425 479
426 void WebResourceService::UnpackLogoSignal(const DictionaryValue& parsed_json) { 480 void WebResourceService::UnpackLogoSignal(const DictionaryValue& parsed_json) {
427 DictionaryValue* topic_dict; 481 DictionaryValue* topic_dict;
428 ListValue* answer_list; 482 ListValue* answer_list;
429 double old_logo_start = 0; 483 double old_logo_start = 0;
430 double old_logo_end = 0; 484 double old_logo_end = 0;
431 double logo_start = 0; 485 double logo_start = 0;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 } 545 }
492 546
493 namespace WebResourceServiceUtil { 547 namespace WebResourceServiceUtil {
494 548
495 bool CanShowPromo(Profile* profile) { 549 bool CanShowPromo(Profile* profile) {
496 bool promo_closed = false; 550 bool promo_closed = false;
497 PrefService* prefs = profile->GetPrefs(); 551 PrefService* prefs = profile->GetPrefs();
498 if (prefs->HasPrefPath(prefs::kNTPPromoClosed)) 552 if (prefs->HasPrefPath(prefs::kNTPPromoClosed))
499 promo_closed = prefs->GetBoolean(prefs::kNTPPromoClosed); 553 promo_closed = prefs->GetBoolean(prefs::kNTPPromoClosed);
500 554
501 bool has_extensions = false; 555 // Only show if not synced.
502 ExtensionService* extensions_service = profile->GetExtensionService(); 556 bool is_synced =
503 if (extensions_service) { 557 (profile->HasProfileSyncService() &&
504 const ExtensionList* extensions = extensions_service->extensions(); 558 sync_ui_util::GetStatus(
505 for (ExtensionList::const_iterator iter = extensions->begin(); 559 profile->GetProfileSyncService()) == sync_ui_util::SYNCED);
506 iter != extensions->end(); 560
507 ++iter) { 561 const std::string channel = platform_util::GetVersionStringModifier();
508 if ((*iter)->location() == Extension::INTERNAL) { 562 bool is_promo_build = false;
509 has_extensions = true; 563 if (prefs->HasPrefPath(prefs::kNTPPromoBuild)) {
510 break; 564 int builds_allowed = prefs->GetInteger(prefs::kNTPPromoBuild);
511 } 565 if (channel == "dev") {
566 is_promo_build = (DEV_BUILD & builds_allowed) != 0;
567 } else if (channel == "beta") {
568 is_promo_build = (BETA_BUILD & builds_allowed) != 0;
569 } else if (channel == "stable") {
570 is_promo_build = (STABLE_BUILD & builds_allowed) != 0;
571 } else {
572 is_promo_build = true;
512 } 573 }
513 } 574 }
514 575
515 // Note that HasProfileSyncService() will be false for ChromeOS, so 576 return !promo_closed && !is_synced && is_promo_build;
516 // promo_options will only be true if the user has an extension installed.
517 // See http://crosbug/10209
518 bool promo_options =
519 (profile->HasProfileSyncService() &&
520 sync_ui_util::GetStatus(
521 profile->GetProfileSyncService()) == sync_ui_util::SYNCED) ||
522 has_extensions;
523
524 return !promo_closed &&
525 promo_options &&
526 g_browser_process->GetApplicationLocale() == "en-US";
527 } 577 }
528 578
529 } // namespace WebResourceService 579 } // namespace WebResourceService
530 580
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698