Merge Chromium + Blink git repositories
[chromium-blink-merge.git] / chrome / browser / signin / cross_device_promo_unittest.cc
blob636cd7853de1b48b3a765ff63b31275d3e1ed8c6
1 // Copyright 2015 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/signin/cross_device_promo.h"
7 #include "base/metrics/field_trial.h"
8 #include "base/run_loop.h"
9 #include "base/test/histogram_tester.h"
10 #include "chrome/browser/prefs/browser_prefs.h"
11 #include "chrome/browser/signin/chrome_signin_client_factory.h"
12 #include "chrome/browser/signin/cross_device_promo_factory.h"
13 #include "chrome/browser/signin/fake_gaia_cookie_manager_service.h"
14 #include "chrome/browser/signin/fake_signin_manager_builder.h"
15 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
16 #include "chrome/browser/signin/signin_manager_factory.h"
17 #include "chrome/browser/signin/test_signin_client_builder.h"
18 #include "chrome/common/pref_names.h"
19 #include "chrome/test/base/testing_browser_process.h"
20 #include "chrome/test/base/testing_profile.h"
21 #include "chrome/test/base/testing_profile_manager.h"
22 #include "components/signin/core/browser/signin_manager.h"
23 #include "components/signin/core/browser/signin_metrics.h"
24 #include "components/signin/core/browser/test_signin_client.h"
25 #include "components/syncable_prefs/pref_service_syncable.h"
26 #include "components/syncable_prefs/testing_pref_service_syncable.h"
27 #include "components/variations/entropy_provider.h"
28 #include "components/variations/variations_associated_data.h"
29 #include "content/public/test/test_browser_thread_bundle.h"
30 #include "google_apis/gaia/gaia_urls.h"
31 #include "net/url_request/test_url_fetcher_factory.h"
32 #include "testing/gtest/include/gtest/gtest.h"
34 namespace {
36 typedef std::map<std::string, std::string> VariationsMap;
38 int64 InTwoHours() {
39 return (base::Time::Now() + base::TimeDelta::FromHours(2)).ToInternalValue();
42 } // namespace
44 class CrossDevicePromoObserver : public CrossDevicePromo::Observer {
45 public:
46 explicit CrossDevicePromoObserver(CrossDevicePromo* promo)
47 : eligible_(false),
48 times_set_eligible_(0),
49 times_set_ineligible_(0),
50 promo_(promo) {
51 promo->AddObserver(this);
54 ~CrossDevicePromoObserver() { promo_->RemoveObserver(this); }
56 void OnPromoEligibilityChanged(bool eligible) override {
57 eligible_ = eligible;
58 if (eligible)
59 ++times_set_eligible_;
60 else
61 ++times_set_ineligible_;
64 bool is_eligible() const { return eligible_; }
65 int times_set_eligible() const { return times_set_eligible_; }
66 int times_set_inactive() const { return times_set_ineligible_; }
68 private:
69 bool eligible_;
70 int times_set_eligible_;
71 int times_set_ineligible_;
72 CrossDevicePromo* promo_;
74 DISALLOW_COPY_AND_ASSIGN(CrossDevicePromoObserver);
77 class CrossDevicePromoTest : public ::testing::Test {
78 public:
79 CrossDevicePromoTest();
81 void SetUp() override;
83 // Destroys any variations which might be defined, and starts fresh.
84 void ResetFieldTrialList();
86 // Defines a default set of variation parameters for promo initialization.
87 void InitPromoVariation();
89 CrossDevicePromo* promo() { return cross_device_promo_; }
90 TestingProfile* profile() { return profile_; }
91 FakeSigninManagerForTesting* signin_manager() { return signin_manager_; }
92 base::HistogramTester* histogram_tester() { return &histogram_tester_; }
93 syncable_prefs::TestingPrefServiceSyncable* prefs() { return pref_service_; }
94 FakeGaiaCookieManagerService* cookie_manager_service() {
95 return cookie_manager_service_;
97 net::FakeURLFetcherFactory* fetcher_factory() {
98 return &fake_url_fetcher_factory_;
101 private:
102 content::TestBrowserThreadBundle bundle_;
103 CrossDevicePromo* cross_device_promo_;
104 TestingProfile* profile_;
105 FakeSigninManagerForTesting* signin_manager_;
106 FakeGaiaCookieManagerService* cookie_manager_service_;
107 syncable_prefs::TestingPrefServiceSyncable* pref_service_;
108 scoped_ptr<TestingProfileManager> testing_profile_manager_;
109 base::HistogramTester histogram_tester_;
110 scoped_ptr<base::FieldTrialList> field_trial_list_;
111 net::FakeURLFetcherFactory fake_url_fetcher_factory_;
113 DISALLOW_COPY_AND_ASSIGN(CrossDevicePromoTest);
116 CrossDevicePromoTest::CrossDevicePromoTest() : fake_url_fetcher_factory_(NULL) {
117 ResetFieldTrialList();
120 void CrossDevicePromoTest::SetUp() {
121 testing_profile_manager_.reset(
122 new TestingProfileManager(TestingBrowserProcess::GetGlobal()));
123 ASSERT_TRUE(testing_profile_manager_.get()->SetUp());
125 TestingProfile::TestingFactories factories;
126 factories.push_back(std::make_pair(ChromeSigninClientFactory::GetInstance(),
127 signin::BuildTestSigninClient));
128 factories.push_back(
129 std::make_pair(GaiaCookieManagerServiceFactory::GetInstance(),
130 FakeGaiaCookieManagerService::Build));
131 factories.push_back(std::make_pair(SigninManagerFactory::GetInstance(),
132 BuildFakeSigninManagerBase));
134 pref_service_ = new syncable_prefs::TestingPrefServiceSyncable();
135 chrome::RegisterUserProfilePrefs(pref_service_->registry());
137 profile_ = testing_profile_manager_.get()->CreateTestingProfile(
138 "name",
139 make_scoped_ptr<syncable_prefs::PrefServiceSyncable>(pref_service_),
140 base::UTF8ToUTF16("name"), 0, std::string(), factories);
142 cookie_manager_service_ = static_cast<FakeGaiaCookieManagerService*>(
143 GaiaCookieManagerServiceFactory::GetForProfile(profile()));
144 cookie_manager_service_->Init(&fake_url_fetcher_factory_);
146 signin_manager_ = static_cast<FakeSigninManagerForTesting*>(
147 SigninManagerFactory::GetForProfile(profile()));
149 cross_device_promo_ = CrossDevicePromoFactory::GetForProfile(profile());
152 void CrossDevicePromoTest::ResetFieldTrialList() {
153 // Destroy the existing FieldTrialList before creating a new one to avoid
154 // a DCHECK.
155 field_trial_list_.reset();
156 field_trial_list_.reset(
157 new base::FieldTrialList(new metrics::SHA1EntropyProvider("foo")));
158 variations::testing::ClearAllVariationParams();
161 void CrossDevicePromoTest::InitPromoVariation() {
162 VariationsMap variations_params;
163 variations_params[
164 CrossDevicePromo::kParamHoursBetweenDeviceActivityChecks] = "2";
165 variations_params[
166 CrossDevicePromo::kParamDaysToVerifySingleUserProfile] = "0";
167 variations_params[
168 CrossDevicePromo::kParamMinutesBetweenBrowsingSessions] = "0";
169 variations_params[
170 CrossDevicePromo::kParamMinutesMaxContextSwitchDuration] = "10";
171 variations_params[
172 CrossDevicePromo::kParamRPCThrottle] = "0";
173 EXPECT_TRUE(variations::AssociateVariationParams(
174 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A", variations_params));
175 base::FieldTrialList::CreateFieldTrial(
176 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A");
179 // Tests for incrementally large portions flow that determines if the promo
180 // should be shown.
182 TEST_F(CrossDevicePromoTest, Uninitialized) {
183 ASSERT_TRUE(promo());
184 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
185 signin_metrics::NO_VARIATIONS_CONFIG,
188 promo()->CheckPromoEligibilityForTesting();
189 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
190 signin_metrics::NO_VARIATIONS_CONFIG,
192 histogram_tester()->ExpectTotalCount("Signin.XDevicePromo.Eligibility", 0);
193 EXPECT_FALSE(prefs()->GetBoolean(prefs::kCrossDevicePromoOptedOut));
196 TEST_F(CrossDevicePromoTest, UnitializedOptedOut) {
197 CrossDevicePromoObserver observer(promo());
199 promo()->OptOut();
200 // Opting out doesn't de-activate a never-active promo.
201 EXPECT_EQ(0, observer.times_set_inactive());
202 EXPECT_TRUE(prefs()->GetBoolean(prefs::kCrossDevicePromoOptedOut));
204 // An opted-out promo will never be initialized.
205 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
206 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
207 signin_metrics::NO_VARIATIONS_CONFIG,
209 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
210 signin_metrics::UNINITIALIZED_OPTED_OUT,
212 histogram_tester()->ExpectTotalCount("Signin.XDevicePromo.Eligibility", 0);
215 TEST_F(CrossDevicePromoTest, PartiallyInitialized) {
216 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
217 signin_metrics::NO_VARIATIONS_CONFIG,
220 VariationsMap variations_params;
221 variations_params[
222 CrossDevicePromo::kParamHoursBetweenDeviceActivityChecks] = "1";
223 variations_params[
224 CrossDevicePromo::kParamDaysToVerifySingleUserProfile] = "1";
225 EXPECT_TRUE(variations::AssociateVariationParams(
226 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A", variations_params));
227 base::FieldTrialList::CreateFieldTrial(
228 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A");
230 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
231 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
232 signin_metrics::NO_VARIATIONS_CONFIG,
234 histogram_tester()->ExpectTotalCount("Signin.XDevicePromo.Eligibility", 0);
237 TEST_F(CrossDevicePromoTest, FullyInitialized) {
238 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
239 signin_metrics::NO_VARIATIONS_CONFIG,
242 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
243 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
244 signin_metrics::NO_VARIATIONS_CONFIG,
247 InitPromoVariation();
248 signin_manager()->SignIn("12345", "foo@bar.com", "password");
249 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
250 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
251 signin_metrics::INITIALIZED, 1);
252 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
253 signin_metrics::NO_VARIATIONS_CONFIG,
256 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
257 signin_metrics::SIGNED_IN, 1);
260 TEST_F(CrossDevicePromoTest, InitializedOptOut) {
261 // In a normal browser, the variations get set before the CrossDevicePromo is
262 // created. Here, we need to force another Init() by calling
263 // CheckPromoEligibilityForTesting().
264 InitPromoVariation();
265 signin_manager()->SignIn("12345", "foo@bar.com", "password");
266 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
268 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
269 signin_metrics::INITIALIZED, 1);
270 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
271 signin_metrics::SIGNED_IN, 1);
273 // After opting out the initialized state remains; eligibility changes.
274 promo()->OptOut();
275 promo()->CheckPromoEligibilityForTesting();
276 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
277 signin_metrics::INITIALIZED, 1);
278 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Eligibility",
279 signin_metrics::OPTED_OUT, 1);
282 TEST_F(CrossDevicePromoTest, SignedInAndOut) {
283 InitPromoVariation();
286 base::HistogramTester test_signed_in;
287 signin_manager()->SignIn("12345", "foo@bar.com", "password");
288 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
289 test_signed_in.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
290 signin_metrics::SIGNED_IN, 1);
294 base::HistogramTester test_signed_out;
295 signin_manager()->SignOut(signin_metrics::SIGNOUT_TEST);
296 promo()->CheckPromoEligibilityForTesting();
297 test_signed_out.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
298 signin_metrics::NOT_SINGLE_GAIA_ACCOUNT,
303 TEST_F(CrossDevicePromoTest, TrackAccountsInCookie) {
304 InitPromoVariation();
305 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
307 ASSERT_FALSE(prefs()->HasPrefPath(
308 prefs::kCrossDevicePromoObservedSingleAccountCookie));
309 std::vector<gaia::ListedAccount> accounts;
311 // Setting a single cookie sets the time.
312 base::Time before_setting_cookies = base::Time::Now();
313 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
314 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
315 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
316 base::RunLoop().RunUntilIdle();
318 base::Time after_setting_cookies = base::Time::Now();
319 EXPECT_TRUE(prefs()->HasPrefPath(
320 prefs::kCrossDevicePromoObservedSingleAccountCookie));
321 EXPECT_LE(
322 before_setting_cookies.ToInternalValue(),
323 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie));
324 EXPECT_GE(
325 after_setting_cookies.ToInternalValue(),
326 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie));
328 // A single cookie a second time doesn't change the time.
329 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
330 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
331 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
332 base::RunLoop().RunUntilIdle();
334 EXPECT_TRUE(prefs()->HasPrefPath(
335 prefs::kCrossDevicePromoObservedSingleAccountCookie));
336 EXPECT_GE(
337 after_setting_cookies.ToInternalValue(),
338 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie));
340 // Setting accounts with an auth error doesn't change the time.
341 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
342 cookie_manager_service()->SetListAccountsResponseWebLoginRequired();
343 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
344 base::RunLoop().RunUntilIdle();
346 EXPECT_TRUE(prefs()->HasPrefPath(
347 prefs::kCrossDevicePromoObservedSingleAccountCookie));
348 EXPECT_LE(
349 before_setting_cookies.ToInternalValue(),
350 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie));
351 EXPECT_GE(
352 after_setting_cookies.ToInternalValue(),
353 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie));
355 // Seeing zero accounts clears the pref.
356 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
357 cookie_manager_service()->SetListAccountsResponseNoAccounts();
358 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
359 base::RunLoop().RunUntilIdle();
361 EXPECT_FALSE(prefs()->HasPrefPath(
362 prefs::kCrossDevicePromoObservedSingleAccountCookie));
365 TEST_F(CrossDevicePromoTest, SingleAccountEligibility) {
366 InitPromoVariation();
369 base::HistogramTester test_single_account;
370 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
371 test_single_account.ExpectUniqueSample(
372 "Signin.XDevicePromo.Eligibility",
373 signin_metrics::NOT_SINGLE_GAIA_ACCOUNT, 1);
376 // Notice a single account.
378 base::HistogramTester test_single_account;
379 std::vector<gaia::ListedAccount> accounts;
380 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
381 cookie_manager_service()->SetListAccountsResponseOneAccount("a@b.com", "1");
382 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
383 base::RunLoop().RunUntilIdle();
385 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
386 test_single_account.ExpectUniqueSample(
387 "Signin.XDevicePromo.Eligibility",
388 signin_metrics::UNKNOWN_COUNT_DEVICES, 1);
391 // Set a single account that hasn't been around for "long enough".
393 base::HistogramTester test_single_account;
394 prefs()->SetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie,
395 InTwoHours());
396 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
397 test_single_account.ExpectBucketCount(
398 "Signin.XDevicePromo.Eligibility",
399 signin_metrics::NOT_SINGLE_GAIA_ACCOUNT, 1);
403 TEST_F(CrossDevicePromoTest, NumDevicesEligibility) {
404 // Start with a variation, signed in, and one account in the cookie jar.
405 InitPromoVariation();
406 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
407 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
408 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
409 std::vector<gaia::ListedAccount> accounts;
410 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
411 base::RunLoop().RunUntilIdle();
413 // Ensure we appropriate schedule a check for device activity.
415 base::HistogramTester test_missing_list_devices;
416 int64 earliest_time_to_check_list_devices =
417 base::Time::Now().ToInternalValue();
418 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
419 int64 latest_time_to_check_list_devices = InTwoHours();
420 test_missing_list_devices.ExpectUniqueSample(
421 "Signin.XDevicePromo.Eligibility",
422 signin_metrics::UNKNOWN_COUNT_DEVICES, 1);
423 EXPECT_TRUE(
424 prefs()->HasPrefPath(prefs::kCrossDevicePromoNextFetchListDevicesTime));
425 int64 when_to_check_list_devices =
426 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime);
427 EXPECT_LT(earliest_time_to_check_list_devices, when_to_check_list_devices);
428 EXPECT_GT(latest_time_to_check_list_devices, when_to_check_list_devices);
431 // Don't reschedule the device activity check if there's one pending.
433 base::HistogramTester test_unknown_devices;
434 int64 list_devices_time = InTwoHours();
435 prefs()->SetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime,
436 list_devices_time);
437 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
438 test_unknown_devices.ExpectUniqueSample(
439 "Signin.XDevicePromo.Eligibility",
440 signin_metrics::UNKNOWN_COUNT_DEVICES, 1);
441 // The scheduled time to fetch device activity should not have changed.
442 EXPECT_EQ(
443 list_devices_time,
444 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime));
447 // Execute the device activity fetch if it's time.
449 base::HistogramTester test_unknown_devices;
450 prefs()->SetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime,
451 base::Time::Now().ToInternalValue());
452 // The DeviceActivityFetcher will return an error to the promo service.
453 fetcher_factory()->SetFakeResponse(
454 GaiaUrls::GetInstance()->oauth2_iframe_url(), "not json", net::HTTP_OK,
455 net::URLRequestStatus::SUCCESS);
456 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
457 base::RunLoop().RunUntilIdle();
458 test_unknown_devices.ExpectUniqueSample(
459 "Signin.XDevicePromo.Eligibility",
460 signin_metrics::ERROR_FETCHING_DEVICE_ACTIVITY, 1);
464 TEST_F(CrossDevicePromoTest, ThrottleDeviceActivityCall) {
465 // Start with a variation (fully throttled), signed in, one account in cookie.
466 VariationsMap variations_params;
467 variations_params[
468 CrossDevicePromo::kParamHoursBetweenDeviceActivityChecks] = "1";
469 variations_params[
470 CrossDevicePromo::kParamDaysToVerifySingleUserProfile] = "0";
471 variations_params[
472 CrossDevicePromo::kParamMinutesBetweenBrowsingSessions] = "0";
473 variations_params[
474 CrossDevicePromo::kParamMinutesMaxContextSwitchDuration] = "10";
475 variations_params[
476 CrossDevicePromo::kParamRPCThrottle] = "100";
477 EXPECT_TRUE(variations::AssociateVariationParams(
478 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A", variations_params));
479 base::FieldTrialList::CreateFieldTrial(
480 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A");
482 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
483 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
484 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
485 std::vector<gaia::ListedAccount> accounts;
486 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
487 base::RunLoop().RunUntilIdle();
489 // Ensure device activity fetches get throttled.
491 base::HistogramTester test_throttle_rpc;
492 prefs()->SetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime,
493 base::Time::Now().ToInternalValue());
494 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
495 test_throttle_rpc.ExpectUniqueSample(
496 "Signin.XDevicePromo.Eligibility",
497 signin_metrics::THROTTLED_FETCHING_DEVICE_ACTIVITY, 1);
501 TEST_F(CrossDevicePromoTest, NumDevicesKnown) {
502 // Start with a variation, signed in, and one account, fetch device activity
503 // in two hours.
504 InitPromoVariation();
505 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
506 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
507 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
508 std::vector<gaia::ListedAccount> accounts;
509 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
510 base::RunLoop().RunUntilIdle();
511 prefs()->SetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime,
512 InTwoHours());
514 // Verify that knowing there are no devices for this account logs the
515 // appropriate metric for ineligibility.
517 base::HistogramTester test_no_devices;
518 prefs()->SetInteger(prefs::kCrossDevicePromoNumDevices, 0);
519 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
520 test_no_devices.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
521 signin_metrics::ZERO_DEVICES, 1);
524 // Verify that knowing there is another device for this account results in the
525 // promo being eligible to be shown.
527 prefs()->SetInteger(prefs::kCrossDevicePromoNumDevices, 1);
528 EXPECT_TRUE(promo()->CheckPromoEligibilityForTesting());
532 TEST_F(CrossDevicePromoTest, FetchDeviceResults) {
533 // Start with a variation, signed in, and one account, fetch device activity
534 // in 2 hours.
535 InitPromoVariation();
536 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
537 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
538 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
539 std::vector<gaia::ListedAccount> accounts;
540 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
541 base::RunLoop().RunUntilIdle();
542 prefs()->SetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime,
543 base::Time::Now().ToInternalValue());
544 prefs()->SetInteger(prefs::kCrossDevicePromoNumDevices, 1);
546 // Verify that if the device activity fetcher returns zero devices the
547 // eligibility metric will report a ZERO_DEVICES event, and will not report
548 // the promo as eligible to be shown.
550 base::HistogramTester test_no_devices;
551 std::vector<DeviceActivityFetcher::DeviceActivity> devices;
552 int64 in_two_hours = InTwoHours();
553 promo()->OnFetchDeviceActivitySuccess(devices);
554 EXPECT_LE(
555 in_two_hours,
556 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime));
557 EXPECT_EQ(0, prefs()->GetInteger(prefs::kCrossDevicePromoNumDevices));
558 test_no_devices.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
559 signin_metrics::ZERO_DEVICES, 1);
562 // Verify that if the device activity fetcher returns one device that was
563 // recently active, the promo is marked as eligible and the eligibility
564 // metric reports an ELIGIBLE event.
566 CrossDevicePromoObserver observer(promo());
567 EXPECT_FALSE(observer.is_eligible());
568 base::HistogramTester test_one_device;
569 std::vector<DeviceActivityFetcher::DeviceActivity> devices;
570 base::Time device_last_active =
571 base::Time::Now() - base::TimeDelta::FromMinutes(4);
572 DeviceActivityFetcher::DeviceActivity device;
573 device.last_active = device_last_active;
574 device.name = "Aslan";
575 devices.push_back(device);
577 int64 in_two_hours = InTwoHours();
578 promo()->OnFetchDeviceActivitySuccess(devices);
579 EXPECT_LE(
580 in_two_hours,
581 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime));
582 EXPECT_EQ(1, prefs()->GetInteger(prefs::kCrossDevicePromoNumDevices));
583 EXPECT_EQ(device_last_active.ToInternalValue(),
584 prefs()->GetInt64(prefs::kCrossDevicePromoLastDeviceActiveTime));
585 EXPECT_TRUE(prefs()->GetBoolean(prefs::kCrossDevicePromoShouldBeShown));
586 test_one_device.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
587 signin_metrics::ELIGIBLE, 1);
588 EXPECT_TRUE(observer.is_eligible());
589 EXPECT_EQ(1, observer.times_set_eligible());
592 // Verify that if the device activity fetcher returns one device that was not
593 // recently active then the eligibility metric will report a NO_ACTIVE_DEVICES
594 // event, and will not report the promo as eligible to be shown.
596 CrossDevicePromoObserver observer(promo());
597 EXPECT_FALSE(observer.is_eligible());
598 base::HistogramTester test_one_device;
599 std::vector<DeviceActivityFetcher::DeviceActivity> devices;
600 base::Time device_last_active =
601 base::Time::Now() - base::TimeDelta::FromMinutes(30);
602 DeviceActivityFetcher::DeviceActivity device;
603 device.last_active = device_last_active;
604 device.name = "Aslan";
605 devices.push_back(device);
607 int64 in_two_hours = InTwoHours();
608 promo()->OnFetchDeviceActivitySuccess(devices);
609 EXPECT_LE(
610 in_two_hours,
611 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime));
612 EXPECT_EQ(1, prefs()->GetInteger(prefs::kCrossDevicePromoNumDevices));
613 EXPECT_EQ(device_last_active.ToInternalValue(),
614 prefs()->GetInt64(prefs::kCrossDevicePromoLastDeviceActiveTime));
615 EXPECT_FALSE(prefs()->GetBoolean(prefs::kCrossDevicePromoShouldBeShown));
616 test_one_device.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
617 signin_metrics::NO_ACTIVE_DEVICES, 1);
618 EXPECT_FALSE(observer.is_eligible());
621 // Verify that if the device activity fetcher returns two devices and one was
622 // recently active, that the promo is eligible to be shown and the last active
623 // time is stored properly.
625 CrossDevicePromoObserver observer(promo());
626 EXPECT_FALSE(observer.is_eligible());
627 base::HistogramTester test_two_devices;
628 std::vector<DeviceActivityFetcher::DeviceActivity> devices;
629 base::Time device1_last_active =
630 base::Time::Now() - base::TimeDelta::FromMinutes(30);
631 base::Time device2_last_active =
632 base::Time::Now() - base::TimeDelta::FromMinutes(3);
633 DeviceActivityFetcher::DeviceActivity device1;
634 device1.last_active = device1_last_active;
635 device1.name = "Aslan";
636 devices.push_back(device1);
637 DeviceActivityFetcher::DeviceActivity device2;
638 device2.last_active = device2_last_active;
639 device2.name = "Balrog";
640 devices.push_back(device2);
642 int64 in_two_hours = InTwoHours();
643 promo()->OnFetchDeviceActivitySuccess(devices);
644 EXPECT_LE(
645 in_two_hours,
646 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime));
647 EXPECT_EQ(2, prefs()->GetInteger(prefs::kCrossDevicePromoNumDevices));
648 EXPECT_EQ(device2_last_active.ToInternalValue(),
649 prefs()->GetInt64(prefs::kCrossDevicePromoLastDeviceActiveTime));
650 EXPECT_TRUE(prefs()->GetBoolean(prefs::kCrossDevicePromoShouldBeShown));
651 test_two_devices.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
652 signin_metrics::ELIGIBLE, 1);
653 EXPECT_TRUE(observer.is_eligible());
654 EXPECT_EQ(1, observer.times_set_eligible());