1 // Copyright 2014 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/password_manager/chrome_password_manager_client.h"
7 #include "base/command_line.h"
8 #include "base/prefs/pref_registry_simple.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/prefs/testing_pref_service.h"
11 #include "base/strings/string16.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "chrome/browser/sync/profile_sync_service_factory.h"
14 #include "chrome/browser/sync/profile_sync_service_mock.h"
15 #include "chrome/common/channel_info.h"
16 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
17 #include "chrome/test/base/testing_pref_service_syncable.h"
18 #include "chrome/test/base/testing_profile.h"
19 #include "components/autofill/content/common/autofill_messages.h"
20 #include "components/password_manager/content/browser/password_manager_internals_service_factory.h"
21 #include "components/password_manager/content/common/credential_manager_messages.h"
22 #include "components/password_manager/core/browser/credentials_filter.h"
23 #include "components/password_manager/core/browser/log_receiver.h"
24 #include "components/password_manager/core/browser/password_manager_internals_service.h"
25 #include "components/password_manager/core/common/credential_manager_types.h"
26 #include "components/password_manager/core/common/password_manager_pref_names.h"
27 #include "components/password_manager/core/common/password_manager_switches.h"
28 #include "components/version_info/version_info.h"
29 #include "content/public/browser/browser_context.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/test/mock_render_process_host.h"
32 #include "testing/gmock/include/gmock/gmock.h"
33 #include "testing/gtest/include/gtest/gtest.h"
35 using content::BrowserContext
;
36 using content::WebContents
;
37 using testing::Return
;
42 const char kTestText
[] = "abcd1234";
44 class MockLogReceiver
: public password_manager::LogReceiver
{
46 MOCK_METHOD1(LogSavePasswordProgress
, void(const std::string
&));
49 // TODO(vabr): Get rid of the mocked client in the client's own test, see
50 // http://crbug.com/474577.
51 class MockChromePasswordManagerClient
: public ChromePasswordManagerClient
{
53 MOCK_CONST_METHOD0(DidLastPageLoadEncounterSSLErrors
, bool());
55 explicit MockChromePasswordManagerClient(content::WebContents
* web_contents
)
56 : ChromePasswordManagerClient(web_contents
, nullptr) {
57 ON_CALL(*this, DidLastPageLoadEncounterSSLErrors())
58 .WillByDefault(testing::Return(false));
60 ~MockChromePasswordManagerClient() override
{}
63 DISALLOW_COPY_AND_ASSIGN(MockChromePasswordManagerClient
);
68 class ChromePasswordManagerClientTest
: public ChromeRenderViewHostTestHarness
{
70 ChromePasswordManagerClientTest();
72 void SetUp() override
;
74 TestingPrefServiceSyncable
* prefs() {
75 return profile()->GetTestingPrefService();
79 ChromePasswordManagerClient
* GetClient();
81 // If the test IPC sink contains an AutofillMsg_SetLoggingState message, then
82 // copies its argument into |activation_flag| and returns true. Otherwise
84 bool WasLoggingActivationMessageSent(bool* activation_flag
);
86 password_manager::PasswordManagerInternalsService
* service_
;
88 testing::StrictMock
<MockLogReceiver
> receiver_
;
89 TestingPrefServiceSimple prefs_
;
92 ChromePasswordManagerClientTest::ChromePasswordManagerClientTest()
96 void ChromePasswordManagerClientTest::SetUp() {
97 ChromeRenderViewHostTestHarness::SetUp();
98 prefs_
.registry()->RegisterBooleanPref(
99 password_manager::prefs::kPasswordManagerSavingEnabled
, true);
100 ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
101 web_contents(), nullptr);
102 service_
= password_manager::PasswordManagerInternalsServiceFactory::
103 GetForBrowserContext(profile());
104 ASSERT_TRUE(service_
);
107 ChromePasswordManagerClient
* ChromePasswordManagerClientTest::GetClient() {
108 return ChromePasswordManagerClient::FromWebContents(web_contents());
111 bool ChromePasswordManagerClientTest::WasLoggingActivationMessageSent(
112 bool* activation_flag
) {
113 const uint32 kMsgID
= AutofillMsg_SetLoggingState::ID
;
114 const IPC::Message
* message
=
115 process()->sink().GetFirstMessageMatching(kMsgID
);
118 base::Tuple
<bool> param
;
119 AutofillMsg_SetLoggingState::Read(message
, ¶m
);
120 *activation_flag
= base::get
<0>(param
);
121 process()->sink().ClearMessages();
125 TEST_F(ChromePasswordManagerClientTest
, LogSavePasswordProgressNoReceiver
) {
126 ChromePasswordManagerClient
* client
= GetClient();
128 EXPECT_CALL(receiver_
, LogSavePasswordProgress(kTestText
)).Times(0);
129 // Before attaching the receiver, no text should be passed.
130 client
->LogSavePasswordProgress(kTestText
);
131 EXPECT_FALSE(client
->IsLoggingActive());
134 TEST_F(ChromePasswordManagerClientTest
, LogSavePasswordProgressAttachReceiver
) {
135 ChromePasswordManagerClient
* client
= GetClient();
136 EXPECT_FALSE(client
->IsLoggingActive());
138 // After attaching the logger, text should be passed.
139 service_
->RegisterReceiver(&receiver_
);
140 EXPECT_TRUE(client
->IsLoggingActive());
141 EXPECT_CALL(receiver_
, LogSavePasswordProgress(kTestText
)).Times(1);
142 client
->LogSavePasswordProgress(kTestText
);
143 service_
->UnregisterReceiver(&receiver_
);
144 EXPECT_FALSE(client
->IsLoggingActive());
147 TEST_F(ChromePasswordManagerClientTest
, LogSavePasswordProgressDetachReceiver
) {
148 ChromePasswordManagerClient
* client
= GetClient();
150 service_
->RegisterReceiver(&receiver_
);
151 EXPECT_TRUE(client
->IsLoggingActive());
152 service_
->UnregisterReceiver(&receiver_
);
153 EXPECT_FALSE(client
->IsLoggingActive());
155 // After detaching the logger, no text should be passed.
156 EXPECT_CALL(receiver_
, LogSavePasswordProgress(kTestText
)).Times(0);
157 client
->LogSavePasswordProgress(kTestText
);
160 TEST_F(ChromePasswordManagerClientTest
, LogSavePasswordProgressNotifyRenderer
) {
161 ChromePasswordManagerClient
* client
= GetClient();
162 bool logging_active
= false;
164 // Initially, the logging should be off, so no IPC messages.
165 EXPECT_FALSE(WasLoggingActivationMessageSent(&logging_active
));
167 service_
->RegisterReceiver(&receiver_
);
168 EXPECT_TRUE(client
->IsLoggingActive());
169 EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active
));
170 EXPECT_TRUE(logging_active
);
172 service_
->UnregisterReceiver(&receiver_
);
173 EXPECT_FALSE(client
->IsLoggingActive());
174 EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active
));
175 EXPECT_FALSE(logging_active
);
178 TEST_F(ChromePasswordManagerClientTest
, AnswerToPingsAboutLoggingState_Active
) {
179 service_
->RegisterReceiver(&receiver_
);
181 process()->sink().ClearMessages();
183 // Ping the client for logging activity update.
184 AutofillHostMsg_PasswordAutofillAgentConstructed
msg(0);
185 static_cast<content::WebContentsObserver
*>(GetClient())->OnMessageReceived(
186 msg
, web_contents()->GetMainFrame());
188 bool logging_active
= false;
189 EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active
));
190 EXPECT_TRUE(logging_active
);
192 service_
->UnregisterReceiver(&receiver_
);
195 TEST_F(ChromePasswordManagerClientTest
,
196 AnswerToPingsAboutLoggingState_Inactive
) {
197 process()->sink().ClearMessages();
199 // Ping the client for logging activity update.
200 AutofillHostMsg_PasswordAutofillAgentConstructed
msg(0);
201 static_cast<content::WebContentsObserver
*>(GetClient())->OnMessageReceived(
202 msg
, web_contents()->GetMainFrame());
204 bool logging_active
= true;
205 EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active
));
206 EXPECT_FALSE(logging_active
);
209 TEST_F(ChromePasswordManagerClientTest
,
210 IsAutomaticPasswordSavingEnabledDefaultBehaviourTest
) {
211 EXPECT_FALSE(GetClient()->IsAutomaticPasswordSavingEnabled());
214 TEST_F(ChromePasswordManagerClientTest
,
215 IsAutomaticPasswordSavingEnabledWhenFlagIsSetTest
) {
216 base::CommandLine::ForCurrentProcess()->AppendSwitch(
217 password_manager::switches::kEnableAutomaticPasswordSaving
);
218 if (chrome::GetChannel() == version_info::Channel::UNKNOWN
)
219 EXPECT_TRUE(GetClient()->IsAutomaticPasswordSavingEnabled());
221 EXPECT_FALSE(GetClient()->IsAutomaticPasswordSavingEnabled());
224 TEST_F(ChromePasswordManagerClientTest
, LogToAReceiver
) {
225 ChromePasswordManagerClient
* client
= GetClient();
226 service_
->RegisterReceiver(&receiver_
);
227 EXPECT_TRUE(client
->IsLoggingActive());
229 EXPECT_CALL(receiver_
, LogSavePasswordProgress(kTestText
)).Times(1);
230 client
->LogSavePasswordProgress(kTestText
);
232 service_
->UnregisterReceiver(&receiver_
);
233 EXPECT_FALSE(client
->IsLoggingActive());
236 TEST_F(ChromePasswordManagerClientTest
,
237 IsPasswordManagementEnabledForCurrentPage
) {
238 ChromePasswordManagerClient
* client
= GetClient();
240 GURL("https://accounts.google.com/ServiceLogin?continue="
241 "https://passwords.google.com/settings&rart=123"));
242 EXPECT_FALSE(client
->IsPasswordManagementEnabledForCurrentPage());
244 // Password site is inaccesible via HTTP, but because of HSTS the following
245 // link should still continue to https://passwords.google.com.
247 GURL("https://accounts.google.com/ServiceLogin?continue="
248 "http://passwords.google.com/settings&rart=123"));
249 EXPECT_FALSE(client
->IsPasswordManagementEnabledForCurrentPage());
250 EXPECT_FALSE(client
->IsSavingEnabledForCurrentPage());
252 // Specifying default port still passes.
254 GURL("https://accounts.google.com/ServiceLogin?continue="
255 "https://passwords.google.com:443/settings&rart=123"));
256 EXPECT_FALSE(client
->IsPasswordManagementEnabledForCurrentPage());
257 EXPECT_FALSE(client
->IsSavingEnabledForCurrentPage());
259 // Encoded URL is considered the same.
261 GURL("https://accounts.google.com/ServiceLogin?continue="
262 "https://passwords.%67oogle.com/settings&rart=123"));
263 EXPECT_FALSE(client
->IsPasswordManagementEnabledForCurrentPage());
264 EXPECT_FALSE(client
->IsSavingEnabledForCurrentPage());
266 // Make sure testing sites are disabled as well.
268 GURL("https://accounts.google.com/Login?continue="
269 "https://passwords-ac-testing.corp.google.com/settings&rart=456"));
270 EXPECT_FALSE(client
->IsSavingEnabledForCurrentPage());
271 EXPECT_FALSE(client
->IsPasswordManagementEnabledForCurrentPage());
273 // Fully qualified domain name is considered a different hostname by GURL.
274 // Ideally this would not be the case, but this quirk can be avoided by
275 // verification on the server. This test is simply documentation of this
278 GURL("https://accounts.google.com/ServiceLogin?continue="
279 "https://passwords.google.com./settings&rart=123"));
280 EXPECT_TRUE(client
->IsPasswordManagementEnabledForCurrentPage());
282 // Not a transactional reauth page.
284 GURL("https://accounts.google.com/ServiceLogin?continue="
285 "https://passwords.google.com/settings"));
286 EXPECT_TRUE(client
->IsPasswordManagementEnabledForCurrentPage());
288 // Should be enabled for other transactional reauth pages.
290 GURL("https://accounts.google.com/ServiceLogin?continue="
291 "https://mail.google.com&rart=234"));
292 EXPECT_TRUE(client
->IsPasswordManagementEnabledForCurrentPage());
294 // Reauth pages are only on accounts.google.com
296 GURL("https://other.site.com/ServiceLogin?continue="
297 "https://passwords.google.com&rart=234"));
298 EXPECT_TRUE(client
->IsPasswordManagementEnabledForCurrentPage());
301 TEST_F(ChromePasswordManagerClientTest
, GetPasswordSyncState
) {
302 ChromePasswordManagerClient
* client
= GetClient();
304 ProfileSyncServiceMock
* mock_sync_service
=
305 static_cast<ProfileSyncServiceMock
*>(
306 ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
307 profile(), ProfileSyncServiceMock::BuildMockProfileSyncService
));
309 syncer::ModelTypeSet active_types
;
310 active_types
.Put(syncer::PASSWORDS
);
311 EXPECT_CALL(*mock_sync_service
, HasSyncSetupCompleted())
312 .WillRepeatedly(Return(true));
313 EXPECT_CALL(*mock_sync_service
, IsSyncActive()).WillRepeatedly(Return(true));
314 EXPECT_CALL(*mock_sync_service
, GetActiveDataTypes())
315 .WillRepeatedly(Return(active_types
));
316 EXPECT_CALL(*mock_sync_service
, IsUsingSecondaryPassphrase())
317 .WillRepeatedly(Return(false));
319 // Passwords are syncing and custom passphrase isn't used.
320 EXPECT_EQ(password_manager::SYNCING_NORMAL_ENCRYPTION
,
321 client
->GetPasswordSyncState());
323 // Again, using a custom passphrase.
324 EXPECT_CALL(*mock_sync_service
, IsUsingSecondaryPassphrase())
325 .WillRepeatedly(Return(true));
327 EXPECT_EQ(password_manager::SYNCING_WITH_CUSTOM_PASSPHRASE
,
328 client
->GetPasswordSyncState());
330 // Report correctly if we aren't syncing passwords.
331 active_types
.Remove(syncer::PASSWORDS
);
332 active_types
.Put(syncer::BOOKMARKS
);
333 EXPECT_CALL(*mock_sync_service
, GetActiveDataTypes())
334 .WillRepeatedly(Return(active_types
));
336 EXPECT_EQ(password_manager::NOT_SYNCING_PASSWORDS
,
337 client
->GetPasswordSyncState());
339 // Again, without a custom passphrase.
340 EXPECT_CALL(*mock_sync_service
, IsUsingSecondaryPassphrase())
341 .WillRepeatedly(Return(false));
343 EXPECT_EQ(password_manager::NOT_SYNCING_PASSWORDS
,
344 client
->GetPasswordSyncState());
347 TEST_F(ChromePasswordManagerClientTest
, IsOffTheRecordTest
) {
348 ChromePasswordManagerClient
* client
= GetClient();
350 profile()->ForceIncognito(true);
351 EXPECT_TRUE(client
->IsOffTheRecord());
353 profile()->ForceIncognito(false);
354 EXPECT_FALSE(client
->IsOffTheRecord());
357 TEST_F(ChromePasswordManagerClientTest
,
358 SavingDependsOnManagerEnabledPreference
) {
359 // Test that saving passwords depends on the password manager enabled
361 ChromePasswordManagerClient
* client
= GetClient();
362 prefs()->SetUserPref(password_manager::prefs::kPasswordManagerSavingEnabled
,
363 new base::FundamentalValue(true));
364 EXPECT_TRUE(client
->IsSavingEnabledForCurrentPage());
365 prefs()->SetUserPref(password_manager::prefs::kPasswordManagerSavingEnabled
,
366 new base::FundamentalValue(false));
367 EXPECT_FALSE(client
->IsSavingEnabledForCurrentPage());
370 TEST_F(ChromePasswordManagerClientTest
, IsSavingEnabledForCurrentPageTest
) {
371 scoped_ptr
<MockChromePasswordManagerClient
> client(
372 new MockChromePasswordManagerClient(web_contents()));
373 // Functionality disabled if there is SSL errors.
374 EXPECT_CALL(*client
, DidLastPageLoadEncounterSSLErrors())
375 .WillRepeatedly(Return(true));
376 EXPECT_FALSE(client
->IsSavingEnabledForCurrentPage());
378 // Functionality disabled if there are SSL errors and the manager itself is
380 prefs()->SetUserPref(password_manager::prefs::kPasswordManagerSavingEnabled
,
381 new base::FundamentalValue(false));
382 EXPECT_FALSE(client
->IsSavingEnabledForCurrentPage());
384 // Functionality disabled if there are no SSL errorsm, but the manager itself
386 EXPECT_CALL(*client
, DidLastPageLoadEncounterSSLErrors())
387 .WillRepeatedly(Return(false));
388 prefs()->SetUserPref(password_manager::prefs::kPasswordManagerSavingEnabled
,
389 new base::FundamentalValue(false));
390 EXPECT_FALSE(client
->IsSavingEnabledForCurrentPage());
392 // Functionality enabled if there are no SSL errors and the manager is
394 EXPECT_CALL(*client
, DidLastPageLoadEncounterSSLErrors())
395 .WillRepeatedly(Return(false));
396 prefs()->SetUserPref(password_manager::prefs::kPasswordManagerSavingEnabled
,
397 new base::FundamentalValue(true));
398 EXPECT_TRUE(client
->IsSavingEnabledForCurrentPage());
400 // Functionality disabled in Incognito mode.
401 profile()->ForceIncognito(true);
402 EXPECT_FALSE(client
->IsSavingEnabledForCurrentPage());
404 // Functionality disabled in Incognito mode also when manager itself is
406 prefs()->SetUserPref(password_manager::prefs::kPasswordManagerSavingEnabled
,
407 new base::FundamentalValue(true));
408 EXPECT_FALSE(client
->IsSavingEnabledForCurrentPage());
409 profile()->ForceIncognito(false);
412 TEST_F(ChromePasswordManagerClientTest
, GetLastCommittedEntryURL_Empty
) {
413 EXPECT_EQ(GURL::EmptyGURL(), GetClient()->GetLastCommittedEntryURL());
416 TEST_F(ChromePasswordManagerClientTest
, GetLastCommittedEntryURL
) {
418 "https://accounts.google.com/ServiceLogin?continue="
419 "https://passwords.google.com/settings&rart=123");
420 NavigateAndCommit(kUrl
);
421 EXPECT_EQ(kUrl
, GetClient()->GetLastCommittedEntryURL());