1 // Copyright (c) 2012 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/chrome_to_mobile_service.h"
7 #include "base/prefs/pref_service.h"
8 #include "chrome/app/chrome_command_ids.h"
9 #include "chrome/browser/chrome_to_mobile_service_factory.h"
10 #include "chrome/browser/command_updater.h"
11 #include "chrome/browser/signin/token_service.h"
12 #include "chrome/browser/ui/browser.h"
13 #include "chrome/browser/ui/browser_command_controller.h"
14 #include "chrome/browser/ui/tabs/tab_strip_model.h"
15 #include "chrome/common/chrome_notification_types.h"
16 #include "chrome/common/extensions/feature_switch.h"
17 #include "chrome/common/pref_names.h"
18 #include "chrome/common/url_constants.h"
19 #include "chrome/test/base/browser_with_test_window_test.h"
20 #include "content/public/browser/navigation_controller.h"
21 #include "content/public/browser/notification_details.h"
22 #include "content/public/browser/notification_source.h"
23 #include "content/public/browser/web_contents.h"
24 #include "google_apis/gaia/gaia_constants.h"
28 using extensions::FeatureSwitch
;
30 class ChromeToMobileServiceTest
: public BrowserWithTestWindowTest
{
32 ChromeToMobileServiceTest();
33 virtual ~ChromeToMobileServiceTest();
35 // Get the ChromeToMobileService for the browser's profile.
36 ChromeToMobileService
* GetService() const;
38 // Ensures the returned command state matches UpdateAndGetCommandState().
39 bool UpdateAndGetVerifiedCommandState();
41 // Set |count| available mock mobile devices in the profile' prefs.
42 void SetDeviceCount(size_t count
);
44 // Fulfill the requirements to enabling the feature.
45 void FulfillFeatureRequirements();
48 FeatureSwitch::ScopedOverride enable_action_box_
;
50 DISALLOW_COPY_AND_ASSIGN(ChromeToMobileServiceTest
);
53 // Chrome To Mobile is currently gated on the Action Box UI,
54 // so need to enable this feature for the test.
55 ChromeToMobileServiceTest::ChromeToMobileServiceTest()
56 : enable_action_box_(FeatureSwitch::action_box(), true) {}
58 ChromeToMobileServiceTest::~ChromeToMobileServiceTest() {}
60 ChromeToMobileService
* ChromeToMobileServiceTest::GetService() const {
61 return ChromeToMobileServiceFactory::GetForProfile(profile());
64 bool ChromeToMobileServiceTest::UpdateAndGetVerifiedCommandState() {
65 bool state
= ChromeToMobileService::UpdateAndGetCommandState(browser());
66 CommandUpdater
* updater
= browser()->command_controller()->command_updater();
67 EXPECT_EQ(state
, updater
->IsCommandEnabled(IDC_CHROME_TO_MOBILE_PAGE
));
71 void ChromeToMobileServiceTest::SetDeviceCount(size_t count
) {
73 for (size_t i
= 0; i
< count
; ++i
)
74 mobiles
.Append(new DictionaryValue());
75 profile()->GetPrefs()->Set(prefs::kChromeToMobileDeviceList
, mobiles
);
78 void ChromeToMobileServiceTest::FulfillFeatureRequirements() {
79 AddTab(browser(), GURL("http://foo"));
81 GetService()->OnInvalidatorStateChange(syncer::INVALIDATIONS_ENABLED
);
82 EXPECT_TRUE(UpdateAndGetVerifiedCommandState());
85 // Test that GetMobiles and HasMobiles require Sync Invalidations being enabled.
86 TEST_F(ChromeToMobileServiceTest
, GetMobiles
) {
87 ChromeToMobileService
* service
= GetService();
88 EXPECT_EQ(NULL
, service
->GetMobiles());
89 EXPECT_FALSE(service
->HasMobiles());
91 // Add a mock mobile device to the profile prefs.
94 // GetMobiles() still returns NULL until Sync Invalidations are enabled.
95 EXPECT_EQ(NULL
, service
->GetMobiles());
96 EXPECT_FALSE(service
->HasMobiles());
97 service
->OnInvalidatorStateChange(syncer::INVALIDATIONS_ENABLED
);
98 EXPECT_EQ(1U, service
->GetMobiles()->GetSize());
99 EXPECT_TRUE(service
->HasMobiles());
101 // Adding and removing devices works while Sync Invalidations are enabled.
103 EXPECT_EQ(0U, service
->GetMobiles()->GetSize());
104 EXPECT_FALSE(service
->HasMobiles());
106 EXPECT_EQ(2U, service
->GetMobiles()->GetSize());
107 EXPECT_TRUE(service
->HasMobiles());
109 // GetMobiles() returns NULL after Sync Invalidations are disabled.
110 service
->OnInvalidatorStateChange(syncer::TRANSIENT_INVALIDATION_ERROR
);
111 EXPECT_EQ(NULL
, service
->GetMobiles());
112 EXPECT_FALSE(service
->HasMobiles());
113 service
->OnInvalidatorStateChange(syncer::INVALIDATION_CREDENTIALS_REJECTED
);
114 EXPECT_EQ(NULL
, service
->GetMobiles());
115 EXPECT_FALSE(service
->HasMobiles());
118 // Test fulfilling the requirements to enable the feature.
119 TEST_F(ChromeToMobileServiceTest
, RequirementsToEnable
) {
120 // Navigate to a page with a URL that is valid to send.
121 AddTab(browser(), GURL("http://foo"));
122 EXPECT_FALSE(UpdateAndGetVerifiedCommandState());
124 // Add a mock mobile device to the profile prefs.
126 EXPECT_FALSE(UpdateAndGetVerifiedCommandState());
128 // Send a fake notification that Sync Invalidations are enabled.
129 GetService()->OnInvalidatorStateChange(syncer::INVALIDATIONS_ENABLED
);
130 EXPECT_TRUE(UpdateAndGetVerifiedCommandState());
133 // Test that the feature handles mobile device count changes properly.
134 TEST_F(ChromeToMobileServiceTest
, MobileDevicesAreRequired
) {
135 FulfillFeatureRequirements();
137 // Removing all devices disables the feature.
139 EXPECT_FALSE(UpdateAndGetVerifiedCommandState());
141 // Restoring mobile devices re-enables the feature.
143 EXPECT_TRUE(UpdateAndGetVerifiedCommandState());
145 EXPECT_TRUE(UpdateAndGetVerifiedCommandState());
148 // Test that the feature handles Sync Invalidations state changes properly.
149 TEST_F(ChromeToMobileServiceTest
, SyncInvalidationsAreRequired
) {
150 FulfillFeatureRequirements();
152 // Disabling Sync Invalidations disables the feature.
153 GetService()->OnInvalidatorStateChange(syncer::TRANSIENT_INVALIDATION_ERROR
);
154 EXPECT_FALSE(UpdateAndGetVerifiedCommandState());
156 // Re-enabling Sync Invalidations re-enables the feature.
157 GetService()->OnInvalidatorStateChange(syncer::INVALIDATIONS_ENABLED
);
158 EXPECT_TRUE(UpdateAndGetVerifiedCommandState());
161 // Test that the feature handles various page URLs properly.
162 TEST_F(ChromeToMobileServiceTest
, CertainSchemesAreRequired
) {
163 FulfillFeatureRequirements();
165 // Only http:, https:, and ftp: URLs are valid to send.
170 { "http://foo", true }, { "https://foo", true }, { "ftp://foo", true },
171 { "about:foo", false }, { "chrome://foo", false }, { "file://foo", false },
172 { "data://foo", false }, { "view-source:foo", false },
175 content::NavigationController
* controller
=
176 &browser()->tab_strip_model()->GetActiveWebContents()->GetController();
177 for (size_t i
= 0; i
< ARRAYSIZE_UNSAFE(cases
); ++i
) {
178 NavigateAndCommit(controller
, GURL(cases
[i
].url
));
179 EXPECT_EQ(cases
[i
].enabled
, UpdateAndGetVerifiedCommandState());
183 // Ensure that only relevant notifications invalidate the access token.
184 TEST_F(ChromeToMobileServiceTest
, TokenNotifications
) {
185 const char dummy_string
[] = "dummy";
186 ChromeToMobileService
* service
= GetService();
187 service
->SetAccessTokenForTest(dummy_string
);
188 ASSERT_FALSE(service
->GetAccessTokenForTest().empty());
190 // Send dummy service/token details (should not clear the token).
191 TokenService::TokenAvailableDetails
dummy_details(dummy_string
, dummy_string
);
192 service
->Observe(chrome::NOTIFICATION_TOKEN_AVAILABLE
,
193 content::Source
<ChromeToMobileServiceTest
>(this),
194 content::Details
<TokenService::TokenAvailableDetails
>(&dummy_details
));
195 EXPECT_FALSE(service
->GetAccessTokenForTest().empty());
197 // Send a Gaia OAuth2 Login service dummy token (should clear the token).
198 TokenService::TokenAvailableDetails
login_details(
199 GaiaConstants::kGaiaOAuth2LoginRefreshToken
, dummy_string
);
200 service
->Observe(chrome::NOTIFICATION_TOKEN_AVAILABLE
,
201 content::Source
<ChromeToMobileServiceTest
>(this),
202 content::Details
<TokenService::TokenAvailableDetails
>(&login_details
));
203 EXPECT_TRUE(service
->GetAccessTokenForTest().empty());