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.
4 
5 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
6 
7 #include <stdint.h>
8 
9 #include <string>
10 #include <utility>
11 
12 #include "base/bind.h"
13 #include "base/command_line.h"
14 #include "base/macros.h"
15 #include "base/run_loop.h"
16 #include "base/strings/string16.h"
17 #include "base/strings/stringprintf.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/test/scoped_feature_list.h"
20 #include "build/build_config.h"
21 #include "chrome/browser/autofill/mock_address_accessory_controller.h"
22 #include "chrome/browser/autofill/mock_manual_filling_view.h"
23 #include "chrome/browser/autofill/mock_password_accessory_controller.h"
24 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
25 #include "chrome/browser/password_manager/password_store_factory.h"
26 #include "chrome/browser/safe_browsing/test_safe_browsing_service.h"
27 #include "chrome/browser/safe_browsing/user_interaction_observer.h"
28 #include "chrome/browser/sync/profile_sync_service_factory.h"
29 #include "chrome/test/base/chrome_render_view_host_test_harness.h"
30 #include "chrome/test/base/testing_profile.h"
31 #include "components/autofill/content/common/mojom/autofill_agent.mojom.h"
32 #include "components/autofill/core/browser/logging/log_manager.h"
33 #include "components/autofill/core/browser/logging/log_receiver.h"
34 #include "components/autofill/core/browser/logging/log_router.h"
35 #include "components/autofill/core/browser/test_autofill_client.h"
36 #include "components/autofill/core/common/autofill_features.h"
37 #include "components/favicon/core/test/mock_favicon_service.h"
38 #include "components/password_manager/content/browser/content_password_manager_driver.h"
39 #include "components/password_manager/content/browser/password_manager_log_router_factory.h"
40 #include "components/password_manager/core/browser/credential_cache.h"
41 #include "components/password_manager/core/browser/credentials_filter.h"
42 #include "components/password_manager/core/browser/mock_password_store.h"
43 #include "components/password_manager/core/browser/password_form.h"
44 #include "components/password_manager/core/browser/password_manager.h"
45 #include "components/password_manager/core/browser/password_manager_test_utils.h"
46 #include "components/password_manager/core/browser/stub_password_manager_client.h"
47 #include "components/password_manager/core/common/credential_manager_types.h"
48 #include "components/password_manager/core/common/password_manager_features.h"
49 #include "components/password_manager/core/common/password_manager_pref_names.h"
50 #include "components/prefs/pref_registry_simple.h"
51 #include "components/prefs/pref_service.h"
52 #include "components/prefs/testing_pref_service.h"
53 #include "components/safe_browsing/buildflags.h"
54 #include "components/safe_browsing/core/features.h"
55 #include "components/sessions/content/content_record_password_state.h"
56 #include "components/sync/driver/test_sync_service.h"
57 #include "components/sync_preferences/testing_pref_service_syncable.h"
58 #include "content/public/browser/browser_context.h"
59 #include "content/public/browser/navigation_entry.h"
60 #include "content/public/browser/web_contents.h"
61 #include "content/public/browser/web_contents_observer.h"
62 #include "content/public/common/content_switches.h"
63 #include "content/public/common/url_constants.h"
64 #include "content/public/test/mock_navigation_handle.h"
65 #include "content/public/test/navigation_simulator.h"
66 #include "content/public/test/web_contents_tester.h"
67 #include "mojo/public/cpp/bindings/associated_receiver.h"
68 #include "mojo/public/cpp/bindings/pending_associated_receiver.h"
69 #include "mojo/public/cpp/bindings/pending_receiver.h"
70 #include "services/service_manager/public/cpp/interface_provider.h"
71 #include "testing/gmock/include/gmock/gmock.h"
72 #include "testing/gtest/include/gtest/gtest.h"
73 #include "third_party/blink/public/common/associated_interfaces/associated_interface_provider.h"
74 #include "url/url_constants.h"
75 
76 #if BUILDFLAG(ENABLE_EXTENSIONS)
77 #include "extensions/common/constants.h"
78 #endif
79 
80 #if BUILDFLAG(FULL_SAFE_BROWSING)
81 #include "components/safe_browsing/content/password_protection/mock_password_protection_service.h"
82 #endif
83 
84 #if defined(OS_ANDROID)
85 #include "chrome/browser/autofill/manual_filling_controller_impl.h"
86 #include "chrome/browser/autofill/mock_address_accessory_controller.h"
87 #include "chrome/browser/autofill/mock_credit_card_accessory_controller.h"
88 #include "chrome/browser/autofill/mock_manual_filling_view.h"
89 #include "chrome/browser/password_manager/android/password_accessory_controller_impl.h"
90 #include "chrome/browser/password_manager/android/password_generation_controller.h"
91 #endif  // defined(OS_ANDROID)
92 
93 using autofill::mojom::FocusedFieldType;
94 using content::BrowserContext;
95 using content::WebContents;
96 using password_manager::PasswordForm;
97 using password_manager::PasswordManagerClient;
98 using sessions::GetPasswordStateFromNavigation;
99 using sessions::SerializedNavigationEntry;
100 using testing::_;
101 using testing::NiceMock;
102 using testing::Return;
103 using testing::StrictMock;
104 
105 #if defined(OS_ANDROID)
106 using password_manager::CredentialCache;
107 #endif
108 
109 namespace {
110 // TODO(crbug.com/474577): Get rid of the mocked client in the client's own
111 // test.
112 class MockChromePasswordManagerClient : public ChromePasswordManagerClient {
113  public:
114   MOCK_CONST_METHOD0(GetMainFrameCertStatus, net::CertStatus());
115 
MockChromePasswordManagerClient(content::WebContents * web_contents)116   explicit MockChromePasswordManagerClient(content::WebContents* web_contents)
117       : ChromePasswordManagerClient(web_contents, nullptr) {
118     ON_CALL(*this, GetMainFrameCertStatus()).WillByDefault(testing::Return(0));
119 #if BUILDFLAG(FULL_SAFE_BROWSING)
120     password_protection_service_ =
121         std::make_unique<safe_browsing::MockPasswordProtectionService>();
122 #endif
123   }
124 
125 #if BUILDFLAG(FULL_SAFE_BROWSING)
GetPasswordProtectionService() const126   safe_browsing::PasswordProtectionService* GetPasswordProtectionService()
127       const override {
128     return password_protection_service_.get();
129   }
130 
password_protection_service()131   safe_browsing::MockPasswordProtectionService* password_protection_service() {
132     return password_protection_service_.get();
133   }
134 #endif
135 
136  private:
137 #if BUILDFLAG(FULL_SAFE_BROWSING)
138   std::unique_ptr<safe_browsing::MockPasswordProtectionService>
139       password_protection_service_;
140 #endif
141   DISALLOW_COPY_AND_ASSIGN(MockChromePasswordManagerClient);
142 };
143 
144 class DummyLogReceiver : public autofill::LogReceiver {
145  public:
146   DummyLogReceiver() = default;
147 
LogEntry(const base::Value & entry)148   void LogEntry(const base::Value& entry) override {}
149 
150  private:
151   DISALLOW_COPY_AND_ASSIGN(DummyLogReceiver);
152 };
153 
154 class FakePasswordAutofillAgent
155     : public autofill::mojom::PasswordAutofillAgent {
156  public:
BindReceiver(mojo::ScopedInterfaceEndpointHandle handle)157   void BindReceiver(mojo::ScopedInterfaceEndpointHandle handle) {
158     receiver_.Bind(
159         mojo::PendingAssociatedReceiver<autofill::mojom::PasswordAutofillAgent>(
160             std::move(handle)));
161   }
162 
called_set_logging_state()163   bool called_set_logging_state() { return called_set_logging_state_; }
164 
logging_state_active()165   bool logging_state_active() { return logging_state_active_; }
166 
reset_data()167   void reset_data() {
168     called_set_logging_state_ = false;
169     logging_state_active_ = false;
170   }
171 
172  private:
173   // autofill::mojom::PasswordAutofillAgent:
FillPasswordForm(const autofill::PasswordFormFillData & form_data)174   void FillPasswordForm(
175       const autofill::PasswordFormFillData& form_data) override {}
176 
InformNoSavedCredentials(bool should_show_popup_without_passwords)177   void InformNoSavedCredentials(
178       bool should_show_popup_without_passwords) override {}
179 
FillIntoFocusedField(bool is_password,const base::string16 & credential)180   void FillIntoFocusedField(bool is_password,
181                             const base::string16& credential) override {}
AnnotateFieldsWithParsingResult(const autofill::ParsingResult & parsing_result)182   void AnnotateFieldsWithParsingResult(
183       const autofill::ParsingResult& parsing_result) override {}
184 
SetLoggingState(bool active)185   void SetLoggingState(bool active) override {
186     called_set_logging_state_ = true;
187     logging_state_active_ = active;
188   }
TouchToFillClosed(bool show_virtual_keyboard)189   void TouchToFillClosed(bool show_virtual_keyboard) override {}
190 
191   // Records whether SetLoggingState() gets called.
192   bool called_set_logging_state_ = false;
193   // Records data received via SetLoggingState() call.
194   bool logging_state_active_ = false;
195 
196   mojo::AssociatedReceiver<autofill::mojom::PasswordAutofillAgent> receiver_{
197       this};
198 };
199 
CreateTestSyncService(content::BrowserContext * context)200 std::unique_ptr<KeyedService> CreateTestSyncService(
201     content::BrowserContext* context) {
202   return std::make_unique<syncer::TestSyncService>();
203 }
204 
205 }  // namespace
206 
207 class ChromePasswordManagerClientTest : public ChromeRenderViewHostTestHarness {
208  public:
209   void SetUp() override;
210   void TearDown() override;
211 
prefs()212   sync_preferences::TestingPrefServiceSyncable* prefs() {
213     return profile()->GetTestingPrefService();
214   }
215 
216   // Caller does not own the returned pointer.
SetupBasicTestSync()217   syncer::TestSyncService* SetupBasicTestSync() {
218     syncer::TestSyncService* sync_service =
219         static_cast<syncer::TestSyncService*>(
220             ProfileSyncServiceFactory::GetInstance()->SetTestingFactoryAndUse(
221                 profile(), base::BindRepeating(&CreateTestSyncService)));
222     return sync_service;
223   }
224 
225   // Make a navigation entry that will accept an annotation.
SetupNavigationForAnnotation()226   void SetupNavigationForAnnotation() {
227     syncer::TestSyncService* sync_service = SetupBasicTestSync();
228     sync_service->SetIsUsingSecondaryPassphrase(false);
229     metrics_enabled_ = true;
230     NavigateAndCommit(GURL("about:blank"));
231   }
232 
233  protected:
234   ChromePasswordManagerClient* GetClient();
235 
236   // If autofill::mojom::PasswordAutofillAgent::SetLoggingState() got called,
237   // copies its argument into |activation_flag| and returns true. Otherwise
238   // returns false.
239   bool WasLoggingActivationMessageSent(bool* activation_flag);
240 
241   FakePasswordAutofillAgent fake_agent_;
242 
243   TestingPrefServiceSimple prefs_;
244   bool metrics_enabled_ = false;
245 
246   base::test::ScopedFeatureList scoped_feature_list_;
247 };
248 
SetUp()249 void ChromePasswordManagerClientTest::SetUp() {
250   ChromeRenderViewHostTestHarness::SetUp();
251 
252   blink::AssociatedInterfaceProvider* remote_interfaces =
253       web_contents()->GetMainFrame()->GetRemoteAssociatedInterfaces();
254   remote_interfaces->OverrideBinderForTesting(
255       autofill::mojom::PasswordAutofillAgent::Name_,
256       base::BindRepeating(&FakePasswordAutofillAgent::BindReceiver,
257                           base::Unretained(&fake_agent_)));
258 
259   prefs_.registry()->RegisterBooleanPref(
260       password_manager::prefs::kCredentialsEnableService, true);
261   ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
262       web_contents(), nullptr);
263 
264   // Connect our bool for testing.
265   ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting(
266       &metrics_enabled_);
267 
268   scoped_feature_list_.InitAndEnableFeature(safe_browsing::kDelayedWarnings);
269 }
270 
TearDown()271 void ChromePasswordManagerClientTest::TearDown() {
272   ChromeMetricsServiceAccessor::SetMetricsAndCrashReportingForTesting(nullptr);
273   ChromeRenderViewHostTestHarness::TearDown();
274 }
275 
GetClient()276 ChromePasswordManagerClient* ChromePasswordManagerClientTest::GetClient() {
277   return ChromePasswordManagerClient::FromWebContents(web_contents());
278 }
279 
WasLoggingActivationMessageSent(bool * activation_flag)280 bool ChromePasswordManagerClientTest::WasLoggingActivationMessageSent(
281     bool* activation_flag) {
282   base::RunLoop().RunUntilIdle();
283   if (!fake_agent_.called_set_logging_state())
284     return false;
285 
286   if (activation_flag)
287     *activation_flag = fake_agent_.logging_state_active();
288   fake_agent_.reset_data();
289   return true;
290 }
291 
TEST_F(ChromePasswordManagerClientTest,LogEntryNotifyRenderer)292 TEST_F(ChromePasswordManagerClientTest, LogEntryNotifyRenderer) {
293   bool logging_active = true;
294   // Ensure the existence of a driver, which will send the IPCs we listen for
295   // below.
296   NavigateAndCommit(GURL("about:blank"));
297 
298   // Initially, the logging should be off, so no IPC messages.
299   EXPECT_TRUE(!WasLoggingActivationMessageSent(&logging_active) ||
300               !logging_active)
301       << "logging_active=" << logging_active;
302 
303   DummyLogReceiver log_receiver;
304   autofill::LogRouter* log_router =
305       password_manager::PasswordManagerLogRouterFactory::GetForBrowserContext(
306           profile());
307   EXPECT_EQ(std::vector<base::Value>(),
308             log_router->RegisterReceiver(&log_receiver));
309   EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active));
310   EXPECT_TRUE(logging_active);
311 
312   log_router->UnregisterReceiver(&log_receiver);
313   EXPECT_TRUE(WasLoggingActivationMessageSent(&logging_active));
314   EXPECT_FALSE(logging_active);
315 }
316 
TEST_F(ChromePasswordManagerClientTest,GetPasswordSyncState)317 TEST_F(ChromePasswordManagerClientTest, GetPasswordSyncState) {
318   syncer::TestSyncService* sync_service = SetupBasicTestSync();
319 
320   sync_service->SetActiveDataTypes(syncer::ModelTypeSet(syncer::PASSWORDS));
321   sync_service->SetIsUsingSecondaryPassphrase(false);
322 
323   ChromePasswordManagerClient* client = GetClient();
324 
325   // Passwords are syncing and custom passphrase isn't used.
326   EXPECT_EQ(password_manager::SYNCING_NORMAL_ENCRYPTION,
327             client->GetPasswordSyncState());
328 
329   // Again, using a custom passphrase.
330   sync_service->SetIsUsingSecondaryPassphrase(true);
331 
332   EXPECT_EQ(password_manager::SYNCING_WITH_CUSTOM_PASSPHRASE,
333             client->GetPasswordSyncState());
334 
335   // Report correctly if we aren't syncing passwords.
336   sync_service->SetActiveDataTypes(syncer::ModelTypeSet(syncer::BOOKMARKS));
337 
338   EXPECT_EQ(password_manager::NOT_SYNCING, client->GetPasswordSyncState());
339 
340   // Again, without a custom passphrase.
341   sync_service->SetIsUsingSecondaryPassphrase(false);
342 
343   EXPECT_EQ(password_manager::NOT_SYNCING, client->GetPasswordSyncState());
344 }
345 
TEST_F(ChromePasswordManagerClientTest,SavingDependsOnManagerEnabledPreference)346 TEST_F(ChromePasswordManagerClientTest,
347        SavingDependsOnManagerEnabledPreference) {
348   // Test that saving passwords depends on the password manager enabled
349   // preference.
350   ChromePasswordManagerClient* client = GetClient();
351   prefs()->SetUserPref(password_manager::prefs::kCredentialsEnableService,
352                        std::make_unique<base::Value>(true));
353   const GURL kUrlOn("https://accounts.google.com");
354   EXPECT_TRUE(client->IsSavingAndFillingEnabled(kUrlOn));
355   prefs()->SetUserPref(password_manager::prefs::kCredentialsEnableService,
356                        std::make_unique<base::Value>(false));
357   EXPECT_FALSE(client->IsSavingAndFillingEnabled(kUrlOn));
358 }
359 
TEST_F(ChromePasswordManagerClientTest,SavingAndFillingEnabledConditionsTest)360 TEST_F(ChromePasswordManagerClientTest, SavingAndFillingEnabledConditionsTest) {
361   std::unique_ptr<WebContents> test_web_contents(
362       content::WebContentsTester::CreateTestWebContents(
363           web_contents()->GetBrowserContext(), nullptr));
364   std::unique_ptr<MockChromePasswordManagerClient> client(
365       new MockChromePasswordManagerClient(test_web_contents.get()));
366   // Functionality disabled if there is an SSL error.
367   EXPECT_CALL(*client, GetMainFrameCertStatus())
368       .WillRepeatedly(Return(net::CERT_STATUS_AUTHORITY_INVALID));
369   const GURL kUrlOn("https://accounts.google.com");
370   EXPECT_FALSE(client->IsSavingAndFillingEnabled(kUrlOn));
371   EXPECT_FALSE(client->IsFillingEnabled(kUrlOn));
372   EXPECT_FALSE(client->IsFillingFallbackEnabled(kUrlOn));
373 
374   // Functionality disabled if there are SSL errors and the manager itself is
375   // disabled.
376   prefs()->SetUserPref(password_manager::prefs::kCredentialsEnableService,
377                        std::make_unique<base::Value>(false));
378   EXPECT_FALSE(client->IsSavingAndFillingEnabled(kUrlOn));
379   EXPECT_FALSE(client->IsFillingEnabled(kUrlOn));
380   EXPECT_FALSE(client->IsFillingFallbackEnabled(kUrlOn));
381 
382   // Saving disabled if there are no SSL errors, but the manager itself is
383   // disabled.
384   EXPECT_CALL(*client, GetMainFrameCertStatus()).WillRepeatedly(Return(0));
385   prefs()->SetUserPref(password_manager::prefs::kCredentialsEnableService,
386                        std::make_unique<base::Value>(false));
387   EXPECT_FALSE(client->IsSavingAndFillingEnabled(kUrlOn));
388   EXPECT_TRUE(client->IsFillingEnabled(kUrlOn));
389   EXPECT_TRUE(client->IsFillingFallbackEnabled(kUrlOn));
390 
391   // Functionality enabled if there are no SSL errors and the manager is
392   // enabled.
393   EXPECT_CALL(*client, GetMainFrameCertStatus()).WillRepeatedly(Return(0));
394   prefs()->SetUserPref(password_manager::prefs::kCredentialsEnableService,
395                        std::make_unique<base::Value>(true));
396   EXPECT_TRUE(client->IsSavingAndFillingEnabled(kUrlOn));
397   EXPECT_TRUE(client->IsFillingEnabled(kUrlOn));
398   EXPECT_TRUE(client->IsFillingFallbackEnabled(kUrlOn));
399 }
400 
TEST_F(ChromePasswordManagerClientTest,SavingAndFillingDisabledConditionsInIncognito)401 TEST_F(ChromePasswordManagerClientTest,
402        SavingAndFillingDisabledConditionsInIncognito) {
403   std::unique_ptr<WebContents> incognito_web_contents(
404       content::WebContentsTester::CreateTestWebContents(
405           profile()->GetPrimaryOTRProfile(), nullptr));
406   std::unique_ptr<MockChromePasswordManagerClient> client(
407       new MockChromePasswordManagerClient(incognito_web_contents.get()));
408   EXPECT_CALL(*client, GetMainFrameCertStatus()).WillRepeatedly(Return(0));
409 
410   // Saving disabled in Incognito mode.
411   const GURL kUrlOn("https://accounts.google.com");
412   EXPECT_FALSE(client->IsSavingAndFillingEnabled(kUrlOn));
413   EXPECT_TRUE(client->IsFillingEnabled(kUrlOn));
414   EXPECT_TRUE(client->IsFillingFallbackEnabled(kUrlOn));
415 
416   // Saving disabled in Incognito mode also when manager itself is
417   // enabled.
418   prefs()->SetUserPref(password_manager::prefs::kCredentialsEnableService,
419                        std::make_unique<base::Value>(true));
420   EXPECT_FALSE(client->IsSavingAndFillingEnabled(kUrlOn));
421   EXPECT_TRUE(client->IsFillingEnabled(kUrlOn));
422   EXPECT_TRUE(client->IsFillingFallbackEnabled(kUrlOn));
423 
424   // In guest mode saving is disabled, filling is enabled but there is in fact
425   // nothing to fill, manual filling is disabled.
426   profile()->SetGuestSession(true);
427   profile()->GetPrimaryOTRProfile()->AsTestingProfile()->SetGuestSession(true);
428   EXPECT_FALSE(client->IsSavingAndFillingEnabled(kUrlOn));
429   EXPECT_TRUE(client->IsFillingEnabled(kUrlOn));
430   EXPECT_FALSE(client->IsFillingFallbackEnabled(kUrlOn));
431 }
432 
TEST_F(ChromePasswordManagerClientTest,SavingDependsOnAutomation)433 TEST_F(ChromePasswordManagerClientTest, SavingDependsOnAutomation) {
434   // Test that saving passwords UI is disabled for automated tests.
435   ChromePasswordManagerClient* client = GetClient();
436   const GURL kUrlOn("https://accounts.google.com");
437   EXPECT_TRUE(client->IsSavingAndFillingEnabled(kUrlOn));
438   base::CommandLine::ForCurrentProcess()->AppendSwitch(
439       switches::kEnableAutomation);
440   EXPECT_FALSE(client->IsSavingAndFillingEnabled(kUrlOn));
441 }
442 
443 // Check that password manager is disabled on about:blank pages.
444 // See https://crbug.com/756587.
TEST_F(ChromePasswordManagerClientTest,SavingAndFillingDisabledForAboutBlank)445 TEST_F(ChromePasswordManagerClientTest, SavingAndFillingDisabledForAboutBlank) {
446   const GURL kUrl(url::kAboutBlankURL);
447   NavigateAndCommit(kUrl);
448   EXPECT_TRUE(GetClient()->GetLastCommittedOrigin().opaque());
449   EXPECT_FALSE(GetClient()->IsSavingAndFillingEnabled(kUrl));
450   EXPECT_FALSE(GetClient()->IsFillingEnabled(kUrl));
451   EXPECT_FALSE(GetClient()->IsFillingFallbackEnabled(kUrl));
452 }
453 
TEST_F(ChromePasswordManagerClientTest,IsFillingAndSavingOnGooglePasswordPage)454 TEST_F(ChromePasswordManagerClientTest,
455        IsFillingAndSavingOnGooglePasswordPage) {
456   PasswordManagerClient* client = GetClient();
457   EXPECT_FALSE(client->IsSavingAndFillingEnabled(
458       GURL("https://passwords.google.com/path?query=1")));
459   EXPECT_FALSE(client->IsFillingEnabled(
460       GURL("https://passwords.google.com/path?query=1")));
461 }
462 
463 namespace {
464 
465 struct SchemeTestCase {
466   const char* scheme;
467   bool password_manager_works;
468 };
469 const SchemeTestCase kTestCases[] = {
470     {url::kHttpScheme, true},
471     {url::kHttpsScheme, true},
472     {url::kFtpScheme, true},
473     {url::kDataScheme, true},
474     {"feed", true},
475 
476     {"invalid-scheme-i-just-made-up", false},
477     {content::kChromeDevToolsScheme, false},
478     {content::kChromeUIScheme, false},
479     {url::kMailToScheme, false},
480 };
481 
482 // Parameterized test that takes a URL scheme as a parameter. Every scheme
483 // requires a separate test because NavigateAndCommit can be called only once.
484 class ChromePasswordManagerClientSchemeTest
485     : public ChromePasswordManagerClientTest,
486       public ::testing::WithParamInterface<const char*> {
487  public:
GetSchemes()488   static std::vector<const char*> GetSchemes() {
489     std::vector<const char*> result;
490     for (const SchemeTestCase& test_case : kTestCases) {
491       result.push_back(test_case.scheme);
492     }
493     return result;
494   }
495 };
496 
TEST_P(ChromePasswordManagerClientSchemeTest,SavingAndFillingOnDifferentSchemes)497 TEST_P(ChromePasswordManagerClientSchemeTest,
498        SavingAndFillingOnDifferentSchemes) {
499   const GURL url(base::StringPrintf("%s://example.org", GetParam()));
500   VLOG(0) << url.possibly_invalid_spec();
501   NavigateAndCommit(url);
502   EXPECT_EQ(url::Origin::Create(url).GetURL(),
503             GetClient()->GetLastCommittedOrigin().GetURL());
504 
505   auto* it = std::find_if(
506       std::begin(kTestCases), std::end(kTestCases),
507       [](auto test_case) { return strcmp(test_case.scheme, GetParam()) == 0; });
508   ASSERT_FALSE(it == std::end(kTestCases));
509   EXPECT_EQ(it->password_manager_works,
510             GetClient()->IsSavingAndFillingEnabled(url));
511   EXPECT_EQ(it->password_manager_works, GetClient()->IsFillingEnabled(url));
512   EXPECT_EQ(it->password_manager_works,
513             GetClient()->IsFillingFallbackEnabled(url));
514 }
515 
516 INSTANTIATE_TEST_SUITE_P(
517     All,
518     ChromePasswordManagerClientSchemeTest,
519     ::testing::ValuesIn(ChromePasswordManagerClientSchemeTest::GetSchemes()));
520 
521 }  // namespace
522 
TEST_F(ChromePasswordManagerClientTest,GetLastCommittedEntryURL_Empty)523 TEST_F(ChromePasswordManagerClientTest, GetLastCommittedEntryURL_Empty) {
524   EXPECT_TRUE(GetClient()->GetLastCommittedOrigin().opaque());
525 }
526 
TEST_F(ChromePasswordManagerClientTest,GetLastCommittedEntryURL)527 TEST_F(ChromePasswordManagerClientTest, GetLastCommittedEntryURL) {
528   GURL kUrl(
529       "https://accounts.google.com/ServiceLogin?continue="
530       "https://passwords.google.com/settings");
531   NavigateAndCommit(kUrl);
532   EXPECT_EQ(url::Origin::Create(kUrl), GetClient()->GetLastCommittedOrigin());
533 }
534 
TEST_F(ChromePasswordManagerClientTest,WebUINoLogging)535 TEST_F(ChromePasswordManagerClientTest, WebUINoLogging) {
536   // Make sure that logging is active.
537   autofill::LogRouter* log_router =
538       password_manager::PasswordManagerLogRouterFactory::GetForBrowserContext(
539           profile());
540   DummyLogReceiver log_receiver;
541   EXPECT_EQ(std::vector<base::Value>(),
542             log_router->RegisterReceiver(&log_receiver));
543 
544   // But then navigate to a WebUI, there the logging should not be active.
545   NavigateAndCommit(GURL("chrome://password-manager-internals/"));
546   EXPECT_FALSE(GetClient()->GetLogManager()->IsLoggingActive());
547 
548   log_router->UnregisterReceiver(&log_receiver);
549 }
550 
551 // Metrics enabled, syncing with non-custom passphrase: Do not annotate.
TEST_F(ChromePasswordManagerClientTest,AnnotateNavigationEntryWithMetricsNoCustom)552 TEST_F(ChromePasswordManagerClientTest,
553        AnnotateNavigationEntryWithMetricsNoCustom) {
554   syncer::TestSyncService* sync_service = SetupBasicTestSync();
555   sync_service->SetIsUsingSecondaryPassphrase(false);
556   metrics_enabled_ = true;
557 
558   NavigateAndCommit(GURL("about:blank"));
559   GetClient()->AnnotateNavigationEntry(true);
560 
561   EXPECT_EQ(
562       SerializedNavigationEntry::HAS_PASSWORD_FIELD,
563       GetPasswordStateFromNavigation(controller().GetLastCommittedEntry()));
564 }
565 
566 // Metrics disabled, syncing with non-custom passphrase: Do not annotate.
TEST_F(ChromePasswordManagerClientTest,AnnotateNavigationEntryNoMetricsNoCustom)567 TEST_F(ChromePasswordManagerClientTest,
568        AnnotateNavigationEntryNoMetricsNoCustom) {
569   syncer::TestSyncService* sync_service = SetupBasicTestSync();
570   sync_service->SetIsUsingSecondaryPassphrase(false);
571   metrics_enabled_ = false;
572 
573   NavigateAndCommit(GURL("about:blank"));
574   GetClient()->AnnotateNavigationEntry(true);
575 
576   EXPECT_EQ(
577       SerializedNavigationEntry::PASSWORD_STATE_UNKNOWN,
578       GetPasswordStateFromNavigation(controller().GetLastCommittedEntry()));
579 }
580 
581 // Metrics enabled, syncing with custom passphrase: Do not annotate.
TEST_F(ChromePasswordManagerClientTest,AnnotateNavigationEntryWithMetricsWithCustom)582 TEST_F(ChromePasswordManagerClientTest,
583        AnnotateNavigationEntryWithMetricsWithCustom) {
584   syncer::TestSyncService* sync_service = SetupBasicTestSync();
585   sync_service->SetIsUsingSecondaryPassphrase(true);
586   metrics_enabled_ = true;
587 
588   NavigateAndCommit(GURL("about:blank"));
589   GetClient()->AnnotateNavigationEntry(true);
590 
591   EXPECT_EQ(
592       SerializedNavigationEntry::PASSWORD_STATE_UNKNOWN,
593       GetPasswordStateFromNavigation(controller().GetLastCommittedEntry()));
594 }
595 
596 // Metrics disabled, syncing with custom passphrase: Do not annotate.
TEST_F(ChromePasswordManagerClientTest,AnnotateNavigationEntryNoMetricsWithCustom)597 TEST_F(ChromePasswordManagerClientTest,
598        AnnotateNavigationEntryNoMetricsWithCustom) {
599   syncer::TestSyncService* sync_service = SetupBasicTestSync();
600   sync_service->SetIsUsingSecondaryPassphrase(true);
601   metrics_enabled_ = false;
602 
603   NavigateAndCommit(GURL("about:blank"));
604   GetClient()->AnnotateNavigationEntry(true);
605 
606   EXPECT_EQ(
607       SerializedNavigationEntry::PASSWORD_STATE_UNKNOWN,
608       GetPasswordStateFromNavigation(controller().GetLastCommittedEntry()));
609 }
610 
611 // State transition: Unannotated
TEST_F(ChromePasswordManagerClientTest,AnnotateNavigationEntryUnannotated)612 TEST_F(ChromePasswordManagerClientTest, AnnotateNavigationEntryUnannotated) {
613   SetupNavigationForAnnotation();
614 
615   EXPECT_EQ(
616       SerializedNavigationEntry::PASSWORD_STATE_UNKNOWN,
617       GetPasswordStateFromNavigation(controller().GetLastCommittedEntry()));
618 }
619 
620 // State transition: unknown->false
TEST_F(ChromePasswordManagerClientTest,AnnotateNavigationEntryToFalse)621 TEST_F(ChromePasswordManagerClientTest, AnnotateNavigationEntryToFalse) {
622   SetupNavigationForAnnotation();
623 
624   GetClient()->AnnotateNavigationEntry(false);
625   EXPECT_EQ(
626       SerializedNavigationEntry::NO_PASSWORD_FIELD,
627       GetPasswordStateFromNavigation(controller().GetLastCommittedEntry()));
628 }
629 
630 // State transition: false->true
TEST_F(ChromePasswordManagerClientTest,AnnotateNavigationEntryToTrue)631 TEST_F(ChromePasswordManagerClientTest, AnnotateNavigationEntryToTrue) {
632   SetupNavigationForAnnotation();
633 
634   GetClient()->AnnotateNavigationEntry(false);
635   GetClient()->AnnotateNavigationEntry(true);
636   EXPECT_EQ(
637       SerializedNavigationEntry::HAS_PASSWORD_FIELD,
638       GetPasswordStateFromNavigation(controller().GetLastCommittedEntry()));
639 }
640 
641 // State transition: true->false (retains true)
TEST_F(ChromePasswordManagerClientTest,AnnotateNavigationEntryTrueToFalse)642 TEST_F(ChromePasswordManagerClientTest, AnnotateNavigationEntryTrueToFalse) {
643   SetupNavigationForAnnotation();
644 
645   GetClient()->AnnotateNavigationEntry(true);
646   GetClient()->AnnotateNavigationEntry(false);
647   EXPECT_EQ(
648       SerializedNavigationEntry::HAS_PASSWORD_FIELD,
649       GetPasswordStateFromNavigation(controller().GetLastCommittedEntry()));
650 }
651 
652 // Handle missing ChromePasswordManagerClient instance in BindCredentialManager
653 // gracefully.
TEST_F(ChromePasswordManagerClientTest,BindCredentialManager_MissingInstance)654 TEST_F(ChromePasswordManagerClientTest, BindCredentialManager_MissingInstance) {
655   // Create a WebContent without tab helpers.
656   std::unique_ptr<content::WebContents> web_contents =
657       content::WebContents::Create(
658           content::WebContents::CreateParams(profile()));
659   // In particular, this WebContent should not have the
660   // ChromePasswordManagerClient.
661   ASSERT_FALSE(
662       ChromePasswordManagerClient::FromWebContents(web_contents.get()));
663 
664   // This call should not crash.
665   ChromePasswordManagerClient::BindCredentialManager(
666       web_contents->GetMainFrame(), mojo::NullReceiver());
667 }
668 
TEST_F(ChromePasswordManagerClientTest,CanShowBubbleOnURL)669 TEST_F(ChromePasswordManagerClientTest, CanShowBubbleOnURL) {
670   struct TestCase {
671     const char* scheme;
672     bool can_show_bubble;
673   } kTestCases[] = {
674     {url::kHttpScheme, true},
675     {url::kHttpsScheme, true},
676     {url::kFtpScheme, true},
677     {url::kDataScheme, true},
678     {"feed", true},
679     {url::kBlobScheme, true},
680     {url::kFileSystemScheme, true},
681 
682     {"invalid-scheme-i-just-made-up", false},
683 #if BUILDFLAG(ENABLE_EXTENSIONS)
684     {extensions::kExtensionScheme, false},
685 #endif
686     {url::kAboutScheme, false},
687     {content::kChromeDevToolsScheme, false},
688     {content::kChromeUIScheme, false},
689     {url::kJavaScriptScheme, false},
690     {url::kMailToScheme, false},
691     {content::kViewSourceScheme, false},
692   };
693 
694   for (const TestCase& test_case : kTestCases) {
695     // CanShowBubbleOnURL currently only depends on the scheme.
696     GURL url(base::StringPrintf("%s://example.org", test_case.scheme));
697     SCOPED_TRACE(url.possibly_invalid_spec());
698     EXPECT_EQ(test_case.can_show_bubble,
699               ChromePasswordManagerClient::CanShowBubbleOnURL(url));
700   }
701 }
702 
703 #if BUILDFLAG(FULL_SAFE_BROWSING)
TEST_F(ChromePasswordManagerClientTest,VerifyMaybeStartPasswordFieldOnFocusRequestCalled)704 TEST_F(ChromePasswordManagerClientTest,
705        VerifyMaybeStartPasswordFieldOnFocusRequestCalled) {
706   std::unique_ptr<WebContents> test_web_contents(
707       content::WebContentsTester::CreateTestWebContents(
708           web_contents()->GetBrowserContext(), nullptr));
709   std::unique_ptr<MockChromePasswordManagerClient> client(
710       new MockChromePasswordManagerClient(test_web_contents.get()));
711   EXPECT_CALL(*client->password_protection_service(),
712               MaybeStartPasswordFieldOnFocusRequest(_, _, _, _, _))
713       .Times(1);
714   PasswordManagerClient* mojom_client = client.get();
715   mojom_client->CheckSafeBrowsingReputation(GURL("http://foo.com/submit"),
716                                             GURL("http://foo.com/iframe.html"));
717 }
718 
719 // SafeBrowsing Delayed Warnings experiment can delay certain SafeBrowsing
720 // warnings until user interaction. This test checks that when a SafeBrowsing
721 // warning is delayed, password saving and filling is disabled on the page.
TEST_F(ChromePasswordManagerClientTest,SavingAndFillingDisabledConditionsDelayedWarnings)722 TEST_F(ChromePasswordManagerClientTest,
723        SavingAndFillingDisabledConditionsDelayedWarnings) {
724   std::unique_ptr<WebContents> test_web_contents(
725       content::WebContentsTester::CreateTestWebContents(
726           web_contents()->GetBrowserContext(), nullptr));
727 
728   // Warnings are delayed until the user interacts with the page. This is
729   // achieved by attaching an observer (SafeBrowsingUserInteractionObserver) to
730   // the current WebContents. Create an observer and attach it to simulate a
731   // delayed warning.
732   auto safe_browsing_service =
733       base::MakeRefCounted<safe_browsing::TestSafeBrowsingService>();
734   auto ui_manager =
735       base::MakeRefCounted<safe_browsing::TestSafeBrowsingUIManager>(
736           safe_browsing_service);
737   security_interstitials::UnsafeResource resource;
738   safe_browsing::SafeBrowsingUserInteractionObserver::CreateForWebContents(
739       test_web_contents.get(), resource, /* is_main_frame= */ true, ui_manager);
740 
741   auto client = std::make_unique<MockChromePasswordManagerClient>(
742       test_web_contents.get());
743   // Saving is disabled when the page has a delayed SafeBrowsing warning.
744   const GURL kUrlOn("https://accounts.google.com");
745   EXPECT_FALSE(client->IsSavingAndFillingEnabled(kUrlOn));
746   EXPECT_FALSE(client->IsFillingEnabled(kUrlOn));
747   EXPECT_FALSE(client->IsFillingFallbackEnabled(kUrlOn));
748 }
749 
TEST_F(ChromePasswordManagerClientTest,VerifyMaybeProtectedPasswordEntryRequestCalled)750 TEST_F(ChromePasswordManagerClientTest,
751        VerifyMaybeProtectedPasswordEntryRequestCalled) {
752   std::unique_ptr<WebContents> test_web_contents(
753       content::WebContentsTester::CreateTestWebContents(
754           web_contents()->GetBrowserContext(), nullptr));
755   std::unique_ptr<MockChromePasswordManagerClient> client(
756       new MockChromePasswordManagerClient(test_web_contents.get()));
757 
758   EXPECT_CALL(
759       *client->password_protection_service(),
760       MaybeStartProtectedPasswordEntryRequest(_, _, "username", _, _, true))
761       .Times(4);
762   std::vector<password_manager::MatchingReusedCredential> credentials = {
763       {"saved_domain.com", base::ASCIIToUTF16("username")}};
764 
765   client->CheckProtectedPasswordEntry(
766       password_manager::metrics_util::PasswordType::SAVED_PASSWORD, "username",
767       credentials, true);
768   client->CheckProtectedPasswordEntry(
769       password_manager::metrics_util::PasswordType::PRIMARY_ACCOUNT_PASSWORD,
770       "username", credentials, true);
771   client->CheckProtectedPasswordEntry(
772       password_manager::metrics_util::PasswordType::OTHER_GAIA_PASSWORD,
773       "username", credentials, true);
774   client->CheckProtectedPasswordEntry(
775       password_manager::metrics_util::PasswordType::ENTERPRISE_PASSWORD,
776       "username", credentials, true);
777 }
778 
TEST_F(ChromePasswordManagerClientTest,VerifyLogPasswordReuseDetectedEvent)779 TEST_F(ChromePasswordManagerClientTest, VerifyLogPasswordReuseDetectedEvent) {
780   std::unique_ptr<WebContents> test_web_contents(
781       content::WebContentsTester::CreateTestWebContents(
782           web_contents()->GetBrowserContext(), nullptr));
783   std::unique_ptr<MockChromePasswordManagerClient> client(
784       new MockChromePasswordManagerClient(test_web_contents.get()));
785   EXPECT_CALL(*client->password_protection_service(),
786               MaybeLogPasswordReuseDetectedEvent(test_web_contents.get()))
787       .Times(1);
788   client->LogPasswordReuseDetectedEvent();
789 }
790 #endif
791 
TEST_F(ChromePasswordManagerClientTest,MissingUIDelegate)792 TEST_F(ChromePasswordManagerClientTest, MissingUIDelegate) {
793   // Checks that the saving fallback methods don't crash if there is no UI
794   // delegate. It can happen on ChromeOS login form, for example.
795   GURL kUrl("https://example.com/");
796   NavigateAndCommit(kUrl);
797   PasswordManagerClient* client = GetClient();
798   client->ShowManualFallbackForSaving(nullptr, false, false);
799   client->HideManualFallbackForSaving();
800 }
801 
802 #if defined(OS_ANDROID)
803 class ChromePasswordManagerClientAndroidTest
804     : public ChromePasswordManagerClientTest {
805  protected:
806   std::unique_ptr<password_manager::ContentPasswordManagerDriver>
807   CreateContentPasswordManagerDriver(content::RenderFrameHost* rfh);
808 
809   void SetUp() override;
810 
811   void CreateManualFillingController(content::WebContents* web_contents);
812 
controller()813   ManualFillingControllerImpl* controller() {
814     return ManualFillingControllerImpl::FromWebContents(web_contents());
815   }
816 
view()817   MockManualFillingView* view() {
818     return static_cast<MockManualFillingView*>(controller()->view());
819   }
820 
821  private:
822   autofill::TestAutofillClient test_autofill_client_;
823   NiceMock<MockPasswordAccessoryController> mock_pwd_controller_;
824   NiceMock<MockAddressAccessoryController> mock_address_controller_;
825   NiceMock<MockCreditCardAccessoryController> mock_cc_controller_;
826 };
827 
SetUp()828 void ChromePasswordManagerClientAndroidTest::SetUp() {
829   ChromePasswordManagerClientTest::SetUp();
830   PasswordStoreFactory::GetInstance()->SetTestingFactory(
831       GetBrowserContext(),
832       base::BindRepeating(
833           &password_manager::BuildPasswordStore<
834               content::BrowserContext, password_manager::MockPasswordStore>));
835 }
836 
837 std::unique_ptr<password_manager::ContentPasswordManagerDriver>
CreateContentPasswordManagerDriver(content::RenderFrameHost * rfh)838 ChromePasswordManagerClientAndroidTest::CreateContentPasswordManagerDriver(
839     content::RenderFrameHost* rfh) {
840   return std::make_unique<password_manager::ContentPasswordManagerDriver>(
841       rfh, GetClient(), &test_autofill_client_);
842 }
843 
CreateManualFillingController(content::WebContents * web_contents)844 void ChromePasswordManagerClientAndroidTest::CreateManualFillingController(
845     content::WebContents* web_contents) {
846   ManualFillingControllerImpl::CreateForWebContentsForTesting(
847       web_contents, mock_pwd_controller_.AsWeakPtr(),
848       mock_address_controller_.AsWeakPtr(), mock_cc_controller_.AsWeakPtr(),
849       std::make_unique<NiceMock<MockManualFillingView>>());
850 }
851 
TEST_F(ChromePasswordManagerClientAndroidTest,FocusedInputChangedNoFrameFillableField)852 TEST_F(ChromePasswordManagerClientAndroidTest,
853        FocusedInputChangedNoFrameFillableField) {
854   CreateManualFillingController(web_contents());
855   ASSERT_FALSE(web_contents()->GetFocusedFrame());
856 
857   ChromePasswordManagerClient* client = GetClient();
858 
859   std::unique_ptr<password_manager::ContentPasswordManagerDriver> driver =
860       CreateContentPasswordManagerDriver(main_rfh());
861   client->FocusedInputChanged(driver.get(),
862                               FocusedFieldType::kFillablePasswordField);
863 
864   PasswordGenerationController* pwd_generation_controller =
865       PasswordGenerationController::GetIfExisting(web_contents());
866   EXPECT_FALSE(pwd_generation_controller);
867 }
868 
TEST_F(ChromePasswordManagerClientAndroidTest,FocusedInputChangedNoFrameNoField)869 TEST_F(ChromePasswordManagerClientAndroidTest,
870        FocusedInputChangedNoFrameNoField) {
871   CreateManualFillingController(web_contents());
872   std::unique_ptr<password_manager::ContentPasswordManagerDriver> driver =
873       CreateContentPasswordManagerDriver(main_rfh());
874 
875   // Simulate that an element was focused before as far as the generation
876   // controller is concerned.
877   PasswordGenerationController* pwd_generation_controller =
878       PasswordGenerationController::GetOrCreate(web_contents());
879   pwd_generation_controller->FocusedInputChanged(
880       FocusedFieldType::kFillablePasswordField, driver.get()->AsWeakPtr());
881 
882   ChromePasswordManagerClient* client = GetClient();
883 
884   ASSERT_FALSE(web_contents()->GetFocusedFrame());
885   ASSERT_TRUE(pwd_generation_controller->GetActiveFrameDriver());
886   client->FocusedInputChanged(driver.get(), FocusedFieldType::kUnknown);
887 
888   // Check that the event was processed by the generation controller and that
889   // the active frame driver was unset.
890   EXPECT_FALSE(pwd_generation_controller->GetActiveFrameDriver());
891 }
892 
TEST_F(ChromePasswordManagerClientAndroidTest,FocusedInputChangedWrongFrame)893 TEST_F(ChromePasswordManagerClientAndroidTest, FocusedInputChangedWrongFrame) {
894   ChromePasswordManagerClient* client = GetClient();
895 
896   // Set up the main frame.
897   NavigateAndCommit(GURL("https://example.com"));
898   FocusWebContentsOnMainFrame();
899   CreateManualFillingController(web_contents());
900 
901   content::RenderFrameHost* subframe =
902       content::RenderFrameHostTester::For(main_rfh())->AppendChild("subframe");
903   std::unique_ptr<password_manager::ContentPasswordManagerDriver> driver =
904       CreateContentPasswordManagerDriver(subframe);
905   client->FocusedInputChanged(driver.get(),
906                               FocusedFieldType::kFillablePasswordField);
907 
908   PasswordGenerationController* pwd_generation_controller =
909       PasswordGenerationController::GetIfExisting(web_contents());
910 
911   // Check that no generation controller was created, since this event should be
912   // rejected and not passed on to a generation controller.
913   EXPECT_FALSE(pwd_generation_controller);
914 }
915 
TEST_F(ChromePasswordManagerClientAndroidTest,FocusedInputChangedGoodFrame)916 TEST_F(ChromePasswordManagerClientAndroidTest, FocusedInputChangedGoodFrame) {
917   ChromePasswordManagerClient* client = GetClient();
918   CreateManualFillingController(web_contents());
919 
920   std::unique_ptr<password_manager::ContentPasswordManagerDriver> driver =
921       CreateContentPasswordManagerDriver(main_rfh());
922   FocusWebContentsOnMainFrame();
923   client->FocusedInputChanged(driver.get(),
924                               FocusedFieldType::kFillablePasswordField);
925 
926   PasswordGenerationController* pwd_generation_controller =
927       PasswordGenerationController::GetIfExisting(web_contents());
928   EXPECT_TRUE(pwd_generation_controller);
929 }
930 
TEST_F(ChromePasswordManagerClientAndroidTest,SameDocumentNavigationDoesNotClearCache)931 TEST_F(ChromePasswordManagerClientAndroidTest,
932        SameDocumentNavigationDoesNotClearCache) {
933   auto origin = url::Origin::Create(GURL("https://example.com"));
934   PasswordForm form;
935   form.url = origin.GetURL();
936   form.username_value = base::ASCIIToUTF16("alice");
937   form.password_value = base::ASCIIToUTF16("S3cr3t");
938   GetClient()
939       ->GetCredentialCacheForTesting()
940       ->SaveCredentialsAndBlacklistedForOrigin(
941           {&form}, CredentialCache::IsOriginBlacklisted(false), origin);
942 
943   // Check that a navigation within the same document does not clear the cache.
944   content::MockNavigationHandle handle(web_contents());
945   handle.set_is_same_document(true);
946   handle.set_has_committed(true);
947   static_cast<content::WebContentsObserver*>(GetClient())
948       ->DidFinishNavigation(&handle);
949 
950   EXPECT_FALSE(GetClient()
951                    ->GetCredentialCacheForTesting()
952                    ->GetCredentialStore(origin)
953                    .GetCredentials()
954                    .empty());
955 
956   // Check that a navigation to a different origin clears the cache.
957   NavigateAndCommit(GURL("https://example.org"));
958   EXPECT_TRUE(GetClient()
959                   ->GetCredentialCacheForTesting()
960                   ->GetCredentialStore(origin)
961                   .GetCredentials()
962                   .empty());
963 }
964 
TEST_F(ChromePasswordManagerClientAndroidTest,HideFillingUIOnNavigatingAway)965 TEST_F(ChromePasswordManagerClientAndroidTest, HideFillingUIOnNavigatingAway) {
966   CreateManualFillingController(web_contents());
967   // Navigate to a URL with a bubble/popup.
968   GURL kUrl1("https://example.com/");
969   NavigateAndCommit(kUrl1);
970   EXPECT_TRUE(ChromePasswordManagerClient::CanShowBubbleOnURL(kUrl1));
971 
972   // Navigating away should call Hide.
973   EXPECT_CALL(*view(), Hide());
974   GURL kUrl2("https://accounts.google.com");
975   NavigateAndCommit(kUrl2);
976 }
977 #endif  //  defined(OS_ANDROID)
978