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/strings/string16.h"
9 #include "base/strings/utf_string_conversions.h"
10 #include "chrome/common/chrome_version_info.h"
11 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
12 #include "chrome/test/base/testing_profile.h"
13 #include "components/autofill/content/common/autofill_messages.h"
14 #include "components/password_manager/content/browser/password_manager_internals_service_factory.h"
15 #include "components/password_manager/content/common/credential_manager_messages.h"
16 #include "components/password_manager/content/common/credential_manager_types.h"
17 #include "components/password_manager/core/browser/log_receiver.h"
18 #include "components/password_manager/core/browser/password_manager_internals_service.h"
19 #include "components/password_manager/core/common/password_manager_switches.h"
20 #include "content/public/browser/browser_context.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/test/mock_render_process_host.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
26 using content::BrowserContext;
27 using content::WebContents;
31 const char kTestText[] = "abcd1234";
32 const int kRequestId = 4;
34 class MockLogReceiver : public password_manager::LogReceiver {
36 MOCK_METHOD1(LogSavePasswordProgress, void(const std::string&));
39 class TestChromePasswordManagerClient : public ChromePasswordManagerClient {
41 explicit TestChromePasswordManagerClient(content::WebContents* web_contents)
42 : ChromePasswordManagerClient(web_contents, NULL),
43 is_sync_account_credential_(false) {}
44 virtual ~TestChromePasswordManagerClient() {}
46 virtual bool IsSyncAccountCredential(
47 const std::string& username,
48 const std::string& origin) const OVERRIDE {
49 return is_sync_account_credential_;
52 void set_is_sync_account_credential(bool is_sync_account_credential) {
53 is_sync_account_credential_ = is_sync_account_credential;
57 bool is_sync_account_credential_;
59 DISALLOW_COPY_AND_ASSIGN(TestChromePasswordManagerClient);
64 class ChromePasswordManagerClientTest : public ChromeRenderViewHostTestHarness {
66 ChromePasswordManagerClientTest();
68 virtual void SetUp() OVERRIDE;
71 ChromePasswordManagerClient* GetClient();
73 // If the test IPC sink contains an AutofillMsg_SetLoggingState message, then
74 // copies its argument into |activation_flag| and returns true. Otherwise
76 bool WasLoggingActivationMessageSent(bool* activation_flag);
78 password_manager::PasswordManagerInternalsService* service_;
80 testing::StrictMock<MockLogReceiver> receiver_;
83 ChromePasswordManagerClientTest::ChromePasswordManagerClientTest()
87 void ChromePasswordManagerClientTest::SetUp() {
88 ChromeRenderViewHostTestHarness::SetUp();
89 ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
90 web_contents(), NULL);
91 service_ = password_manager::PasswordManagerInternalsServiceFactory::
92 GetForBrowserContext(profile());
93 ASSERT_TRUE(service_);
96 ChromePasswordManagerClient* ChromePasswordManagerClientTest::GetClient() {
97 return ChromePasswordManagerClient::FromWebContents(web_contents());
100 bool ChromePasswordManagerClientTest::WasLoggingActivationMessageSent(
101 bool* activation_flag) {
102 const uint32 kMsgID = AutofillMsg_SetLoggingState::ID;
103 const IPC::Message* message =
104 process()->sink().GetFirstMessageMatching(kMsgID);
108 AutofillMsg_SetLoggingState::Read(message, ¶m);
109 *activation_flag = param.a;
110 process()->sink().ClearMessages();
114 TEST_F(ChromePasswordManagerClientTest, LogSavePasswordProgressNoReceiver) {
115 ChromePasswordManagerClient* client = GetClient();
117 EXPECT_CALL(receiver_, LogSavePasswordProgress(kTestText)).Times(0);
118 // Before attaching the receiver, no text should be passed.
119 client->LogSavePasswordProgress(kTestText);
120 EXPECT_FALSE(client->IsLoggingActive());
123 TEST_F(ChromePasswordManagerClientTest, LogSavePasswordProgressAttachReceiver) {
124 ChromePasswordManagerClient* client = GetClient();
125 EXPECT_FALSE(client->IsLoggingActive());
127 // After attaching the logger, text should be passed.
128 service_->RegisterReceiver(&receiver_);
129 EXPECT_TRUE(client->IsLoggingActive());
130 EXPECT_CALL(receiver_, LogSavePasswordProgress(kTestText)).Times(1);
131 client->LogSavePasswordProgress(kTestText);
132 service_->UnregisterReceiver(&receiver_);
133 EXPECT_FALSE(client->IsLoggingActive());
136 TEST_F(ChromePasswordManagerClientTest, LogSavePasswordProgressDetachReceiver) {
137 ChromePasswordManagerClient* client = GetClient();
139 service_->RegisterReceiver(&receiver_);
140 EXPECT_TRUE(client->IsLoggingActive());
141 service_->UnregisterReceiver(&receiver_);
142 EXPECT_FALSE(client->IsLoggingActive());
144 // After detaching the logger, no text should be passed.
145 EXPECT_CALL(receiver_, LogSavePasswordProgress(kTestText)).Times(0);
146 client->LogSavePasswordProgress(kTestText);
149 TEST_F(ChromePasswordManagerClientTest, LogSavePasswordProgressNotifyRenderer) {
150 ChromePasswordManagerClient* client = GetClient();
151 bool logging_active = false;
153 // Initially, the logging should be off, so no IPC messages.
154 EXPECT_FALSE(WasLoggingActivationMessageSent(&logging_active));
156 service_->RegisterReceiver(&receiver_);
157 EXPECT_TRUE(client->IsLoggingActive());
158 EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active));
159 EXPECT_TRUE(logging_active);
161 service_->UnregisterReceiver(&receiver_);
162 EXPECT_FALSE(client->IsLoggingActive());
163 EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active));
164 EXPECT_FALSE(logging_active);
167 TEST_F(ChromePasswordManagerClientTest, AnswerToPingsAboutLoggingState_Active) {
168 service_->RegisterReceiver(&receiver_);
170 process()->sink().ClearMessages();
172 // Ping the client for logging activity update.
173 AutofillHostMsg_PasswordAutofillAgentConstructed msg(0);
174 static_cast<IPC::Listener*>(GetClient())->OnMessageReceived(msg);
176 bool logging_active = false;
177 EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active));
178 EXPECT_TRUE(logging_active);
180 service_->UnregisterReceiver(&receiver_);
183 TEST_F(ChromePasswordManagerClientTest,
184 AnswerToPingsAboutLoggingState_Inactive) {
185 process()->sink().ClearMessages();
187 // Ping the client for logging activity update.
188 AutofillHostMsg_PasswordAutofillAgentConstructed msg(0);
189 static_cast<IPC::Listener*>(GetClient())->OnMessageReceived(msg);
191 bool logging_active = true;
192 EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active));
193 EXPECT_FALSE(logging_active);
196 TEST_F(ChromePasswordManagerClientTest,
197 IsAutomaticPasswordSavingEnabledDefaultBehaviourTest) {
198 EXPECT_FALSE(GetClient()->IsAutomaticPasswordSavingEnabled());
201 TEST_F(ChromePasswordManagerClientTest,
202 IsAutomaticPasswordSavingEnabledWhenFlagIsSetTest) {
203 CommandLine::ForCurrentProcess()->AppendSwitch(
204 password_manager::switches::kEnableAutomaticPasswordSaving);
205 if (chrome::VersionInfo::GetChannel() == chrome::VersionInfo::CHANNEL_UNKNOWN)
206 EXPECT_TRUE(GetClient()->IsAutomaticPasswordSavingEnabled());
208 EXPECT_FALSE(GetClient()->IsAutomaticPasswordSavingEnabled());
211 TEST_F(ChromePasswordManagerClientTest, LogToAReceiver) {
212 ChromePasswordManagerClient* client = GetClient();
213 service_->RegisterReceiver(&receiver_);
214 EXPECT_TRUE(client->IsLoggingActive());
216 EXPECT_CALL(receiver_, LogSavePasswordProgress(kTestText)).Times(1);
217 client->LogSavePasswordProgress(kTestText);
219 service_->UnregisterReceiver(&receiver_);
220 EXPECT_FALSE(client->IsLoggingActive());
223 TEST_F(ChromePasswordManagerClientTest, ShouldFilterAutofillResult_Reauth) {
224 // Make client disallow only reauth requests.
225 CommandLine* command_line = CommandLine::ForCurrentProcess();
226 command_line->AppendSwitch(
227 password_manager::switches::kDisallowAutofillSyncCredentialForReauth);
228 scoped_ptr<TestChromePasswordManagerClient> client(
229 new TestChromePasswordManagerClient(web_contents()));
230 autofill::PasswordForm form;
232 client->set_is_sync_account_credential(false);
234 GURL("https://accounts.google.com/login?rart=123&continue=blah"));
235 EXPECT_FALSE(client->ShouldFilterAutofillResult(form));
237 client->set_is_sync_account_credential(true);
239 GURL("https://accounts.google.com/login?rart=123&continue=blah"));
240 EXPECT_TRUE(client->ShouldFilterAutofillResult(form));
242 // This counts as a reauth url, though a valid URL should have a value for
244 NavigateAndCommit(GURL("https://accounts.google.com/addlogin?rart"));
245 EXPECT_TRUE(client->ShouldFilterAutofillResult(form));
247 NavigateAndCommit(GURL("https://accounts.google.com/login?param=123"));
248 EXPECT_FALSE(client->ShouldFilterAutofillResult(form));
250 NavigateAndCommit(GURL("https://site.com/login?rart=678"));
251 EXPECT_FALSE(client->ShouldFilterAutofillResult(form));
254 TEST_F(ChromePasswordManagerClientTest, ShouldFilterAutofillResult) {
255 // Normally the client should allow any credentials through, even if they
256 // are the sync credential.
257 scoped_ptr<TestChromePasswordManagerClient> client(
258 new TestChromePasswordManagerClient(web_contents()));
259 autofill::PasswordForm form;
260 client->set_is_sync_account_credential(true);
261 NavigateAndCommit(GURL("https://accounts.google.com/Login"));
262 EXPECT_FALSE(client->ShouldFilterAutofillResult(form));
264 // Adding disallow switch should cause sync credential to be filtered.
265 CommandLine* command_line = CommandLine::ForCurrentProcess();
266 command_line->AppendSwitch(
267 password_manager::switches::kDisallowAutofillSyncCredential);
268 client.reset(new TestChromePasswordManagerClient(web_contents()));
269 client->set_is_sync_account_credential(true);
270 NavigateAndCommit(GURL("https://accounts.google.com/Login"));
271 EXPECT_TRUE(client->ShouldFilterAutofillResult(form));
274 TEST_F(ChromePasswordManagerClientTest,
275 IsPasswordManagerEnabledForCurrentPage) {
276 ChromePasswordManagerClient* client = GetClient();
278 GURL("https://accounts.google.com/ServiceLogin?continue="
279 "https://passwords.google.com/settings&rart=123"));
280 EXPECT_FALSE(client->IsPasswordManagerEnabledForCurrentPage());
282 // Password site is inaccesible via HTTP, but because of HSTS the following
283 // link should still continue to https://passwords.google.com.
285 GURL("https://accounts.google.com/ServiceLogin?continue="
286 "http://passwords.google.com/settings&rart=123"));
287 EXPECT_FALSE(client->IsPasswordManagerEnabledForCurrentPage());
289 // Specifying default port still passes.
291 GURL("https://accounts.google.com/ServiceLogin?continue="
292 "https://passwords.google.com:443/settings&rart=123"));
293 EXPECT_FALSE(client->IsPasswordManagerEnabledForCurrentPage());
295 // Encoded URL is considered the same.
297 GURL("https://accounts.google.com/ServiceLogin?continue="
298 "https://passwords.%67oogle.com/settings&rart=123"));
299 EXPECT_FALSE(client->IsPasswordManagerEnabledForCurrentPage());
301 // Make sure testing sites are disabled as well.
303 GURL("https://accounts.google.com/Login?continue="
304 "https://passwords-ac-testing.corp.google.com/settings&rart=456"));
305 EXPECT_FALSE(client->IsPasswordManagerEnabledForCurrentPage());
307 // Fully qualified domain name is considered a different hostname by GURL.
308 // Ideally this would not be the case, but this quirk can be avoided by
309 // verification on the server. This test is simply documentation of this
312 GURL("https://accounts.google.com/ServiceLogin?continue="
313 "https://passwords.google.com./settings&rart=123"));
314 EXPECT_TRUE(client->IsPasswordManagerEnabledForCurrentPage());
316 // Not a transactional reauth page.
318 GURL("https://accounts.google.com/ServiceLogin?continue="
319 "https://passwords.google.com/settings"));
320 EXPECT_TRUE(client->IsPasswordManagerEnabledForCurrentPage());
322 // Should be enabled for other transactional reauth pages.
324 GURL("https://accounts.google.com/ServiceLogin?continue="
325 "https://mail.google.com&rart=234"));
326 EXPECT_TRUE(client->IsPasswordManagerEnabledForCurrentPage());
328 // Reauth pages are only on accounts.google.com
330 GURL("https://other.site.com/ServiceLogin?continue="
331 "https://passwords.google.com&rart=234"));
332 EXPECT_TRUE(client->IsPasswordManagerEnabledForCurrentPage());
335 TEST_F(ChromePasswordManagerClientTest, CredentialManagerOnNotifyFailedSignIn) {
336 scoped_ptr<TestChromePasswordManagerClient> client(
337 new TestChromePasswordManagerClient(web_contents()));
339 password_manager::CredentialInfo info(base::ASCIIToUTF16("id"),
340 base::ASCIIToUTF16("name"),
341 GURL("https://example.com/image.png"));
342 client->OnNotifyFailedSignIn(kRequestId, info);
344 const uint32 kMsgID = CredentialManagerMsg_AcknowledgeFailedSignIn::ID;
345 const IPC::Message* message =
346 process()->sink().GetFirstMessageMatching(kMsgID);
347 EXPECT_TRUE(message);
348 process()->sink().ClearMessages();
351 TEST_F(ChromePasswordManagerClientTest, CredentialManagerOnNotifySignedIn) {
352 scoped_ptr<TestChromePasswordManagerClient> client(
353 new TestChromePasswordManagerClient(web_contents()));
355 password_manager::CredentialInfo info(base::ASCIIToUTF16("id"),
356 base::ASCIIToUTF16("name"),
357 GURL("https://example.com/image.png"));
358 client->OnNotifySignedIn(kRequestId, info);
360 const uint32 kMsgID = CredentialManagerMsg_AcknowledgeSignedIn::ID;
361 const IPC::Message* message =
362 process()->sink().GetFirstMessageMatching(kMsgID);
363 EXPECT_TRUE(message);
364 process()->sink().ClearMessages();
367 TEST_F(ChromePasswordManagerClientTest, CredentialManagerOnNotifySignedOut) {
368 scoped_ptr<TestChromePasswordManagerClient> client(
369 new TestChromePasswordManagerClient(web_contents()));
371 client->OnNotifySignedOut(kRequestId);
373 const uint32 kMsgID = CredentialManagerMsg_AcknowledgeSignedOut::ID;
374 const IPC::Message* message =
375 process()->sink().GetFirstMessageMatching(kMsgID);
376 EXPECT_TRUE(message);
377 process()->sink().ClearMessages();
380 TEST_F(ChromePasswordManagerClientTest, CredentialManagerOnRequestCredential) {
381 scoped_ptr<TestChromePasswordManagerClient> client(
382 new TestChromePasswordManagerClient(web_contents()));
384 std::vector<GURL> federations;
385 client->OnRequestCredential(kRequestId, false, federations);
387 const uint32 kMsgID = CredentialManagerMsg_SendCredential::ID;
388 const IPC::Message* message =
389 process()->sink().GetFirstMessageMatching(kMsgID);
390 EXPECT_TRUE(message);
391 process()->sink().ClearMessages();