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/prefs/pref_service_syncable.h"
12 #include "chrome/browser/signin/chrome_signin_client_factory.h"
13 #include "chrome/browser/signin/cross_device_promo_factory.h"
14 #include "chrome/browser/signin/fake_gaia_cookie_manager_service.h"
15 #include "chrome/browser/signin/fake_signin_manager_builder.h"
16 #include "chrome/browser/signin/gaia_cookie_manager_service_factory.h"
17 #include "chrome/browser/signin/signin_manager_factory.h"
18 #include "chrome/browser/signin/test_signin_client_builder.h"
19 #include "chrome/common/pref_names.h"
20 #include "chrome/test/base/testing_browser_process.h"
21 #include "chrome/test/base/testing_pref_service_syncable.h"
22 #include "chrome/test/base/testing_profile.h"
23 #include "chrome/test/base/testing_profile_manager.h"
24 #include "components/signin/core/browser/signin_manager.h"
25 #include "components/signin/core/browser/signin_metrics.h"
26 #include "components/signin/core/browser/test_signin_client.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"
36 typedef std::map
<std::string
, std::string
> VariationsMap
;
39 return (base::Time::Now() + base::TimeDelta::FromHours(2)).ToInternalValue();
44 class CrossDevicePromoObserver
: public CrossDevicePromo::Observer
{
46 explicit CrossDevicePromoObserver(CrossDevicePromo
* promo
)
48 times_set_eligible_(0),
49 times_set_ineligible_(0),
51 promo
->AddObserver(this);
54 ~CrossDevicePromoObserver() { promo_
->RemoveObserver(this); }
56 void OnPromoEligibilityChanged(bool eligible
) override
{
59 ++times_set_eligible_
;
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_
; }
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
{
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_
;
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
));
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
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
;
163 CrossDevicePromo::kParamHoursBetweenDeviceActivityChecks
] = "2";
165 CrossDevicePromo::kParamDaysToVerifySingleUserProfile
] = "0";
167 CrossDevicePromo::kParamMinutesBetweenBrowsingSessions
] = "0";
169 CrossDevicePromo::kParamMinutesMaxContextSwitchDuration
] = "10";
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
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());
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
;
221 CrossDevicePromo::kParamHoursBetweenDeviceActivityChecks
] = "1";
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 EXPECT_FALSE(histogram_tester()->GetHistogramSamplesSinceCreation(
234 "Signin.XDevicePromo.Eligibility"));
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.
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
));
322 before_setting_cookies
.ToInternalValue(),
323 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie
));
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
));
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
));
349 before_setting_cookies
.ToInternalValue(),
350 prefs()->GetInt64(prefs::kCrossDevicePromoObservedSingleAccountCookie
));
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
,
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);
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
,
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.
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
;
468 CrossDevicePromo::kParamHoursBetweenDeviceActivityChecks
] = "1";
470 CrossDevicePromo::kParamDaysToVerifySingleUserProfile
] = "0";
472 CrossDevicePromo::kParamMinutesBetweenBrowsingSessions
] = "0";
474 CrossDevicePromo::kParamMinutesMaxContextSwitchDuration
] = "10";
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
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
,
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
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
);
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
);
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
);
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
);
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());