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

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 149 matching lines...) Expand 10 before | Expand all | Expand 10 after
196 const std::string& json_data_; 214 const std::string& json_data_;
197 215
198 // True if we got a response from the utility process and have cleaned up 216 // True if we got a response from the utility process and have cleaned up
199 // already. 217 // already.
200 bool got_response_; 218 bool got_response_;
201 }; 219 };
202 220
203 // Server for dynamically loaded NTP HTML elements. TODO(mirandac): append 221 // Server for dynamically loaded NTP HTML elements. TODO(mirandac): append
204 // locale for future usage, when we're serving localizable strings. 222 // locale for future usage, when we're serving localizable strings.
205 const char* WebResourceService::kDefaultWebResourceServer = 223 const char* WebResourceService::kDefaultWebResourceServer =
206 "https://www.google.com/support/chrome/bin/topic/30248/inproduct"; 224 // "https://www.google.com/support/chrome/bin/topic/30248/inproduct";
225 "http://www.corp.google.com/~mirandac/testprefs.json";
207 226
208 WebResourceService::WebResourceService(Profile* profile) 227 WebResourceService::WebResourceService(Profile* profile)
209 : prefs_(profile->GetPrefs()), 228 : prefs_(profile->GetPrefs()),
210 profile_(profile), 229 profile_(profile),
211 ALLOW_THIS_IN_INITIALIZER_LIST(service_factory_(this)), 230 ALLOW_THIS_IN_INITIALIZER_LIST(service_factory_(this)),
212 in_fetch_(false), 231 in_fetch_(false),
213 web_resource_update_scheduled_(false) { 232 web_resource_update_scheduled_(false) {
214 Init(); 233 Init();
215 } 234 }
216 235
217 WebResourceService::~WebResourceService() { } 236 WebResourceService::~WebResourceService() { }
218 237
219 void WebResourceService::Init() { 238 void WebResourceService::Init() {
220 cache_update_delay_ = kCacheUpdateDelay; 239 cache_update_delay_ = kCacheUpdateDelay;
221 resource_dispatcher_host_ = g_browser_process->resource_dispatcher_host(); 240 resource_dispatcher_host_ = g_browser_process->resource_dispatcher_host();
222 web_resource_fetcher_.reset(new WebResourceFetcher(this)); 241 web_resource_fetcher_.reset(new WebResourceFetcher(this));
223 prefs_->RegisterStringPref(prefs::kNTPWebResourceCacheUpdate, "0"); 242 prefs_->RegisterStringPref(prefs::kNTPWebResourceCacheUpdate, "0");
224 prefs_->RegisterRealPref(prefs::kNTPCustomLogoStart, 0); 243 prefs_->RegisterRealPref(prefs::kNTPCustomLogoStart, 0);
225 prefs_->RegisterRealPref(prefs::kNTPCustomLogoEnd, 0); 244 prefs_->RegisterRealPref(prefs::kNTPCustomLogoEnd, 0);
226 prefs_->RegisterRealPref(prefs::kNTPPromoStart, 0); 245 prefs_->RegisterRealPref(prefs::kNTPPromoStart, 0);
227 prefs_->RegisterRealPref(prefs::kNTPPromoEnd, 0); 246 prefs_->RegisterRealPref(prefs::kNTPPromoEnd, 0);
228 prefs_->RegisterStringPref(prefs::kNTPPromoLine, std::string()); 247 prefs_->RegisterStringPref(prefs::kNTPPromoLine, std::string());
229 prefs_->RegisterBooleanPref(prefs::kNTPPromoClosed, false); 248 prefs_->RegisterBooleanPref(prefs::kNTPPromoClosed, false);
249 prefs_->RegisterIntegerPref(prefs::kNTPPromoGroup, -1);
250 prefs_->RegisterIntegerPref(prefs::kNTPPromoBuild,
251 DEV_BUILD | BETA_BUILD | STABLE_BUILD);
252 prefs_->RegisterIntegerPref(prefs::kNTPPromoGroupTimeSlice, 0);
230 253
231 // If the promo start is in the future, set a notification task to invalidate 254 // 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. 255 // the NTP cache at the time of the promo start.
233 double promo_start = prefs_->GetReal(prefs::kNTPPromoStart); 256 double promo_start = prefs_->GetReal(prefs::kNTPPromoStart);
234 double promo_end = prefs_->GetReal(prefs::kNTPPromoEnd); 257 double promo_end = prefs_->GetReal(prefs::kNTPPromoEnd);
235 ScheduleNotification(promo_start, promo_end); 258 ScheduleNotification(promo_start, promo_end);
236 } 259 }
237 260
238 void WebResourceService::EndFetch() { 261 void WebResourceService::EndFetch() {
239 in_fetch_ = false; 262 in_fetch_ = false;
240 } 263 }
241 264
242 void WebResourceService::OnWebResourceUnpacked( 265 void WebResourceService::OnWebResourceUnpacked(
243 const DictionaryValue& parsed_json) { 266 const DictionaryValue& parsed_json) {
244 UnpackLogoSignal(parsed_json); 267 UnpackLogoSignal(parsed_json);
245 if (WebResourceServiceUtil::CanShowPromo(profile_)) 268 UnpackPromoSignal(parsed_json);
246 UnpackPromoSignal(parsed_json);
247 EndFetch(); 269 EndFetch();
248 } 270 }
249 271
250 void WebResourceService::WebResourceStateChange() { 272 void WebResourceService::WebResourceStateChange() {
251 web_resource_update_scheduled_ = false; 273 web_resource_update_scheduled_ = false;
252 NotificationService* service = NotificationService::current(); 274 NotificationService* service = NotificationService::current();
253 service->Notify(NotificationType::WEB_RESOURCE_STATE_CHANGED, 275 service->Notify(NotificationType::WEB_RESOURCE_STATE_CHANGED,
254 Source<WebResourceService>(this), 276 Source<WebResourceService>(this),
255 NotificationService::NoDetails()); 277 NotificationService::NoDetails());
256 } 278 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
370 old_promo_start = prefs_->GetReal(prefs::kNTPPromoStart); 392 old_promo_start = prefs_->GetReal(prefs::kNTPPromoStart);
371 old_promo_end = prefs_->GetReal(prefs::kNTPPromoEnd); 393 old_promo_end = prefs_->GetReal(prefs::kNTPPromoEnd);
372 } 394 }
373 395
374 // Check for newly received start and end values. 396 // Check for newly received start and end values.
375 if (parsed_json.GetDictionary("topic", &topic_dict)) { 397 if (parsed_json.GetDictionary("topic", &topic_dict)) {
376 if (topic_dict->GetList("answers", &answer_list)) { 398 if (topic_dict->GetList("answers", &answer_list)) {
377 std::string promo_start_string = ""; 399 std::string promo_start_string = "";
378 std::string promo_end_string = ""; 400 std::string promo_end_string = "";
379 std::string promo_string = ""; 401 std::string promo_string = "";
402 std::string promo_build = "";
403 int promo_build_type;
404 int time_slice_hrs;
380 for (ListValue::const_iterator tip_iter = answer_list->begin(); 405 for (ListValue::const_iterator tip_iter = answer_list->begin();
381 tip_iter != answer_list->end(); ++tip_iter) { 406 tip_iter != answer_list->end(); ++tip_iter) {
382 if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY)) 407 if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY))
383 continue; 408 continue;
384 DictionaryValue* a_dic = 409 DictionaryValue* a_dic =
385 static_cast<DictionaryValue*>(*tip_iter); 410 static_cast<DictionaryValue*>(*tip_iter);
386 std::string promo_signal; 411 std::string promo_signal;
387 if (a_dic->GetString("name", &promo_signal)) { 412 if (a_dic->GetString("name", &promo_signal)) {
388 if (promo_signal == "promo_start") { 413 if (promo_signal == "promo_start") {
414 a_dic->GetString("question", &promo_build);
415 size_t split = promo_build.find(":");
416 if (split != std::string::npos &&
417 base::StringToInt(promo_build.substr(0, split),
418 &promo_build_type) &&
419 base::StringToInt(promo_build.substr(split+1),
420 &time_slice_hrs) &&
421 promo_build_type >= 0 &&
422 promo_build_type <= (DEV_BUILD | BETA_BUILD | STABLE_BUILD) &&
423 time_slice_hrs >= 0 &&
424 time_slice_hrs <= kMaxTimeSliceHours) {
425 prefs_->SetInteger(prefs::kNTPPromoBuild, promo_build_type);
426 prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice,
427 time_slice_hrs);
428 } else {
429 // If no time data or bad time data are set, show promo on all
430 // builds with no time slicing.
431 prefs_->SetInteger(prefs::kNTPPromoBuild,
432 DEV_BUILD | BETA_BUILD | STABLE_BUILD);
433 prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice, 0);
434 }
389 a_dic->GetString("inproduct", &promo_start_string); 435 a_dic->GetString("inproduct", &promo_start_string);
390 a_dic->GetString("tooltip", &promo_string); 436 a_dic->GetString("tooltip", &promo_string);
391 prefs_->SetString(prefs::kNTPPromoLine, promo_string); 437 prefs_->SetString(prefs::kNTPPromoLine, promo_string);
438 srand(static_cast<uint32>(time(NULL)));
439 prefs_->SetInteger(prefs::kNTPPromoGroup,
440 rand() % kNTPPromoGroupSize);
392 } else if (promo_signal == "promo_end") { 441 } else if (promo_signal == "promo_end") {
393 a_dic->GetString("inproduct", &promo_end_string); 442 a_dic->GetString("inproduct", &promo_end_string);
394 } 443 }
395 } 444 }
396 } 445 }
397 if (!promo_start_string.empty() && 446 if (!promo_start_string.empty() &&
398 promo_start_string.length() > 0 && 447 promo_start_string.length() > 0 &&
399 !promo_end_string.empty() && 448 !promo_end_string.empty() &&
400 promo_end_string.length() > 0) { 449 promo_end_string.length() > 0) {
401 base::Time start_time; 450 base::Time start_time;
402 base::Time end_time; 451 base::Time end_time;
403 if (base::Time::FromString( 452 if (base::Time::FromString(
404 ASCIIToWide(promo_start_string).c_str(), &start_time) && 453 ASCIIToWide(promo_start_string).c_str(), &start_time) &&
405 base::Time::FromString( 454 base::Time::FromString(
406 ASCIIToWide(promo_end_string).c_str(), &end_time)) { 455 ASCIIToWide(promo_end_string).c_str(), &end_time)) {
407 promo_start = start_time.ToDoubleT(); 456 // Add group time slice, adjusted from hours to seconds.
457 promo_start = start_time.ToDoubleT() +
458 (prefs_->FindPreference(prefs::kNTPPromoGroup) ?
459 prefs_->GetInteger(prefs::kNTPPromoGroup) *
460 time_slice_hrs * 60 * 60 : 0);
408 promo_end = end_time.ToDoubleT(); 461 promo_end = end_time.ToDoubleT();
409 } 462 }
410 } 463 }
411 } 464 }
412 } 465 }
413 466
414 // If start or end times have changed, trigger a new web resource 467 // 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 468 // 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 469 // outside the reading of the web resource data, because the absence of
417 // dates counts as a triggering change if there were dates before. 470 // dates counts as a triggering change if there were dates before.
471 // Also reset the promo closed preference, to signal a new promo.
418 if (!(old_promo_start == promo_start) || 472 if (!(old_promo_start == promo_start) ||
419 !(old_promo_end == promo_end)) { 473 !(old_promo_end == promo_end)) {
420 prefs_->SetReal(prefs::kNTPPromoStart, promo_start); 474 prefs_->SetReal(prefs::kNTPPromoStart, promo_start);
421 prefs_->SetReal(prefs::kNTPPromoEnd, promo_end); 475 prefs_->SetReal(prefs::kNTPPromoEnd, promo_end);
476 prefs_->SetBoolean(prefs::kNTPPromoClosed, false);
422 ScheduleNotification(promo_start, promo_end); 477 ScheduleNotification(promo_start, promo_end);
423 } 478 }
424 } 479 }
425 480
426 void WebResourceService::UnpackLogoSignal(const DictionaryValue& parsed_json) { 481 void WebResourceService::UnpackLogoSignal(const DictionaryValue& parsed_json) {
427 DictionaryValue* topic_dict; 482 DictionaryValue* topic_dict;
428 ListValue* answer_list; 483 ListValue* answer_list;
429 double old_logo_start = 0; 484 double old_logo_start = 0;
430 double old_logo_end = 0; 485 double old_logo_end = 0;
431 double logo_start = 0; 486 double logo_start = 0;
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
491 } 546 }
492 547
493 namespace WebResourceServiceUtil { 548 namespace WebResourceServiceUtil {
494 549
495 bool CanShowPromo(Profile* profile) { 550 bool CanShowPromo(Profile* profile) {
496 bool promo_closed = false; 551 bool promo_closed = false;
497 PrefService* prefs = profile->GetPrefs(); 552 PrefService* prefs = profile->GetPrefs();
498 if (prefs->HasPrefPath(prefs::kNTPPromoClosed)) 553 if (prefs->HasPrefPath(prefs::kNTPPromoClosed))
499 promo_closed = prefs->GetBoolean(prefs::kNTPPromoClosed); 554 promo_closed = prefs->GetBoolean(prefs::kNTPPromoClosed);
500 555
501 bool has_extensions = false; 556 // Only show if not synced.
502 ExtensionService* extensions_service = profile->GetExtensionService(); 557 bool is_synced =
503 if (extensions_service) { 558 (profile->HasProfileSyncService() &&
504 const ExtensionList* extensions = extensions_service->extensions(); 559 sync_ui_util::GetStatus(
505 for (ExtensionList::const_iterator iter = extensions->begin(); 560 profile->GetProfileSyncService()) == sync_ui_util::SYNCED);
506 iter != extensions->end(); 561
507 ++iter) { 562 const std::string channel = platform_util::GetVersionStringModifier();
508 if ((*iter)->location() == Extension::INTERNAL) { 563 bool is_promo_build = false;
509 has_extensions = true; 564 if (prefs->HasPrefPath(prefs::kNTPPromoBuild)) {
510 break; 565 int builds_allowed = prefs->GetInteger(prefs::kNTPPromoBuild);
511 } 566 if (channel == "dev") {
567 is_promo_build = (DEV_BUILD & builds_allowed) != 0;
568 } else if (channel == "beta") {
569 is_promo_build = (BETA_BUILD & builds_allowed) != 0;
570 } else if (channel == "stable") {
571 is_promo_build = (STABLE_BUILD & builds_allowed) != 0;
572 } else {
573 is_promo_build = true;
512 } 574 }
513 } 575 }
514 576
515 // Note that HasProfileSyncService() will be false for ChromeOS, so 577 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 } 578 }
528 579
529 } // namespace WebResourceService 580 } // namespace WebResourceService
530 581
OLDNEW
« no previous file with comments | « chrome/browser/web_resource/web_resource_service.h ('k') | chrome/browser/web_resource/web_resource_service_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698