diff options
author | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-24 20:10:13 +0000 |
---|---|---|
committer | mirandac@chromium.org <mirandac@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-01-24 20:10:13 +0000 |
commit | 47db9a95e12b8ab2ed14f33bcca1f8f2a40ea6d4 (patch) | |
tree | 8f4bc0ade113dbde98cf44caa0f7d7a9d147ffca /chrome/browser/web_resource | |
parent | 1503de36be46c5d273254bc7023b440f291e4be1 (diff) | |
download | chromium_src-47db9a95e12b8ab2ed14f33bcca1f8f2a40ea6d4.zip chromium_src-47db9a95e12b8ab2ed14f33bcca1f8f2a40ea6d4.tar.gz chromium_src-47db9a95e12b8ab2ed14f33bcca1f8f2a40ea6d4.tar.bz2 |
Add possibility to divide chrome users into groups of equal size, and change promo code to reflect sync promo.
BUG=68671, 68672
TEST=none
Review URL: http://codereview.chromium.org/6313009
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@72374 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/web_resource')
3 files changed, 151 insertions, 44 deletions
diff --git a/chrome/browser/web_resource/web_resource_service.cc b/chrome/browser/web_resource/web_resource_service.cc index 35f4aea..f7984a7 100644 --- a/chrome/browser/web_resource/web_resource_service.cc +++ b/chrome/browser/web_resource/web_resource_service.cc @@ -4,6 +4,8 @@ #include "chrome/browser/web_resource/web_resource_service.h" +#include <string> + #include "base/command_line.h" #include "base/file_path.h" #include "base/string_util.h" @@ -14,6 +16,7 @@ #include "chrome/browser/browser_process.h" #include "chrome/browser/browser_thread.h" #include "chrome/browser/extensions/extension_service.h" +#include "chrome/browser/platform_util.h" #include "chrome/browser/profiles/profile.h" #include "chrome/browser/sync/sync_ui_util.h" #include "chrome/common/chrome_switches.h" @@ -34,6 +37,21 @@ static const int kStartResourceFetchDelay = 5000; // Delay between calls to update the cache (48 hours). static const int kCacheUpdateDelay = 48 * 60 * 60 * 1000; +// Users are randomly assigned to one of kNTPPromoGroupSize buckets, in order +// to be able to roll out promos slowly, or display different promos to +// different groups. +static const int kNTPPromoGroupSize = 16; + +// Maximum number of hours for each time slice (4 weeks). +static const int kMaxTimeSliceHours = 24 * 7 * 4; + +// Used to determine which build type should be shown a given promo. +enum BuildType { + DEV_BUILD = 1, + BETA_BUILD = 1 << 1, + STABLE_BUILD = 1 << 2, +}; + } // namespace const char* WebResourceService::kCurrentTipPrefName = "current_tip"; @@ -203,7 +221,8 @@ class WebResourceService::UnpackerClient // Server for dynamically loaded NTP HTML elements. TODO(mirandac): append // locale for future usage, when we're serving localizable strings. const char* WebResourceService::kDefaultWebResourceServer = - "https://www.google.com/support/chrome/bin/topic/30248/inproduct"; +// "https://www.google.com/support/chrome/bin/topic/30248/inproduct"; + "http://www.corp.google.com/~mirandac/testprefs.json"; WebResourceService::WebResourceService(Profile* profile) : prefs_(profile->GetPrefs()), @@ -227,6 +246,10 @@ void WebResourceService::Init() { prefs_->RegisterRealPref(prefs::kNTPPromoEnd, 0); prefs_->RegisterStringPref(prefs::kNTPPromoLine, std::string()); prefs_->RegisterBooleanPref(prefs::kNTPPromoClosed, false); + prefs_->RegisterIntegerPref(prefs::kNTPPromoGroup, -1); + prefs_->RegisterIntegerPref(prefs::kNTPPromoBuild, + DEV_BUILD | BETA_BUILD | STABLE_BUILD); + prefs_->RegisterIntegerPref(prefs::kNTPPromoGroupTimeSlice, 0); // If the promo start is in the future, set a notification task to invalidate // the NTP cache at the time of the promo start. @@ -242,8 +265,7 @@ void WebResourceService::EndFetch() { void WebResourceService::OnWebResourceUnpacked( const DictionaryValue& parsed_json) { UnpackLogoSignal(parsed_json); - if (WebResourceServiceUtil::CanShowPromo(profile_)) - UnpackPromoSignal(parsed_json); + UnpackPromoSignal(parsed_json); EndFetch(); } @@ -377,6 +399,9 @@ void WebResourceService::UnpackPromoSignal(const DictionaryValue& parsed_json) { std::string promo_start_string = ""; std::string promo_end_string = ""; std::string promo_string = ""; + std::string promo_build = ""; + int promo_build_type; + int time_slice_hrs; for (ListValue::const_iterator tip_iter = answer_list->begin(); tip_iter != answer_list->end(); ++tip_iter) { if (!(*tip_iter)->IsType(Value::TYPE_DICTIONARY)) @@ -386,9 +411,33 @@ void WebResourceService::UnpackPromoSignal(const DictionaryValue& parsed_json) { std::string promo_signal; if (a_dic->GetString("name", &promo_signal)) { if (promo_signal == "promo_start") { + a_dic->GetString("question", &promo_build); + size_t split = promo_build.find(":"); + if (split != std::string::npos && + base::StringToInt(promo_build.substr(0, split), + &promo_build_type) && + base::StringToInt(promo_build.substr(split+1), + &time_slice_hrs) && + promo_build_type >= 0 && + promo_build_type <= (DEV_BUILD | BETA_BUILD | STABLE_BUILD) && + time_slice_hrs >= 0 && + time_slice_hrs <= kMaxTimeSliceHours) { + prefs_->SetInteger(prefs::kNTPPromoBuild, promo_build_type); + prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice, + time_slice_hrs); + } else { + // If no time data or bad time data are set, show promo on all + // builds with no time slicing. + prefs_->SetInteger(prefs::kNTPPromoBuild, + DEV_BUILD | BETA_BUILD | STABLE_BUILD); + prefs_->SetInteger(prefs::kNTPPromoGroupTimeSlice, 0); + } a_dic->GetString("inproduct", &promo_start_string); a_dic->GetString("tooltip", &promo_string); prefs_->SetString(prefs::kNTPPromoLine, promo_string); + srand(static_cast<uint32>(time(NULL))); + prefs_->SetInteger(prefs::kNTPPromoGroup, + rand() % kNTPPromoGroupSize); } else if (promo_signal == "promo_end") { a_dic->GetString("inproduct", &promo_end_string); } @@ -404,7 +453,11 @@ void WebResourceService::UnpackPromoSignal(const DictionaryValue& parsed_json) { ASCIIToWide(promo_start_string).c_str(), &start_time) && base::Time::FromString( ASCIIToWide(promo_end_string).c_str(), &end_time)) { - promo_start = start_time.ToDoubleT(); + // Add group time slice, adjusted from hours to seconds. + promo_start = start_time.ToDoubleT() + + (prefs_->FindPreference(prefs::kNTPPromoGroup) ? + prefs_->GetInteger(prefs::kNTPPromoGroup) * + time_slice_hrs * 60 * 60 : 0); promo_end = end_time.ToDoubleT(); } } @@ -415,10 +468,12 @@ void WebResourceService::UnpackPromoSignal(const DictionaryValue& parsed_json) { // notification, so that the logo on the NTP is updated. This check is // outside the reading of the web resource data, because the absence of // dates counts as a triggering change if there were dates before. + // Also reset the promo closed preference, to signal a new promo. if (!(old_promo_start == promo_start) || !(old_promo_end == promo_end)) { prefs_->SetReal(prefs::kNTPPromoStart, promo_start); prefs_->SetReal(prefs::kNTPPromoEnd, promo_end); + prefs_->SetBoolean(prefs::kNTPPromoClosed, false); ScheduleNotification(promo_start, promo_end); } } @@ -498,32 +553,28 @@ bool CanShowPromo(Profile* profile) { if (prefs->HasPrefPath(prefs::kNTPPromoClosed)) promo_closed = prefs->GetBoolean(prefs::kNTPPromoClosed); - bool has_extensions = false; - ExtensionService* extensions_service = profile->GetExtensionService(); - if (extensions_service) { - const ExtensionList* extensions = extensions_service->extensions(); - for (ExtensionList::const_iterator iter = extensions->begin(); - iter != extensions->end(); - ++iter) { - if ((*iter)->location() == Extension::INTERNAL) { - has_extensions = true; - break; - } - } - } - - // Note that HasProfileSyncService() will be false for ChromeOS, so - // promo_options will only be true if the user has an extension installed. - // See http://crosbug/10209 - bool promo_options = + // Only show if not synced. + bool is_synced = (profile->HasProfileSyncService() && sync_ui_util::GetStatus( - profile->GetProfileSyncService()) == sync_ui_util::SYNCED) || - has_extensions; + profile->GetProfileSyncService()) == sync_ui_util::SYNCED); + + const std::string channel = platform_util::GetVersionStringModifier(); + bool is_promo_build = false; + if (prefs->HasPrefPath(prefs::kNTPPromoBuild)) { + int builds_allowed = prefs->GetInteger(prefs::kNTPPromoBuild); + if (channel == "dev") { + is_promo_build = (DEV_BUILD & builds_allowed) != 0; + } else if (channel == "beta") { + is_promo_build = (BETA_BUILD & builds_allowed) != 0; + } else if (channel == "stable") { + is_promo_build = (STABLE_BUILD & builds_allowed) != 0; + } else { + is_promo_build = true; + } + } - return !promo_closed && - promo_options && - g_browser_process->GetApplicationLocale() == "en-US"; + return !promo_closed && !is_synced && is_promo_build; } } // namespace WebResourceService diff --git a/chrome/browser/web_resource/web_resource_service.h b/chrome/browser/web_resource/web_resource_service.h index 70c8000..2373757 100644 --- a/chrome/browser/web_resource/web_resource_service.h +++ b/chrome/browser/web_resource/web_resource_service.h @@ -23,6 +23,14 @@ bool CanShowPromo(Profile* profile); } // namespace WebResourceService +// A WebResourceService fetches data from a web resource server to be used to +// dynamically change the appearance of the New Tab Page. For example, it has +// been used to fetch "tips" to be displayed on the NTP, or to display +// promotional messages to certain groups of Chrome users. +// +// TODO(mirandac): Arrange for a server to be set up specifically for promo +// messages, which have until now been piggybacked onto the old tips server +// structure. (see http://crbug.com/70634 for details.) class WebResourceService : public UtilityProcessHost::Client { public: @@ -65,7 +73,7 @@ class WebResourceService // { // "answer_id": "1067976", // "name": "promo_start", - // "question": "", + // "question": "1:24", // "tooltip": // "Click \u003ca href=http://www.google.com\u003ehere\u003c/a\u003e!", // "inproduct": "10/8/09 12:00", @@ -84,6 +92,18 @@ class WebResourceService // } // } // + // Because the promo signal data is piggybacked onto the tip server, the + // values don't exactly correspond with the field names: + // + // For "promo_start" or "promo_end", the date to start or stop showing the + // promotional line is given by the "inproduct" line. + // For "promo_start", the promotional line itself is given in the "tooltip" + // field. The "question" field gives the type of builds that should be shown + // this promo (see the BuildType enum in web_resource_service.cc) and the + // number of hours that each promo group should see it, separated by ":". + // For example, "7:24" would indicate that all builds should see the promo, + // and each group should see it for 24 hours. + // // Public for unit testing. void UnpackPromoSignal(const DictionaryValue& parsed_json); diff --git a/chrome/browser/web_resource/web_resource_service_unittest.cc b/chrome/browser/web_resource/web_resource_service_unittest.cc index 2211bb4..4127a6e 100644 --- a/chrome/browser/web_resource/web_resource_service_unittest.cc +++ b/chrome/browser/web_resource/web_resource_service_unittest.cc @@ -14,6 +14,17 @@ typedef testing::Test WebResourceServiceTest; +namespace { + +// From web_resource_service.cc +enum BuildType { + DEV_BUILD = 1, + BETA_BUILD = 1 << 1, + STABLE_BUILD = 1 << 2, +}; + +} // namespace + // Verifies that custom dates read from a web resource server are written to // the preferences file. TEST_F(WebResourceServiceTest, UnpackLogoSignal) { @@ -42,12 +53,15 @@ TEST_F(WebResourceServiceTest, UnpackLogoSignal) { // Check that prefs are set correctly. web_resource_service->UnpackLogoSignal(*(test_json.get())); + PrefService* prefs = profile.GetPrefs(); + ASSERT_TRUE(prefs != NULL); + double logo_start = - profile.GetPrefs()->GetReal(prefs::kNTPCustomLogoStart); - ASSERT_EQ(logo_start, 1264899600); // unix epoch for Jan 31 2010 0100 GMT. + prefs->GetReal(prefs::kNTPCustomLogoStart); + EXPECT_EQ(logo_start, 1264899600); // unix epoch for Jan 31 2010 0100 GMT. double logo_end = - profile.GetPrefs()->GetReal(prefs::kNTPCustomLogoEnd); - ASSERT_EQ(logo_end, 1327971600); // unix epoch for Jan 31 2012 0100 GMT. + prefs->GetReal(prefs::kNTPCustomLogoEnd); + EXPECT_EQ(logo_end, 1327971600); // unix epoch for Jan 31 2012 0100 GMT. // Change the start only and recheck. json = "{ " @@ -70,8 +84,9 @@ TEST_F(WebResourceServiceTest, UnpackLogoSignal) { // Check that prefs are set correctly. web_resource_service->UnpackLogoSignal(*(test_json.get())); - logo_start = profile.GetPrefs()->GetReal(prefs::kNTPCustomLogoStart); - ASSERT_EQ(logo_start, 1267365600); // date changes to Feb 28 2010 1400 GMT. + + logo_start = prefs->GetReal(prefs::kNTPCustomLogoStart); + EXPECT_EQ(logo_start, 1267365600); // date changes to Feb 28 2010 1400 GMT. // If no date is included in the prefs, reset custom logo dates to 0. json = "{ " @@ -88,10 +103,10 @@ TEST_F(WebResourceServiceTest, UnpackLogoSignal) { // Check that prefs are set correctly. web_resource_service->UnpackLogoSignal(*(test_json.get())); - logo_start = profile.GetPrefs()->GetReal(prefs::kNTPCustomLogoStart); - ASSERT_EQ(logo_start, 0); // date value reset to 0; - logo_end = profile.GetPrefs()->GetReal(prefs::kNTPCustomLogoEnd); - ASSERT_EQ(logo_end, 0); // date value reset to 0; + logo_start = prefs->GetReal(prefs::kNTPCustomLogoStart); + EXPECT_EQ(logo_start, 0); // date value reset to 0; + logo_end = prefs->GetReal(prefs::kNTPCustomLogoEnd); + EXPECT_EQ(logo_end, 0); // date value reset to 0; } TEST_F(WebResourceServiceTest, UnpackPromoSignal) { @@ -107,6 +122,7 @@ TEST_F(WebResourceServiceTest, UnpackPromoSignal) { " \"answers\": [" " {" " \"name\": \"promo_start\"," + " \"question\": \"3:2\"," " \"tooltip\": \"Eat more pie!\"," " \"inproduct\": \"31/01/10 01:00 GMT\"" " }," @@ -125,13 +141,33 @@ TEST_F(WebResourceServiceTest, UnpackPromoSignal) { // Check that prefs are set correctly. web_resource_service->UnpackPromoSignal(*(test_json.get())); + PrefService* prefs = profile.GetPrefs(); + ASSERT_TRUE(prefs != NULL); + + std::string promo_line = prefs->GetString(prefs::kNTPPromoLine); + EXPECT_EQ(promo_line, "Eat more pie!"); + + int promo_group = prefs->GetInteger(prefs::kNTPPromoGroup); + EXPECT_GE(promo_group, 0); + EXPECT_LT(promo_group, 16); + + int promo_build_type = prefs->GetInteger(prefs::kNTPPromoBuild); + EXPECT_EQ(promo_build_type & DEV_BUILD, DEV_BUILD); + EXPECT_EQ(promo_build_type & BETA_BUILD, BETA_BUILD); + EXPECT_EQ(promo_build_type & STABLE_BUILD, 0); + + int promo_time_slice = prefs->GetInteger(prefs::kNTPPromoGroupTimeSlice); + EXPECT_EQ(promo_time_slice, 2); + double promo_start = - profile.GetPrefs()->GetReal(prefs::kNTPPromoStart); - ASSERT_EQ(promo_start, 1264899600); // unix epoch for Jan 31 2010 0100 GMT. + prefs->GetReal(prefs::kNTPPromoStart); + int64 actual_start = 1264899600 + // unix epoch for Jan 31 2010 0100 GMT. + promo_group * 2 * 60 * 60; + EXPECT_EQ(promo_start, actual_start); + double promo_end = - profile.GetPrefs()->GetReal(prefs::kNTPPromoEnd); - ASSERT_EQ(promo_end, 1327971600); // unix epoch for Jan 31 2012 0100 GMT. - std::string promo_line = profile.GetPrefs()->GetString(prefs::kNTPPromoLine); - ASSERT_EQ(promo_line, "Eat more pie!"); + prefs->GetReal(prefs::kNTPPromoEnd); + EXPECT_EQ(promo_end, 1327971600); // unix epoch for Jan 31 2012 0100 GMT. } + |