diff options
author | dbeam@chromium.org <dbeam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-17 06:15:04 +0000 |
---|---|---|
committer | dbeam@chromium.org <dbeam@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-17 06:15:04 +0000 |
commit | 728171342522b70993ac59a956a678d375d73fda (patch) | |
tree | eee15bf88a9e802e2269161fe929a97c994b4cc9 | |
parent | 8d944b369dc0979cc9926cdda7673682bf8e5bef (diff) | |
download | chromium_src-728171342522b70993ac59a956a678d375d73fda.zip chromium_src-728171342522b70993ac59a956a678d375d73fda.tar.gz chromium_src-728171342522b70993ac59a956a678d375d73fda.tar.bz2 |
Sign In Promo: Roll out the new sign in promo gradually using a server check
R=achuith@chromium.org,mirandac@chromium.org
BUG=94242
TEST=SyncPromoTest.*
Review URL: http://codereview.chromium.org/7983046
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@105771 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r-- | chrome/browser/resources/ntp4/new_tab.js | 25 | ||||
-rw-r--r-- | chrome/browser/ui/webui/ntp/ntp_resource_cache.cc | 7 | ||||
-rw-r--r-- | chrome/browser/ui/webui/sync_promo_ui.cc | 5 | ||||
-rw-r--r-- | chrome/browser/web_resource/promo_resource_service.cc | 97 | ||||
-rw-r--r-- | chrome/browser/web_resource/promo_resource_service.h | 21 | ||||
-rw-r--r-- | chrome/browser/web_resource/promo_resource_service_unittest.cc | 195 | ||||
-rw-r--r-- | chrome/common/pref_names.cc | 7 | ||||
-rw-r--r-- | chrome/common/pref_names.h | 2 |
8 files changed, 347 insertions, 12 deletions
diff --git a/chrome/browser/resources/ntp4/new_tab.js b/chrome/browser/resources/ntp4/new_tab.js index 477e91f5..d374a6d 100644 --- a/chrome/browser/resources/ntp4/new_tab.js +++ b/chrome/browser/resources/ntp4/new_tab.js @@ -235,13 +235,8 @@ cr.define('ntp4', function() { chrome.send('notificationPromoViewed'); } - chrome.send('initializeSyncLogin'); - sliderFrame.classList.add('showing-sync-promo'); - $('login-container').addEventListener('click', function() { - var rect = $('login-container').getBoundingClientRect(); - chrome.send('showSyncLoginUI', - [rect.left, rect.top, rect.width, rect.height]); - }); + if (templateData.showSyncPromo) + showSyncPromo(); } /** @@ -848,6 +843,21 @@ cr.define('ntp4', function() { $('recently-closed-menu-button').dataItems = dataItems; } + /** + * Visually shows the sync promo on the NTP. + */ + function showSyncPromo() { + var loginContainer = getRequiredElement('login-container'); + if (loginContainer.hidden) { + chrome.send('initializeSyncLogin'); + loginContainer.addEventListener('click', function() { + var rect = loginContainer.getBoundingClientRect(); + chrome.send('showSyncLoginUI', + [rect.left, rect.top, rect.width, rect.height]); + }); + } + } + function setMostVisitedPages(data, hasBlacklistedUrls) { mostVisitedPage.data = data; } @@ -960,6 +970,7 @@ cr.define('ntp4', function() { setRecentlyClosedTabs: setRecentlyClosedTabs, setStripeColor: setStripeColor, showNotification: showNotification, + showSyncPromo: showSyncPromo, themeChanged: themeChanged, updateLogin: updateLogin, updateOfflineEnabledApps: updateOfflineEnabledApps diff --git a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc index 076877b..9f3efdb 100644 --- a/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc +++ b/chrome/browser/ui/webui/ntp/ntp_resource_cache.cc @@ -10,8 +10,8 @@ #include "base/file_util.h" #include "base/memory/ref_counted_memory.h" #include "base/string16.h" -#include "base/stringprintf.h" #include "base/string_number_conversions.h" +#include "base/stringprintf.h" #include "base/time.h" #include "base/utf_string_conversions.h" #include "base/values.h" @@ -26,6 +26,7 @@ #include "chrome/browser/ui/webui/ntp/new_tab_page_handler.h" #include "chrome/browser/ui/webui/ntp/new_tab_ui.h" #include "chrome/browser/ui/webui/ntp/shown_sections_handler.h" +#include "chrome/browser/ui/webui/sync_promo_ui.h" #include "chrome/browser/ui/webui/sync_setup_handler.h" #include "chrome/browser/web_resource/promo_resource_service.h" #include "chrome/common/chrome_notification_types.h" @@ -421,6 +422,10 @@ void NTPResourceCache::CreateNewTabHTML() { UserMetrics::RecordAction(UserMetricsAction("NTPPromoShown")); } + // Tell the NTP whether or not it should show the sync promotion. + localized_strings.SetBoolean("showSyncPromo", + SyncPromoUI::ShouldShowSyncPromo(profile_)); + // Enable or disable bookmark features based on an about flag. localized_strings.SetString("bookmark_features", NewTabUI::NTP4BookmarkFeaturesEnabled() ? "true" : "false"); diff --git a/chrome/browser/ui/webui/sync_promo_ui.cc b/chrome/browser/ui/webui/sync_promo_ui.cc index 58ee4cb..b2a0734 100644 --- a/chrome/browser/ui/webui/sync_promo_ui.cc +++ b/chrome/browser/ui/webui/sync_promo_ui.cc @@ -15,6 +15,7 @@ #include "chrome/browser/ui/webui/options/core_options_handler.h" #include "chrome/browser/ui/webui/sync_promo_handler.h" #include "chrome/browser/ui/webui/theme_source.h" +#include "chrome/browser/web_resource/promo_resource_service.h" #include "chrome/common/chrome_switches.h" #include "chrome/common/pref_names.h" #include "chrome/common/url_constants.h" @@ -90,7 +91,9 @@ bool SyncPromoUI::ShouldShowSyncPromo(Profile* profile) { if (!service || service->HasSyncSetupCompleted()) return false; - return true; + // If we're not excluded from showing sync, let's check to see if the remote + // data from the promo server says we should show a promo now. + return PromoResourceService::CanShowSyncPromo(profile); } // static diff --git a/chrome/browser/web_resource/promo_resource_service.cc b/chrome/browser/web_resource/promo_resource_service.cc index 14c1a30..7c9ff0d 100644 --- a/chrome/browser/web_resource/promo_resource_service.cc +++ b/chrome/browser/web_resource/promo_resource_service.cc @@ -5,6 +5,7 @@ #include "chrome/browser/web_resource/promo_resource_service.h" #include "base/command_line.h" +#include "base/rand_util.h" #include "base/string_number_conversions.h" #include "base/threading/thread_restrictions.h" #include "base/time.h" @@ -36,6 +37,10 @@ static const int kTestCacheUpdateDelay = 3 * 60 * 1000; // to versions with different types of promos). static const int kPromoServiceVersion = 2; +// The number of groups sync promo users will be divided into (which gives us a +// 1/N granularity when targeting more groups). +static const int kSyncPromoNumberOfGroups = 100; + // Properties used by the server. static const char kAnswerIdProperty[] = "answer_id"; static const char kWebStoreHeaderProperty[] = "question"; @@ -79,6 +84,12 @@ void PromoResourceService::RegisterUserPrefs(PrefService* prefs) { prefs->RegisterDoublePref(prefs::kNTPCustomLogoEnd, 0, PrefService::UNSYNCABLE_PREF); + prefs->RegisterIntegerPref(prefs::kNTPSyncPromoGroup, + 0, + PrefService::UNSYNCABLE_PREF); + prefs->RegisterIntegerPref(prefs::kNTPSyncPromoGroupMax, + 0, + PrefService::UNSYNCABLE_PREF); NotificationPromo::RegisterUserPrefs(prefs); } @@ -92,8 +103,11 @@ chrome::VersionInfo::Channel PromoResourceService::GetChannel() { // static bool PromoResourceService::IsBuildTargeted(chrome::VersionInfo::Channel channel, int builds_allowed) { - if (builds_allowed == NO_BUILD) + if (builds_allowed == NO_BUILD || + builds_allowed < 0 || + builds_allowed > ALL_BUILDS) { return false; + } switch (channel) { case chrome::VersionInfo::CHANNEL_CANARY: return (CANARY_BUILD & builds_allowed) != 0; @@ -140,6 +154,7 @@ void PromoResourceService::Unpack(const DictionaryValue& parsed_json) { UnpackLogoSignal(parsed_json); UnpackNotificationSignal(parsed_json); UnpackWebStoreSignal(parsed_json); + UnpackSyncPromoSignal(parsed_json); } void PromoResourceService::OnNewNotification(double start, double end) { @@ -359,3 +374,83 @@ void PromoResourceService::UnpackLogoSignal( NotificationService::NoDetails()); } } + +void PromoResourceService::UnpackSyncPromoSignal( + const DictionaryValue& parsed_json) { +#if defined(OS_CHROMEOS) + // Don't bother with this signal on ChromeOS. Users are already synced. + return; +#endif + + DictionaryValue* topic_dict; + if (!parsed_json.GetDictionary("topic", &topic_dict)) + return; + + ListValue* answer_list; + if (!topic_dict->GetList("answers", &answer_list)) + return; + + std::string question; + for (ListValue::const_iterator answer_iter = answer_list->begin(); + answer_iter != answer_list->end(); ++answer_iter) { + if (!(*answer_iter)->IsType(Value::TYPE_DICTIONARY)) + continue; + DictionaryValue* a_dic = static_cast<DictionaryValue*>(*answer_iter); + std::string name; + if (a_dic->GetString("name", &name) && name == "sync_promo") { + a_dic->GetString("question", &question); + break; + } + } + + int new_build; + int new_group_max; + size_t build_index = question.find(":"); + if (std::string::npos == build_index || + !base::StringToInt(question.substr(0, build_index), &new_build) || + !IsBuildTargeted(new_build) || + !base::StringToInt(question.substr(build_index + 1), &new_group_max)) { + // If anything about the response was invalid or this build is no longer + // targeted and there are existing prefs, clear them and notify. + if (prefs_->HasPrefPath(prefs::kNTPSyncPromoGroup) || + prefs_->HasPrefPath(prefs::kNTPSyncPromoGroupMax)) { + // Make sure we clear first, as the following notification may possibly + // depend on calling CanShowSyncPromo synchronously. + prefs_->ClearPref(prefs::kNTPSyncPromoGroup); + prefs_->ClearPref(prefs::kNTPSyncPromoGroupMax); + // Notify the NTP resource cache if the promo has been disabled. + NotificationService::current()->Notify( + chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED, + Source<WebResourceService>(this), + NotificationService::NoDetails()); + } + return; + } + + // TODO(dbeam): Add automagic hour group bumper to parsing? + + // If we successfully parsed a response and it differs from our user prefs, + // set pref for next time to compare. + if (new_group_max != prefs_->GetInteger(prefs::kNTPSyncPromoGroupMax)) + prefs_->SetInteger(prefs::kNTPSyncPromoGroupMax, new_group_max); +} + +// static +bool PromoResourceService::CanShowSyncPromo(Profile* profile) { + DCHECK(profile); + PrefService* prefs = profile->GetPrefs(); + + if (!prefs->HasPrefPath(prefs::kNTPSyncPromoGroupMax)) + return false; + + // If there's a max group set and the user hasn't been bucketed yet, do it. + if (!prefs->HasPrefPath(prefs::kNTPSyncPromoGroup)) { + prefs->SetInteger(prefs::kNTPSyncPromoGroup, + base::RandInt(1, kSyncPromoNumberOfGroups)); + } + + // A response is not kept if the build wasn't targeted, so the only thing + // required to check is the group this client has been tagged in. + return prefs->GetInteger(prefs::kNTPSyncPromoGroupMax) >= + prefs->GetInteger(prefs::kNTPSyncPromoGroup); +} diff --git a/chrome/browser/web_resource/promo_resource_service.h b/chrome/browser/web_resource/promo_resource_service.h index 1077cbf..fd97425 100644 --- a/chrome/browser/web_resource/promo_resource_service.h +++ b/chrome/browser/web_resource/promo_resource_service.h @@ -44,6 +44,9 @@ class PromoResourceService // Checks for conditions to show promo: start/end times, channel, etc. static bool CanShowNotificationPromo(Profile* profile); + // Checks if this user is in a group for sync promo roll-out. + static bool CanShowSyncPromo(Profile* profile); + static void RegisterPrefs(PrefService* local_state); static void RegisterUserPrefs(PrefService* prefs); @@ -57,6 +60,7 @@ class PromoResourceService static const char* kDefaultPromoResourceServer; private: + friend class SyncPromoTest; FRIEND_TEST_ALL_PREFIXES(PromoResourceServiceTest, IsBuildTargetedTest); FRIEND_TEST_ALL_PREFIXES(PromoResourceServiceTest, UnpackLogoSignal); FRIEND_TEST_ALL_PREFIXES(PromoResourceServiceTest, UnpackWebStoreSignal); @@ -205,6 +209,23 @@ class PromoResourceService // answer_id: the promo's id void UnpackWebStoreSignal(const base::DictionaryValue& parsed_json); + // Unpack the sync promo. Expects JSON delivery in the following format: + // { + // "topic": { + // "answers": [ + // ... + // { + // "answer_id": "XXXXXXX", + // "name": "sync_promo", + // "question": "1:5" + // } + // ] + // } + // } + // + // The question is in the form of "<build>:<group_max>". + void UnpackSyncPromoSignal(const base::DictionaryValue& parsed_json); + // NotificationPromo::Delegate override. virtual void OnNewNotification(double start, double end) OVERRIDE; diff --git a/chrome/browser/web_resource/promo_resource_service_unittest.cc b/chrome/browser/web_resource/promo_resource_service_unittest.cc index 6b6a8ed..b4a2501 100644 --- a/chrome/browser/web_resource/promo_resource_service_unittest.cc +++ b/chrome/browser/web_resource/promo_resource_service_unittest.cc @@ -3,6 +3,7 @@ // found in the LICENSE file. #include "base/json/json_reader.h" +#include "base/string_number_conversions.h" #include "base/time.h" #include "base/utf_string_conversions.h" #include "base/values.h" @@ -12,10 +13,12 @@ #include "chrome/browser/prefs/pref_service.h" #include "chrome/browser/web_resource/notification_promo.h" #include "chrome/browser/web_resource/promo_resource_service.h" +#include "chrome/common/chrome_notification_types.h" #include "chrome/common/pref_names.h" #include "chrome/test/base/testing_browser_process.h" #include "chrome/test/base/testing_pref_service.h" #include "chrome/test/base/testing_profile.h" +#include "content/common/notification_registrar.h" #include "content/test/test_url_fetcher_factory.h" #include "testing/gtest/include/gtest/gtest.h" @@ -33,6 +36,75 @@ class PromoResourceServiceTest : public testing::Test { MessageLoop loop_; }; +class SyncPromoTest : public PromoResourceServiceTest, + public NotificationObserver { + public: + SyncPromoTest() : PromoResourceServiceTest(), notifications_allowed_(false) { + web_resource_service_->set_channel(chrome::VersionInfo::CHANNEL_DEV); + registrar_.Add(this, + chrome::NOTIFICATION_PROMO_RESOURCE_STATE_CHANGED, + NotificationService::AllSources()); + } + + virtual void Observe(int type, + const NotificationSource& source, + const NotificationDetails& details) { + // If we get any unexpected notifications we should fail. + EXPECT_TRUE(notifications_allowed_); + } + + void allow_notifications(bool allowed) { notifications_allowed_ = allowed; } + + protected: + void ClearSyncPromoPrefs() { + PrefService* prefs = profile_.GetPrefs(); + prefs->ClearPref(prefs::kNTPSyncPromoGroup); + prefs->ClearPref(prefs::kNTPSyncPromoGroupMax); + ASSERT_FALSE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroup)); + ASSERT_FALSE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroupMax)); + } + + void InvalidTestCase(const std::string& question) { + PrefService* prefs = profile_.GetPrefs(); + ASSERT_TRUE(prefs != NULL); + prefs->SetInteger(prefs::kNTPSyncPromoGroup, 50); + prefs->SetInteger(prefs::kNTPSyncPromoGroupMax, 75); + UnpackSyncPromo(question); + EXPECT_FALSE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroup)); + EXPECT_FALSE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroupMax)); + } + + void SetupSyncPromoCase(int build, int max_group) { + std::string question = base::IntToString(build) + ":" + + base::IntToString(max_group); + UnpackSyncPromo(question); + } + + void UnpackSyncPromo(const std::string& question) { + std::string json_header = + "{ " + " \"topic\": {" + " \"answers\": [" + " {" + " \"name\": \"sync_promo\"," + " \"question\": \""; + + std::string json_footer = "\"" + " }" + " ]" + " }" + "}"; + + scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>( + base::JSONReader::Read(json_header + question + json_footer, false))); + web_resource_service_->UnpackSyncPromoSignal(*(test_json.get())); + } + + private: + bool notifications_allowed_; + NotificationRegistrar registrar_; +}; + // Verifies that custom dates read from a web resource server are written to // the preferences file. TEST_F(PromoResourceServiceTest, UnpackLogoSignal) { @@ -51,8 +123,8 @@ TEST_F(PromoResourceServiceTest, UnpackLogoSignal) { " ]" " }" "}"; - scoped_ptr<DictionaryValue> test_json(static_cast<DictionaryValue*>( - base::JSONReader::Read(json, false))); + scoped_ptr<DictionaryValue> test_json( + static_cast<DictionaryValue*>(base::JSONReader::Read(json, false))); // Check that prefs are set correctly. web_resource_service_->UnpackLogoSignal(*(test_json.get())); @@ -669,6 +741,121 @@ TEST_F(PromoResourceServiceTest, UnpackWebStoreSignalHttpLogo) { EXPECT_EQ(GURL(""), AppsPromo::GetSourcePromoLogoURL()); } +// Don't run sync promo unpacking tests on ChromeOS as on that plaform +// PromoResourceService::UnpackSyncPromoSignal() basically just no-ops. +#if !defined(OS_CHROMEOS) +TEST_F(SyncPromoTest, UnpackSyncPromoSignal) { + PrefService* prefs = profile_.GetPrefs(); + ASSERT_TRUE(prefs != NULL); + + // It's OK if we get notifications now, so just allow all. + allow_notifications(true); + + // Test on by default (currently should be false). + EXPECT_FALSE(PromoResourceService::CanShowSyncPromo(&profile_)); + EXPECT_FALSE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroup)); + EXPECT_FALSE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroupMax)); + + // Non-targeted build. + ClearSyncPromoPrefs(); + SetupSyncPromoCase(2, 50); + EXPECT_FALSE(PromoResourceService::CanShowSyncPromo(&profile_)); + EXPECT_FALSE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroup)); + EXPECT_FALSE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroupMax)); + + // Targeted build, doesn't create bucket and doesn't show promo because + // groupMax < group. + ClearSyncPromoPrefs(); + SetupSyncPromoCase(1, 0); + EXPECT_FALSE(PromoResourceService::CanShowSyncPromo(&profile_)); + EXPECT_EQ(prefs->GetInteger(prefs::kNTPSyncPromoGroupMax), 0); + EXPECT_FALSE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroup)); + + // Targeted build, max_group = 50, ensure group pref created and within the + // group bounds. + ClearSyncPromoPrefs(); + SetupSyncPromoCase(1, 50); + PromoResourceService::CanShowSyncPromo(&profile_); + EXPECT_EQ(prefs->GetInteger(prefs::kNTPSyncPromoGroupMax), 50); + EXPECT_TRUE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroup)); + EXPECT_GT(prefs->GetInteger(prefs::kNTPSyncPromoGroup), 0); + EXPECT_LE(prefs->GetInteger(prefs::kNTPSyncPromoGroup), 100); + + // Set user group = 50, now shows promo. + prefs->SetInteger(prefs::kNTPSyncPromoGroup, 50); + EXPECT_TRUE(PromoResourceService::CanShowSyncPromo(&profile_)); + EXPECT_EQ(prefs->GetInteger(prefs::kNTPSyncPromoGroup), 50); + EXPECT_EQ(prefs->GetInteger(prefs::kNTPSyncPromoGroupMax), 50); + + // Bump user group, ensure that we should not show promo. + prefs->SetInteger(prefs::kNTPSyncPromoGroup, 51); + EXPECT_FALSE(PromoResourceService::CanShowSyncPromo(&profile_)); + EXPECT_EQ(prefs->GetInteger(prefs::kNTPSyncPromoGroup), 51); + EXPECT_EQ(prefs->GetInteger(prefs::kNTPSyncPromoGroupMax), 50); + + // If the max group gets bumped to the user's group (or above), it should + // show. + prefs->SetInteger(prefs::kNTPSyncPromoGroupMax, 51); + EXPECT_TRUE(PromoResourceService::CanShowSyncPromo(&profile_)); + EXPECT_EQ(prefs->GetInteger(prefs::kNTPSyncPromoGroup), 51); + EXPECT_EQ(prefs->GetInteger(prefs::kNTPSyncPromoGroupMax), 51); + + // Reduce max group. + prefs->SetInteger(prefs::kNTPSyncPromoGroupMax, 49); + EXPECT_FALSE(PromoResourceService::CanShowSyncPromo(&profile_)); + EXPECT_EQ(prefs->GetInteger(prefs::kNTPSyncPromoGroup), 51); + EXPECT_EQ(prefs->GetInteger(prefs::kNTPSyncPromoGroupMax), 49); + + // Ignore non-targeted builds. + prefs->SetInteger(prefs::kNTPSyncPromoGroup, 50); + prefs->SetInteger(prefs::kNTPSyncPromoGroupMax, 75); + EXPECT_TRUE(PromoResourceService::CanShowSyncPromo(&profile_)); + SetupSyncPromoCase(2, 25); + // Make sure the prefs are deleted. + EXPECT_FALSE(PromoResourceService::CanShowSyncPromo(&profile_)); + EXPECT_FALSE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroup)); + EXPECT_FALSE(prefs->HasPrefPath(prefs::kNTPSyncPromoGroupMax)); +} + +// Throw random stuff at UnpackSyncPromoSignal and make sure no segfaults or +// other issues and that the prefs were cleared. +TEST_F(SyncPromoTest, UnpackSyncPromoSignalInvalid) { + // We're not testing these here, so ignore them. + allow_notifications(true); + + // Empty. + InvalidTestCase(""); + + // Negative numbers. + InvalidTestCase("-5:-6"); + + // An extra field. + InvalidTestCase("1:0:1"); + + // A ton of separators. + InvalidTestCase("::::::"); + + // Really big numbers. + InvalidTestCase("68719476737:68719476737"); + + // UTF-8 chars. + InvalidTestCase("だからって馬鹿に:してるの?怒る友人"); +} + +TEST_F(SyncPromoTest, UnpackSyncPromoSignalNotify) { + // Ensure no notifications are sent. + ClearSyncPromoPrefs(); + allow_notifications(false); + SetupSyncPromoCase(2, 50); + SetupSyncPromoCase(1, 0); + SetupSyncPromoCase(1, 100); + + // Expect a notification to be called when the promo is disabled. + allow_notifications(true); + SetupSyncPromoCase(2, 0); +} +#endif // !defined(OS_CHROMEOS) + TEST_F(PromoResourceServiceTest, IsBuildTargetedTest) { // canary const chrome::VersionInfo::Channel canary = @@ -710,4 +897,8 @@ TEST_F(PromoResourceServiceTest, IsBuildTargetedTest) { EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 8)); EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, 11)); EXPECT_TRUE(PromoResourceService::IsBuildTargeted(stable, 12)); + + // invalid + EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, -1)); + EXPECT_FALSE(PromoResourceService::IsBuildTargeted(stable, INT_MAX)); } diff --git a/chrome/common/pref_names.cc b/chrome/common/pref_names.cc index 0176499..c5efb78 100644 --- a/chrome/common/pref_names.cc +++ b/chrome/common/pref_names.cc @@ -1300,6 +1300,13 @@ const char kNTPPromoLine[] = "ntp.promo_line"; const char kNTPPromoStart[] = "ntp.promo_start"; const char kNTPPromoEnd[] = "ntp.promo_end"; +// A randomly generated group created to control the number of users we show the +// sync promo to on the NTP. +const char kNTPSyncPromoGroup[] = "ntp.sync_promo.group"; + +// The maximum allowable group that can be shown the sync promotion on the NTP. +const char kNTPSyncPromoGroupMax[] = "ntp.sync_promo.group_max"; + // Boolean indicating whether the web store is active for the current locale. const char kNTPWebStoreEnabled[] = "ntp.webstore_enabled"; diff --git a/chrome/common/pref_names.h b/chrome/common/pref_names.h index 676a37a..f5e7c50 100644 --- a/chrome/common/pref_names.h +++ b/chrome/common/pref_names.h @@ -464,6 +464,8 @@ extern const char kNTPPromoGroupMax[]; extern const char kNTPPromoViews[]; extern const char kNTPPromoViewsMax[]; extern const char kNTPPromoBuild[]; +extern const char kNTPSyncPromoGroup[]; +extern const char kNTPSyncPromoGroupMax[]; extern const char kNTPWebStoreEnabled[]; extern const char kNTPWebStorePromoLastId[]; extern const char kNTPWebStorePromoId[]; |