MD Downloads: UI review feedback
[chromium-blink-merge.git] / chrome / browser / signin / cross_device_promo_unittest.cc
blobaa7b51b0ecb4d330e8579377dbe6d1623ab914ad
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 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 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 TestingPrefServiceSyncable();
135 chrome::RegisterUserProfilePrefs(pref_service_->registry());
137 profile_ = testing_profile_manager_.get()->CreateTestingProfile(
138 "name", make_scoped_ptr<PrefServiceSyncable>(pref_service_),
139 base::UTF8ToUTF16("name"), 0, std::string(), factories);
141 cookie_manager_service_ = static_cast<FakeGaiaCookieManagerService*>(
142 GaiaCookieManagerServiceFactory::GetForProfile(profile()));
143 cookie_manager_service_->Init(&fake_url_fetcher_factory_);
145 signin_manager_ = static_cast<FakeSigninManagerForTesting*>(
146 SigninManagerFactory::GetForProfile(profile()));
148 cross_device_promo_ = CrossDevicePromoFactory::GetForProfile(profile());
151 void CrossDevicePromoTest::ResetFieldTrialList() {
152 // Destroy the existing FieldTrialList before creating a new one to avoid
153 // a DCHECK.
154 field_trial_list_.reset();
155 field_trial_list_.reset(
156 new base::FieldTrialList(new metrics::SHA1EntropyProvider("foo")));
157 variations::testing::ClearAllVariationParams();
160 void CrossDevicePromoTest::InitPromoVariation() {
161 VariationsMap variations_params;
162 variations_params[
163 CrossDevicePromo::kParamHoursBetweenDeviceActivityChecks] = "2";
164 variations_params[
165 CrossDevicePromo::kParamDaysToVerifySingleUserProfile] = "0";
166 variations_params[
167 CrossDevicePromo::kParamMinutesBetweenBrowsingSessions] = "0";
168 variations_params[
169 CrossDevicePromo::kParamMinutesMaxContextSwitchDuration] = "10";
170 variations_params[
171 CrossDevicePromo::kParamRPCThrottle] = "0";
172 EXPECT_TRUE(variations::AssociateVariationParams(
173 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A", variations_params));
174 base::FieldTrialList::CreateFieldTrial(
175 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A");
178 // Tests for incrementally large portions flow that determines if the promo
179 // should be shown.
181 TEST_F(CrossDevicePromoTest, Uninitialized) {
182 ASSERT_TRUE(promo());
183 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
184 signin_metrics::NO_VARIATIONS_CONFIG,
187 promo()->CheckPromoEligibilityForTesting();
188 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
189 signin_metrics::NO_VARIATIONS_CONFIG,
191 histogram_tester()->ExpectTotalCount("Signin.XDevicePromo.Eligibility", 0);
192 EXPECT_FALSE(prefs()->GetBoolean(prefs::kCrossDevicePromoOptedOut));
195 TEST_F(CrossDevicePromoTest, UnitializedOptedOut) {
196 CrossDevicePromoObserver observer(promo());
198 promo()->OptOut();
199 // Opting out doesn't de-activate a never-active promo.
200 EXPECT_EQ(0, observer.times_set_inactive());
201 EXPECT_TRUE(prefs()->GetBoolean(prefs::kCrossDevicePromoOptedOut));
203 // An opted-out promo will never be initialized.
204 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
205 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
206 signin_metrics::NO_VARIATIONS_CONFIG,
208 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
209 signin_metrics::UNINITIALIZED_OPTED_OUT,
211 histogram_tester()->ExpectTotalCount("Signin.XDevicePromo.Eligibility", 0);
214 TEST_F(CrossDevicePromoTest, PartiallyInitialized) {
215 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
216 signin_metrics::NO_VARIATIONS_CONFIG,
219 VariationsMap variations_params;
220 variations_params[
221 CrossDevicePromo::kParamHoursBetweenDeviceActivityChecks] = "1";
222 variations_params[
223 CrossDevicePromo::kParamDaysToVerifySingleUserProfile] = "1";
224 EXPECT_TRUE(variations::AssociateVariationParams(
225 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A", variations_params));
226 base::FieldTrialList::CreateFieldTrial(
227 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A");
229 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
230 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
231 signin_metrics::NO_VARIATIONS_CONFIG,
233 histogram_tester()->ExpectTotalCount("Signin.XDevicePromo.Eligibility", 0);
236 TEST_F(CrossDevicePromoTest, FullyInitialized) {
237 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
238 signin_metrics::NO_VARIATIONS_CONFIG,
241 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
242 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Initialized",
243 signin_metrics::NO_VARIATIONS_CONFIG,
246 InitPromoVariation();
247 signin_manager()->SignIn("12345", "foo@bar.com", "password");
248 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
249 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
250 signin_metrics::INITIALIZED, 1);
251 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
252 signin_metrics::NO_VARIATIONS_CONFIG,
255 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
256 signin_metrics::SIGNED_IN, 1);
259 TEST_F(CrossDevicePromoTest, InitializedOptOut) {
260 // In a normal browser, the variations get set before the CrossDevicePromo is
261 // created. Here, we need to force another Init() by calling
262 // CheckPromoEligibilityForTesting().
263 InitPromoVariation();
264 signin_manager()->SignIn("12345", "foo@bar.com", "password");
265 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
267 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
268 signin_metrics::INITIALIZED, 1);
269 histogram_tester()->ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
270 signin_metrics::SIGNED_IN, 1);
272 // After opting out the initialized state remains; eligibility changes.
273 promo()->OptOut();
274 promo()->CheckPromoEligibilityForTesting();
275 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Initialized",
276 signin_metrics::INITIALIZED, 1);
277 histogram_tester()->ExpectBucketCount("Signin.XDevicePromo.Eligibility",
278 signin_metrics::OPTED_OUT, 1);
281 TEST_F(CrossDevicePromoTest, SignedInAndOut) {
282 InitPromoVariation();
285 base::HistogramTester test_signed_in;
286 signin_manager()->SignIn("12345", "foo@bar.com", "password");
287 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
288 test_signed_in.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
289 signin_metrics::SIGNED_IN, 1);
293 base::HistogramTester test_signed_out;
294 signin_manager()->SignOut(signin_metrics::SIGNOUT_TEST);
295 promo()->CheckPromoEligibilityForTesting();
296 test_signed_out.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
297 signin_metrics::NOT_SINGLE_GAIA_ACCOUNT,
302 TEST_F(CrossDevicePromoTest, TrackAccountsInCookie) {
303 InitPromoVariation();
304 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
306 ASSERT_FALSE(prefs()->HasPrefPath(
307 prefs::kCrossDevicePromoObservedSingleAccountCookie));
308 std::vector<gaia::ListedAccount> accounts;
310 // Setting a single cookie sets the time.
311 base::Time before_setting_cookies = base::Time::Now();
312 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
313 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
314 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
315 base::RunLoop().RunUntilIdle();
317 base::Time after_setting_cookies = base::Time::Now();
318 EXPECT_TRUE(prefs()->HasPrefPath(
319 prefs::kCrossDevicePromoObservedSingleAccountCookie));
320 EXPECT_LE(
321 before_setting_cookies.ToInternalValue(),
322 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie));
323 EXPECT_GE(
324 after_setting_cookies.ToInternalValue(),
325 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie));
327 // A single cookie a second time doesn't change the time.
328 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
329 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
330 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
331 base::RunLoop().RunUntilIdle();
333 EXPECT_TRUE(prefs()->HasPrefPath(
334 prefs::kCrossDevicePromoObservedSingleAccountCookie));
335 EXPECT_GE(
336 after_setting_cookies.ToInternalValue(),
337 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie));
339 // Setting accounts with an auth error doesn't change the time.
340 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
341 cookie_manager_service()->SetListAccountsResponseWebLoginRequired();
342 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
343 base::RunLoop().RunUntilIdle();
345 EXPECT_TRUE(prefs()->HasPrefPath(
346 prefs::kCrossDevicePromoObservedSingleAccountCookie));
347 EXPECT_LE(
348 before_setting_cookies.ToInternalValue(),
349 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie));
350 EXPECT_GE(
351 after_setting_cookies.ToInternalValue(),
352 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie));
354 // Seeing zero accounts clears the pref.
355 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
356 cookie_manager_service()->SetListAccountsResponseNoAccounts();
357 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
358 base::RunLoop().RunUntilIdle();
360 EXPECT_FALSE(prefs()->HasPrefPath(
361 prefs::kCrossDevicePromoObservedSingleAccountCookie));
364 TEST_F(CrossDevicePromoTest, SingleAccountEligibility) {
365 InitPromoVariation();
368 base::HistogramTester test_single_account;
369 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
370 test_single_account.ExpectUniqueSample(
371 "Signin.XDevicePromo.Eligibility",
372 signin_metrics::NOT_SINGLE_GAIA_ACCOUNT, 1);
375 // Notice a single account.
377 base::HistogramTester test_single_account;
378 std::vector<gaia::ListedAccount> accounts;
379 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
380 cookie_manager_service()->SetListAccountsResponseOneAccount("a@b.com", "1");
381 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
382 base::RunLoop().RunUntilIdle();
384 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
385 test_single_account.ExpectUniqueSample(
386 "Signin.XDevicePromo.Eligibility",
387 signin_metrics::UNKNOWN_COUNT_DEVICES, 1);
390 // Set a single account that hasn't been around for "long enough".
392 base::HistogramTester test_single_account;
393 prefs()->SetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie,
394 InTwoHours());
395 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
396 test_single_account.ExpectBucketCount(
397 "Signin.XDevicePromo.Eligibility",
398 signin_metrics::NOT_SINGLE_GAIA_ACCOUNT, 1);
402 TEST_F(CrossDevicePromoTest, NumDevicesEligibility) {
403 // Start with a variation, signed in, and one account in the cookie jar.
404 InitPromoVariation();
405 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
406 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
407 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
408 std::vector<gaia::ListedAccount> accounts;
409 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
410 base::RunLoop().RunUntilIdle();
412 // Ensure we appropriate schedule a check for device activity.
414 base::HistogramTester test_missing_list_devices;
415 int64 earliest_time_to_check_list_devices =
416 base::Time::Now().ToInternalValue();
417 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
418 int64 latest_time_to_check_list_devices = InTwoHours();
419 test_missing_list_devices.ExpectUniqueSample(
420 "Signin.XDevicePromo.Eligibility",
421 signin_metrics::UNKNOWN_COUNT_DEVICES, 1);
422 EXPECT_TRUE(
423 prefs()->HasPrefPath(prefs::kCrossDevicePromoNextFetchListDevicesTime));
424 int64 when_to_check_list_devices =
425 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime);
426 EXPECT_LT(earliest_time_to_check_list_devices, when_to_check_list_devices);
427 EXPECT_GT(latest_time_to_check_list_devices, when_to_check_list_devices);
430 // Don't reschedule the device activity check if there's one pending.
432 base::HistogramTester test_unknown_devices;
433 int64 list_devices_time = InTwoHours();
434 prefs()->SetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime,
435 list_devices_time);
436 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
437 test_unknown_devices.ExpectUniqueSample(
438 "Signin.XDevicePromo.Eligibility",
439 signin_metrics::UNKNOWN_COUNT_DEVICES, 1);
440 // The scheduled time to fetch device activity should not have changed.
441 EXPECT_EQ(
442 list_devices_time,
443 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime));
446 // Execute the device activity fetch if it's time.
448 base::HistogramTester test_unknown_devices;
449 prefs()->SetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime,
450 base::Time::Now().ToInternalValue());
451 // The DeviceActivityFetcher will return an error to the promo service.
452 fetcher_factory()->SetFakeResponse(
453 GaiaUrls::GetInstance()->oauth2_iframe_url(), "not json", net::HTTP_OK,
454 net::URLRequestStatus::SUCCESS);
455 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
456 base::RunLoop().RunUntilIdle();
457 test_unknown_devices.ExpectUniqueSample(
458 "Signin.XDevicePromo.Eligibility",
459 signin_metrics::ERROR_FETCHING_DEVICE_ACTIVITY, 1);
463 TEST_F(CrossDevicePromoTest, ThrottleDeviceActivityCall) {
464 // Start with a variation (fully throttled), signed in, one account in cookie.
465 VariationsMap variations_params;
466 variations_params[
467 CrossDevicePromo::kParamHoursBetweenDeviceActivityChecks] = "1";
468 variations_params[
469 CrossDevicePromo::kParamDaysToVerifySingleUserProfile] = "0";
470 variations_params[
471 CrossDevicePromo::kParamMinutesBetweenBrowsingSessions] = "0";
472 variations_params[
473 CrossDevicePromo::kParamMinutesMaxContextSwitchDuration] = "10";
474 variations_params[
475 CrossDevicePromo::kParamRPCThrottle] = "100";
476 EXPECT_TRUE(variations::AssociateVariationParams(
477 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A", variations_params));
478 base::FieldTrialList::CreateFieldTrial(
479 CrossDevicePromo::kCrossDevicePromoFieldTrial, "A");
481 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
482 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
483 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
484 std::vector<gaia::ListedAccount> accounts;
485 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
486 base::RunLoop().RunUntilIdle();
488 // Ensure device activity fetches get throttled.
490 base::HistogramTester test_throttle_rpc;
491 prefs()->SetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime,
492 base::Time::Now().ToInternalValue());
493 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
494 test_throttle_rpc.ExpectUniqueSample(
495 "Signin.XDevicePromo.Eligibility",
496 signin_metrics::THROTTLED_FETCHING_DEVICE_ACTIVITY, 1);
500 TEST_F(CrossDevicePromoTest, NumDevicesKnown) {
501 // Start with a variation, signed in, and one account, fetch device activity
502 // in two hours.
503 InitPromoVariation();
504 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
505 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
506 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
507 std::vector<gaia::ListedAccount> accounts;
508 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
509 base::RunLoop().RunUntilIdle();
510 prefs()->SetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime,
511 InTwoHours());
513 // Verify that knowing there are no devices for this account logs the
514 // appropriate metric for ineligibility.
516 base::HistogramTester test_no_devices;
517 prefs()->SetInteger(prefs::kCrossDevicePromoNumDevices, 0);
518 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
519 test_no_devices.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
520 signin_metrics::ZERO_DEVICES, 1);
523 // Verify that knowing there is another device for this account results in the
524 // promo being eligible to be shown.
526 prefs()->SetInteger(prefs::kCrossDevicePromoNumDevices, 1);
527 EXPECT_TRUE(promo()->CheckPromoEligibilityForTesting());
531 TEST_F(CrossDevicePromoTest, FetchDeviceResults) {
532 // Start with a variation, signed in, and one account, fetch device activity
533 // in 2 hours.
534 InitPromoVariation();
535 EXPECT_FALSE(promo()->CheckPromoEligibilityForTesting());
536 cookie_manager_service()->set_list_accounts_fetched_once_for_testing(false);
537 cookie_manager_service()->SetListAccountsResponseOneAccount("f@bar.com", "1");
538 std::vector<gaia::ListedAccount> accounts;
539 EXPECT_FALSE(cookie_manager_service()->ListAccounts(&accounts));
540 base::RunLoop().RunUntilIdle();
541 prefs()->SetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime,
542 base::Time::Now().ToInternalValue());
543 prefs()->SetInteger(prefs::kCrossDevicePromoNumDevices, 1);
545 // Verify that if the device activity fetcher returns zero devices the
546 // eligibility metric will report a ZERO_DEVICES event, and will not report
547 // the promo as eligible to be shown.
549 base::HistogramTester test_no_devices;
550 std::vector<DeviceActivityFetcher::DeviceActivity> devices;
551 int64 in_two_hours = InTwoHours();
552 promo()->OnFetchDeviceActivitySuccess(devices);
553 EXPECT_LE(
554 in_two_hours,
555 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime));
556 EXPECT_EQ(0, prefs()->GetInteger(prefs::kCrossDevicePromoNumDevices));
557 test_no_devices.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
558 signin_metrics::ZERO_DEVICES, 1);
561 // Verify that if the device activity fetcher returns one device that was
562 // recently active, the promo is marked as eligible and the eligibility
563 // metric reports an ELIGIBLE event.
565 CrossDevicePromoObserver observer(promo());
566 EXPECT_FALSE(observer.is_eligible());
567 base::HistogramTester test_one_device;
568 std::vector<DeviceActivityFetcher::DeviceActivity> devices;
569 base::Time device_last_active =
570 base::Time::Now() - base::TimeDelta::FromMinutes(4);
571 DeviceActivityFetcher::DeviceActivity device;
572 device.last_active = device_last_active;
573 device.name = "Aslan";
574 devices.push_back(device);
576 int64 in_two_hours = InTwoHours();
577 promo()->OnFetchDeviceActivitySuccess(devices);
578 EXPECT_LE(
579 in_two_hours,
580 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime));
581 EXPECT_EQ(1, prefs()->GetInteger(prefs::kCrossDevicePromoNumDevices));
582 EXPECT_EQ(device_last_active.ToInternalValue(),
583 prefs()->GetInt64(prefs::kCrossDevicePromoLastDeviceActiveTime));
584 EXPECT_TRUE(prefs()->GetBoolean(prefs::kCrossDevicePromoShouldBeShown));
585 test_one_device.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
586 signin_metrics::ELIGIBLE, 1);
587 EXPECT_TRUE(observer.is_eligible());
588 EXPECT_EQ(1, observer.times_set_eligible());
591 // Verify that if the device activity fetcher returns one device that was not
592 // recently active then the eligibility metric will report a NO_ACTIVE_DEVICES
593 // event, and will not report the promo as eligible to be shown.
595 CrossDevicePromoObserver observer(promo());
596 EXPECT_FALSE(observer.is_eligible());
597 base::HistogramTester test_one_device;
598 std::vector<DeviceActivityFetcher::DeviceActivity> devices;
599 base::Time device_last_active =
600 base::Time::Now() - base::TimeDelta::FromMinutes(30);
601 DeviceActivityFetcher::DeviceActivity device;
602 device.last_active = device_last_active;
603 device.name = "Aslan";
604 devices.push_back(device);
606 int64 in_two_hours = InTwoHours();
607 promo()->OnFetchDeviceActivitySuccess(devices);
608 EXPECT_LE(
609 in_two_hours,
610 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime));
611 EXPECT_EQ(1, prefs()->GetInteger(prefs::kCrossDevicePromoNumDevices));
612 EXPECT_EQ(device_last_active.ToInternalValue(),
613 prefs()->GetInt64(prefs::kCrossDevicePromoLastDeviceActiveTime));
614 EXPECT_FALSE(prefs()->GetBoolean(prefs::kCrossDevicePromoShouldBeShown));
615 test_one_device.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
616 signin_metrics::NO_ACTIVE_DEVICES, 1);
617 EXPECT_FALSE(observer.is_eligible());
620 // Verify that if the device activity fetcher returns two devices and one was
621 // recently active, that the promo is eligible to be shown and the last active
622 // time is stored properly.
624 CrossDevicePromoObserver observer(promo());
625 EXPECT_FALSE(observer.is_eligible());
626 base::HistogramTester test_two_devices;
627 std::vector<DeviceActivityFetcher::DeviceActivity> devices;
628 base::Time device1_last_active =
629 base::Time::Now() - base::TimeDelta::FromMinutes(30);
630 base::Time device2_last_active =
631 base::Time::Now() - base::TimeDelta::FromMinutes(3);
632 DeviceActivityFetcher::DeviceActivity device1;
633 device1.last_active = device1_last_active;
634 device1.name = "Aslan";
635 devices.push_back(device1);
636 DeviceActivityFetcher::DeviceActivity device2;
637 device2.last_active = device2_last_active;
638 device2.name = "Balrog";
639 devices.push_back(device2);
641 int64 in_two_hours = InTwoHours();
642 promo()->OnFetchDeviceActivitySuccess(devices);
643 EXPECT_LE(
644 in_two_hours,
645 prefs()->GetInt64(prefs::kCrossDevicePromoNextFetchListDevicesTime));
646 EXPECT_EQ(2, prefs()->GetInteger(prefs::kCrossDevicePromoNumDevices));
647 EXPECT_EQ(device2_last_active.ToInternalValue(),
648 prefs()->GetInt64(prefs::kCrossDevicePromoLastDeviceActiveTime));
649 EXPECT_TRUE(prefs()->GetBoolean(prefs::kCrossDevicePromoShouldBeShown));
650 test_two_devices.ExpectUniqueSample("Signin.XDevicePromo.Eligibility",
651 signin_metrics::ELIGIBLE, 1);
652 EXPECT_TRUE(observer.is_eligible());
653 EXPECT_EQ(1, observer.times_set_eligible());