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 <memory>
8 
9 #include <string>
10 #include <utility>
11 
12 #include "base/bind.h"
13 #include "base/callback_helpers.h"
14 #include "base/command_line.h"
15 #include "base/memory/ptr_util.h"
16 #include "base/memory/ref_counted.h"
17 #include "base/memory/singleton.h"
18 #include "base/metrics/field_trial.h"
19 #include "base/metrics/histogram_functions.h"
20 #include "base/metrics/histogram_macros.h"
21 #include "base/no_destructor.h"
22 #include "build/branding_buildflags.h"
23 #include "build/build_config.h"
24 #include "build/buildflag.h"
25 #include "chrome/browser/browser_process.h"
26 #include "chrome/browser/engagement/site_engagement_service.h"
27 #include "chrome/browser/favicon/favicon_service_factory.h"
28 #include "chrome/browser/metrics/chrome_metrics_service_accessor.h"
29 #include "chrome/browser/password_manager/account_password_store_factory.h"
30 #include "chrome/browser/password_manager/chrome_biometric_authenticator.h"
31 #include "chrome/browser/password_manager/field_info_manager_factory.h"
32 #include "chrome/browser/password_manager/password_store_factory.h"
33 #include "chrome/browser/profiles/profile.h"
34 #include "chrome/browser/safe_browsing/chrome_password_protection_service.h"
35 #include "chrome/browser/safe_browsing/user_interaction_observer.h"
36 #include "chrome/browser/signin/identity_manager_factory.h"
37 #include "chrome/browser/sync/profile_sync_service_factory.h"
38 #include "chrome/browser/translate/chrome_translate_client.h"
39 #include "chrome/browser/ui/passwords/manage_passwords_view_utils.h"
40 #include "chrome/browser/ui/passwords/password_generation_popup_controller_impl.h"
41 #include "chrome/browser/ui/passwords/passwords_client_ui_delegate.h"
42 #include "chrome/browser/vr/vr_tab_helper.h"
43 #include "chrome/common/channel_info.h"
44 #include "chrome/common/url_constants.h"
45 #include "components/autofill/content/browser/content_autofill_driver.h"
46 #include "components/autofill/content/browser/content_autofill_driver_factory.h"
47 #include "components/autofill/core/browser/logging/log_manager.h"
48 #include "components/autofill/core/browser/logging/log_receiver.h"
49 #include "components/autofill/core/common/password_generation_util.h"
50 #include "components/autofill_assistant/browser/public/runtime_manager.h"
51 #include "components/browsing_data/content/browsing_data_helper.h"
52 #include "components/no_state_prefetch/browser/prerender_contents.h"
53 #include "components/password_manager/content/browser/bad_message.h"
54 #include "components/password_manager/content/browser/content_password_manager_driver.h"
55 #include "components/password_manager/content/browser/password_manager_log_router_factory.h"
56 #include "components/password_manager/content/browser/password_requirements_service_factory.h"
57 #include "components/password_manager/core/browser/browser_save_password_progress_logger.h"
58 #include "components/password_manager/core/browser/field_info_manager.h"
59 #include "components/password_manager/core/browser/hsts_query.h"
60 #include "components/password_manager/core/browser/http_auth_manager.h"
61 #include "components/password_manager/core/browser/http_auth_manager_impl.h"
62 #include "components/password_manager/core/browser/password_form.h"
63 #include "components/password_manager/core/browser/password_form_manager_for_ui.h"
64 #include "components/password_manager/core/browser/password_manager_constants.h"
65 #include "components/password_manager/core/browser/password_manager_metrics_util.h"
66 #include "components/password_manager/core/browser/password_manager_util.h"
67 #include "components/password_manager/core/browser/password_requirements_service.h"
68 #include "components/password_manager/core/browser/password_scripts_fetcher.h"
69 #include "components/password_manager/core/browser/store_metrics_reporter.h"
70 #include "components/password_manager/core/common/credential_manager_types.h"
71 #include "components/password_manager/core/common/password_manager_features.h"
72 #include "components/password_manager/core/common/password_manager_pref_names.h"
73 #include "components/prefs/pref_service.h"
74 #include "components/safe_browsing/buildflags.h"
75 #include "components/sessions/content/content_record_password_state.h"
76 #include "components/signin/public/base/signin_metrics.h"
77 #include "components/signin/public/identity_manager/identity_manager.h"
78 #include "components/site_isolation/site_isolation_policy.h"
79 #include "components/sync/driver/sync_service.h"
80 #include "components/sync/driver/sync_user_settings.h"
81 #include "components/translate/core/browser/translate_manager.h"
82 #include "components/ukm/content/source_url_recorder.h"
83 #include "components/version_info/version_info.h"
84 #include "content/public/browser/back_forward_cache.h"
85 #include "content/public/browser/browser_context.h"
86 #include "content/public/browser/child_process_security_policy.h"
87 #include "content/public/browser/navigation_entry.h"
88 #include "content/public/browser/navigation_handle.h"
89 #include "content/public/browser/render_frame_host.h"
90 #include "content/public/browser/render_view_host.h"
91 #include "content/public/browser/render_widget_host_view.h"
92 #include "content/public/browser/ssl_status.h"
93 #include "content/public/browser/storage_partition.h"
94 #include "content/public/browser/web_contents.h"
95 #include "content/public/common/content_switches.h"
96 #include "content/public/common/origin_util.h"
97 #include "extensions/buildflags/buildflags.h"
98 #include "google_apis/gaia/gaia_urls.h"
99 #include "net/base/url_util.h"
100 #include "net/cert/cert_status_flags.h"
101 #include "services/metrics/public/cpp/ukm_recorder.h"
102 #if defined(OS_BSD)
103 #include <re2/re2.h>
104 #else
105 #include "third_party/re2/src/re2/re2.h"
106 #endif
107 #include "url/url_constants.h"
108 
109 #if BUILDFLAG(FULL_SAFE_BROWSING)
110 #include "chrome/browser/safe_browsing/advanced_protection_status_manager.h"
111 #include "chrome/browser/safe_browsing/advanced_protection_status_manager_factory.h"
112 #include "third_party/blink/public/mojom/clipboard/clipboard.mojom.h"
113 #include "ui/base/clipboard/clipboard.h"
114 #include "ui/base/data_transfer_policy/data_transfer_endpoint.h"
115 #include "ui/events/keycodes/keyboard_codes.h"
116 #endif
117 
118 #if defined(OS_ANDROID)
119 #include "base/feature_list.h"
120 #include "chrome/browser/android/tab_android.h"
121 #include "chrome/browser/autofill/manual_filling_controller.h"
122 #include "chrome/browser/infobars/infobar_service.h"
123 #include "chrome/browser/password_manager/android/account_chooser_dialog_android.h"
124 #include "chrome/browser/password_manager/android/auto_signin_first_run_dialog_android.h"
125 #include "chrome/browser/password_manager/android/auto_signin_prompt_controller.h"
126 #include "chrome/browser/password_manager/android/credential_leak_controller_android.h"
127 #include "chrome/browser/password_manager/android/generated_password_saved_infobar_delegate_android.h"
128 #include "chrome/browser/password_manager/android/password_accessory_controller.h"
129 #include "chrome/browser/password_manager/android/password_accessory_controller_impl.h"
130 #include "chrome/browser/password_manager/android/password_generation_controller.h"
131 #include "chrome/browser/password_manager/android/password_manager_launcher_android.h"
132 #include "chrome/browser/password_manager/android/save_password_infobar_delegate_android.h"
133 #include "chrome/browser/password_manager/android/update_password_infobar_delegate_android.h"
134 #include "chrome/browser/password_manager/password_scripts_fetcher_factory.h"
135 #include "chrome/browser/touch_to_fill/touch_to_fill_controller.h"
136 #include "components/infobars/core/infobar.h"
137 #include "components/messages/android/messages_feature.h"
138 #include "components/password_manager/core/browser/credential_cache.h"
139 #include "ui/base/ui_base_features.h"
140 #else
141 #include "chrome/browser/ui/browser_finder.h"
142 #endif
143 
144 #if BUILDFLAG(ENABLE_EXTENSIONS)
145 #include "extensions/common/constants.h"
146 #endif
147 
148 #if !defined(OS_CHROMEOS) && !defined(OS_ANDROID)
149 #include "chrome/browser/signin/dice_web_signin_interceptor_factory.h"
150 #endif
151 
152 #if defined(OS_ANDROID)
153 using password_manager::CredentialCache;
154 #endif
155 
156 using autofill::mojom::FocusedFieldType;
157 using autofill::password_generation::PasswordGenerationType;
158 using password_manager::BadMessageReason;
159 using password_manager::ContentPasswordManagerDriverFactory;
160 using password_manager::FieldInfoManager;
161 using password_manager::PasswordForm;
162 using password_manager::PasswordManagerClientHelper;
163 using password_manager::PasswordManagerDriver;
164 using password_manager::PasswordManagerMetricsRecorder;
165 using password_manager::metrics_util::PasswordType;
166 using sessions::SerializedNavigationEntry;
167 
168 // Shorten the name to spare line breaks. The code provides enough context
169 // already.
170 typedef autofill::SavePasswordProgressLogger Logger;
171 
172 namespace {
173 
GetSyncService(Profile * profile)174 const syncer::SyncService* GetSyncService(Profile* profile) {
175   if (ProfileSyncServiceFactory::HasSyncService(profile))
176     return ProfileSyncServiceFactory::GetForProfile(profile);
177   return nullptr;
178 }
179 
180 // Adds |observer| to the input observers of |widget_host|.
AddToWidgetInputEventObservers(content::RenderWidgetHost * widget_host,content::RenderWidgetHost::InputEventObserver * observer)181 void AddToWidgetInputEventObservers(
182     content::RenderWidgetHost* widget_host,
183     content::RenderWidgetHost::InputEventObserver* observer) {
184 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
185   // TODO(https://crbug.com/1104919): Remove this logging.
186   VLOG(1) << __FUNCTION__ << ": widget_host: " << widget_host
187           << "; observer: " << observer;
188 #endif
189 
190   // Since Widget API doesn't allow to check whether the observer is already
191   // added, the observer is removed and added again, to ensure that it is added
192   // only once.
193 #if defined(OS_ANDROID)
194   widget_host->RemoveImeInputEventObserver(observer);
195   widget_host->AddImeInputEventObserver(observer);
196 #endif
197   widget_host->RemoveInputEventObserver(observer);
198   widget_host->AddInputEventObserver(observer);
199 }
200 
201 // Removes |observer| from the input observers of |widget_host|.
202 // This method is a NOOP for branded builds.
MaybeRemoveFromWidgetInputEventObservers(content::RenderWidgetHost * widget_host,content::RenderWidgetHost::InputEventObserver * observer)203 void MaybeRemoveFromWidgetInputEventObservers(
204     content::RenderWidgetHost* widget_host,
205     content::RenderWidgetHost::InputEventObserver* observer) {
206 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
207   // TODO(https://crbug.com/1104919): Remove this logging.
208   VLOG(1) << __FUNCTION__ << ": widget_host: " << widget_host
209           << "; observer: " << observer;
210 
211   if (!widget_host)
212     return;
213 
214 #if defined(OS_ANDROID)
215   widget_host->RemoveImeInputEventObserver(observer);
216 #endif
217   widget_host->RemoveInputEventObserver(observer);
218 #endif  // !BUILDFLAG(GOOGLE_CHROME_BRANDING)
219 }
220 
221 #if defined(OS_ANDROID)
HideSavePasswordInfobar(content::WebContents * web_contents)222 void HideSavePasswordInfobar(content::WebContents* web_contents) {
223   InfoBarService* infobar_service =
224       InfoBarService::FromWebContents(web_contents);
225   for (size_t i = 0; i < infobar_service->infobar_count(); ++i) {
226     infobars::InfoBar* infobar = infobar_service->infobar_at(i);
227     if (infobar->delegate()->GetIdentifier() ==
228         SavePasswordInfoBarDelegate::SAVE_PASSWORD_INFOBAR_DELEGATE_MOBILE) {
229       infobar_service->RemoveInfoBar(infobar);
230       break;
231     }
232   }
233 }
234 #endif  // defined(OS_ANDROID)
235 
236 class NavigationPasswordMetricsRecorder
237     : public PasswordManagerMetricsRecorder::NavigationMetricRecorderDelegate {
238  public:
NavigationPasswordMetricsRecorder(content::WebContents * web_contents)239   explicit NavigationPasswordMetricsRecorder(content::WebContents* web_contents)
240       : web_contents_(web_contents) {}
241 
OnUserFocusedPasswordFieldFirstTime()242   void OnUserFocusedPasswordFieldFirstTime() override {
243     RecordEngagementLevel("Security.PasswordFocus.SiteEngagementLevel");
244   }
245 
OnUserModifiedPasswordFieldFirstTime()246   void OnUserModifiedPasswordFieldFirstTime() override {
247     RecordEngagementLevel("Security.PasswordEntry.SiteEngagementLevel");
248   }
249 
250  private:
RecordEngagementLevel(const char * histogram_name)251   void RecordEngagementLevel(const char* histogram_name) {
252     const GURL& main_frame_url = web_contents_->GetLastCommittedURL();
253     if (main_frame_url.SchemeIsHTTPOrHTTPS()) {
254       SiteEngagementService* site_engagement_service =
255           SiteEngagementService::Get(
256               Profile::FromBrowserContext(web_contents_->GetBrowserContext()));
257       blink::mojom::EngagementLevel engagement_level =
258           site_engagement_service->GetEngagementLevel(main_frame_url);
259       base::UmaHistogramEnumeration(histogram_name, engagement_level);
260     }
261   }
262 
263   content::WebContents* web_contents_;
264 };
265 
266 }  // namespace
267 
268 // static
CreateForWebContentsWithAutofillClient(content::WebContents * contents,autofill::AutofillClient * autofill_client)269 void ChromePasswordManagerClient::CreateForWebContentsWithAutofillClient(
270     content::WebContents* contents,
271     autofill::AutofillClient* autofill_client) {
272   if (FromWebContents(contents))
273     return;
274 
275   contents->SetUserData(UserDataKey(),
276                         base::WrapUnique(new ChromePasswordManagerClient(
277                             contents, autofill_client)));
278 }
279 
~ChromePasswordManagerClient()280 ChromePasswordManagerClient::~ChromePasswordManagerClient() {
281 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
282   // TODO(https://crbug.com/1104919): Remove this logging.
283   VLOG(1) << __FUNCTION__ << ": this: " << this;
284   VLOG(1) << "wc: " << web_contents();
285   if (web_contents()) {
286     VLOG(1) << "wc->GetRenderViewHost(): "
287             << web_contents()->GetMainFrame()->GetRenderViewHost();
288   }
289 #endif
290 }
291 
IsSavingAndFillingEnabled(const GURL & url) const292 bool ChromePasswordManagerClient::IsSavingAndFillingEnabled(
293     const GURL& url) const {
294   if (base::CommandLine::ForCurrentProcess()->HasSwitch(
295           switches::kEnableAutomation)) {
296     // Disable the password saving UI for automated tests. It obscures the
297     // page, and there is no API to access (or dismiss) UI bubbles/infobars.
298     return false;
299   }
300   return *saving_passwords_enabled_ && !IsIncognito() && IsFillingEnabled(url);
301 }
302 
IsFillingEnabled(const GURL & url) const303 bool ChromePasswordManagerClient::IsFillingEnabled(const GURL& url) const {
304   const bool ssl_errors = net::IsCertStatusError(GetMainFrameCertStatus());
305 
306   if (log_manager_->IsLoggingActive()) {
307     password_manager::BrowserSavePasswordProgressLogger logger(
308         log_manager_.get());
309     logger.LogBoolean(Logger::STRING_SSL_ERRORS_PRESENT, ssl_errors);
310   }
311 
312   return !ssl_errors && IsPasswordManagementEnabledForCurrentPage(url);
313 }
314 
IsFillingFallbackEnabled(const GURL & url) const315 bool ChromePasswordManagerClient::IsFillingFallbackEnabled(
316     const GURL& url) const {
317   return IsFillingEnabled(url) &&
318          !Profile::FromBrowserContext(web_contents()->GetBrowserContext())
319               ->IsGuestSession();
320 }
321 
PromptUserToSaveOrUpdatePassword(std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,bool update_password)322 bool ChromePasswordManagerClient::PromptUserToSaveOrUpdatePassword(
323     std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,
324     bool update_password) {
325   // The save password infobar and the password bubble prompt in case of
326   // "webby" URLs and do not prompt in case of "non-webby" URLS (e.g. file://).
327   if (!CanShowBubbleOnURL(web_contents()->GetLastCommittedURL()))
328     return false;
329 
330 #if defined(OS_ANDROID)
331   if (form_to_save->IsBlacklisted())
332     return false;
333 
334   if (update_password) {
335     UpdatePasswordInfoBarDelegate::Create(web_contents(),
336                                           std::move(form_to_save));
337   } else {
338     if (messages::IsPasswordMessagesUiEnabled()) {
339       save_password_message_delegate_.DisplaySavePasswordPrompt(
340           web_contents(), std::move(form_to_save));
341     } else {
342       SavePasswordInfoBarDelegate::Create(web_contents(),
343                                           std::move(form_to_save));
344     }
345   }
346 #else
347   PasswordsClientUIDelegate* manage_passwords_ui_controller =
348       PasswordsClientUIDelegateFromWebContents(web_contents());
349   if (update_password) {
350     manage_passwords_ui_controller->OnUpdatePasswordSubmitted(
351         std::move(form_to_save));
352   } else {
353     manage_passwords_ui_controller->OnPasswordSubmitted(
354         std::move(form_to_save));
355   }
356 #endif
357   return true;
358 }
359 
PromptUserToMovePasswordToAccount(std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_move)360 void ChromePasswordManagerClient::PromptUserToMovePasswordToAccount(
361     std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_move) {
362 #if !defined(OS_ANDROID)
363   PasswordsClientUIDelegateFromWebContents(web_contents())
364       ->OnShowMoveToAccountBubble(std::move(form_to_move));
365 #endif  // !defined(OS_ANDROID)
366 }
367 
ShowManualFallbackForSaving(std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,bool has_generated_password,bool is_update)368 void ChromePasswordManagerClient::ShowManualFallbackForSaving(
369     std::unique_ptr<password_manager::PasswordFormManagerForUI> form_to_save,
370     bool has_generated_password,
371     bool is_update) {
372 #if !defined(OS_ANDROID)
373   if (!CanShowBubbleOnURL(web_contents()->GetLastCommittedURL()))
374     return;
375 
376   PasswordsClientUIDelegate* manage_passwords_ui_controller =
377       PasswordsClientUIDelegateFromWebContents(web_contents());
378   // There may be no UI controller for ChromeOS login page
379   // (see crbug.com/774676).
380   if (manage_passwords_ui_controller) {
381     manage_passwords_ui_controller->OnShowManualFallbackForSaving(
382         std::move(form_to_save), has_generated_password, is_update);
383   }
384 #endif  // !defined(OS_ANDROID)
385 }
386 
HideManualFallbackForSaving()387 void ChromePasswordManagerClient::HideManualFallbackForSaving() {
388 #if !defined(OS_ANDROID)
389   if (!CanShowBubbleOnURL(web_contents()->GetLastCommittedURL()))
390     return;
391 
392   PasswordsClientUIDelegate* manage_passwords_ui_controller =
393       PasswordsClientUIDelegateFromWebContents(web_contents());
394   // There may be no UI controller for ChromeOS login page
395   // (see crbug.com/774676).
396   if (manage_passwords_ui_controller)
397     manage_passwords_ui_controller->OnHideManualFallbackForSaving();
398 #endif  // !defined(OS_ANDROID)
399 }
400 
FocusedInputChanged(PasswordManagerDriver * driver,autofill::mojom::FocusedFieldType focused_field_type)401 void ChromePasswordManagerClient::FocusedInputChanged(
402     PasswordManagerDriver* driver,
403     autofill::mojom::FocusedFieldType focused_field_type) {
404 #if defined(OS_ANDROID)
405   ManualFillingController::GetOrCreate(web_contents())
406       ->NotifyFocusedInputChanged(focused_field_type);
407   password_manager::ContentPasswordManagerDriver* content_driver =
408       static_cast<password_manager::ContentPasswordManagerDriver*>(driver);
409   if (!PasswordAccessoryControllerImpl::ShouldAcceptFocusEvent(
410           web_contents(), content_driver, focused_field_type))
411     return;
412 
413   if (!content_driver->CanShowAutofillUi())
414     return;
415 
416   if (!PasswordAccessoryController::AllowedForWebContents(web_contents()))
417     return;
418 
419   if (web_contents()->GetFocusedFrame()) {
420     GetOrCreatePasswordAccessory()->RefreshSuggestionsForField(
421         focused_field_type,
422         password_manager_util::ManualPasswordGenerationEnabled(driver));
423   }
424 
425   PasswordGenerationController::GetOrCreate(web_contents())
426       ->FocusedInputChanged(focused_field_type,
427                             base::AsWeakPtr(content_driver));
428 #endif  // defined(OS_ANDROID)
429 }
430 
PromptUserToChooseCredentials(std::vector<std::unique_ptr<PasswordForm>> local_forms,const url::Origin & origin,CredentialsCallback callback)431 bool ChromePasswordManagerClient::PromptUserToChooseCredentials(
432     std::vector<std::unique_ptr<PasswordForm>> local_forms,
433     const url::Origin& origin,
434     CredentialsCallback callback) {
435   // Set up an intercept callback if the prompt is zero-clickable (e.g. just one
436   // form provided).
437   CredentialsCallback intercept = base::BindOnce(
438       &PasswordManagerClientHelper::OnCredentialsChosen,
439       base::Unretained(&helper_), std::move(callback), local_forms.size() == 1);
440 #if defined(OS_ANDROID)
441   // Deletes itself on the event from Java counterpart, when user interacts with
442   // dialog.
443   AccountChooserDialogAndroid* acccount_chooser_dialog =
444       new AccountChooserDialogAndroid(web_contents(), std::move(local_forms),
445                                       origin, std::move(intercept));
446   return acccount_chooser_dialog->ShowDialog();
447 #else
448   return PasswordsClientUIDelegateFromWebContents(web_contents())
449       ->OnChooseCredentials(std::move(local_forms), origin,
450                             std::move(intercept));
451 #endif
452 }
453 
ShowTouchToFill(PasswordManagerDriver * driver)454 void ChromePasswordManagerClient::ShowTouchToFill(
455     PasswordManagerDriver* driver) {
456 #if defined(OS_ANDROID)
457   GetOrCreateTouchToFillController()->Show(
458       credential_cache_
459           .GetCredentialStore(
460               url::Origin::Create(driver->GetLastCommittedURL().GetOrigin()))
461           .GetCredentials(),
462       driver->AsWeakPtr());
463 #endif
464 }
465 
466 #if defined(OS_ANDROID)
OnPasswordSelected(const base::string16 & text)467 void ChromePasswordManagerClient::OnPasswordSelected(
468     const base::string16& text) {
469   password_reuse_detection_manager_.OnPaste(text);
470 }
471 #endif
472 
IsAutofillAssistantUIVisible() const473 bool ChromePasswordManagerClient::IsAutofillAssistantUIVisible() const {
474   auto* autofill_assistant_manager =
475       autofill_assistant::RuntimeManager::GetForWebContents(web_contents());
476   return autofill_assistant_manager && autofill_assistant_manager->GetState() ==
477                                            autofill_assistant::UIState::kShown;
478 }
479 
480 password_manager::BiometricAuthenticator*
GetBiometricAuthenticator()481 ChromePasswordManagerClient::GetBiometricAuthenticator() {
482 #if defined(OS_ANDROID)
483   if (!biometric_authenticator_) {
484     biometric_authenticator_ =
485         ChromeBiometricAuthenticator::Create(web_contents());
486   }
487 #endif
488   return biometric_authenticator_.get();
489 }
490 
GeneratePassword(PasswordGenerationType type)491 void ChromePasswordManagerClient::GeneratePassword(
492     PasswordGenerationType type) {
493 #if defined(OS_ANDROID)
494   PasswordGenerationController* generation_controller =
495       PasswordGenerationController::GetIfExisting(web_contents());
496   base::WeakPtr<PasswordManagerDriver> driver =
497       generation_controller->GetActiveFrameDriver();
498   if (!driver)
499     return;
500   password_manager::ContentPasswordManagerDriver* content_driver =
501       static_cast<password_manager::ContentPasswordManagerDriver*>(
502           driver.get());
503 #else
504   password_manager::ContentPasswordManagerDriver* content_driver =
505       driver_factory_->GetDriverForFrame(web_contents()->GetFocusedFrame());
506 #endif
507   // Using unretained pointer is safe because |this| outlives
508   // ContentPasswordManagerDriver that holds the connection.
509   content_driver->GeneratePassword(base::BindOnce(
510       &ChromePasswordManagerClient::GenerationResultAvailable,
511       base::Unretained(this), type, base::AsWeakPtr(content_driver)));
512 }
513 
NotifyUserAutoSignin(std::vector<std::unique_ptr<PasswordForm>> local_forms,const url::Origin & origin)514 void ChromePasswordManagerClient::NotifyUserAutoSignin(
515     std::vector<std::unique_ptr<PasswordForm>> local_forms,
516     const url::Origin& origin) {
517   DCHECK(!local_forms.empty());
518   helper_.NotifyUserAutoSignin();
519 #if defined(OS_ANDROID)
520   ShowAutoSigninPrompt(web_contents(), local_forms[0]->username_value);
521 #else
522   PasswordsClientUIDelegateFromWebContents(web_contents())
523       ->OnAutoSignin(std::move(local_forms), origin);
524 #endif
525 }
526 
NotifyUserCouldBeAutoSignedIn(std::unique_ptr<PasswordForm> form)527 void ChromePasswordManagerClient::NotifyUserCouldBeAutoSignedIn(
528     std::unique_ptr<PasswordForm> form) {
529   helper_.NotifyUserCouldBeAutoSignedIn(std::move(form));
530 }
531 
NotifySuccessfulLoginWithExistingPassword(std::unique_ptr<password_manager::PasswordFormManagerForUI> submitted_manager)532 void ChromePasswordManagerClient::NotifySuccessfulLoginWithExistingPassword(
533     std::unique_ptr<password_manager::PasswordFormManagerForUI>
534         submitted_manager) {
535   helper_.NotifySuccessfulLoginWithExistingPassword(
536       std::move(submitted_manager));
537 }
538 
NotifyStorePasswordCalled()539 void ChromePasswordManagerClient::NotifyStorePasswordCalled() {
540   helper_.NotifyStorePasswordCalled();
541   was_store_ever_called_ = true;
542 }
543 
UpdateCredentialCache(const url::Origin & origin,const std::vector<const PasswordForm * > & best_matches,bool is_blacklisted)544 void ChromePasswordManagerClient::UpdateCredentialCache(
545     const url::Origin& origin,
546     const std::vector<const PasswordForm*>& best_matches,
547     bool is_blacklisted) {
548 #if defined(OS_ANDROID)
549   credential_cache_.SaveCredentialsAndBlacklistedForOrigin(
550       best_matches, CredentialCache::IsOriginBlacklisted(is_blacklisted),
551       origin);
552 
553 #endif
554 }
555 
AutomaticPasswordSave(std::unique_ptr<password_manager::PasswordFormManagerForUI> saved_form)556 void ChromePasswordManagerClient::AutomaticPasswordSave(
557     std::unique_ptr<password_manager::PasswordFormManagerForUI> saved_form) {
558 #if defined(OS_ANDROID)
559   GeneratedPasswordSavedInfoBarDelegateAndroid::Create(web_contents());
560 #else
561   PasswordsClientUIDelegate* manage_passwords_ui_controller =
562       PasswordsClientUIDelegateFromWebContents(web_contents());
563   manage_passwords_ui_controller->OnAutomaticPasswordSave(
564       std::move(saved_form));
565 #endif
566 }
567 
PasswordWasAutofilled(const std::vector<const PasswordForm * > & best_matches,const url::Origin & origin,const std::vector<const PasswordForm * > * federated_matches)568 void ChromePasswordManagerClient::PasswordWasAutofilled(
569     const std::vector<const PasswordForm*>& best_matches,
570     const url::Origin& origin,
571     const std::vector<const PasswordForm*>* federated_matches) {
572 #if !defined(OS_ANDROID)
573   PasswordsClientUIDelegate* manage_passwords_ui_controller =
574       PasswordsClientUIDelegateFromWebContents(web_contents());
575   manage_passwords_ui_controller->OnPasswordAutofilled(best_matches, origin,
576                                                        federated_matches);
577 #endif
578 }
579 
AutofillHttpAuth(const PasswordForm & preferred_match,const password_manager::PasswordFormManagerForUI * form_manager)580 void ChromePasswordManagerClient::AutofillHttpAuth(
581     const PasswordForm& preferred_match,
582     const password_manager::PasswordFormManagerForUI* form_manager) {
583   httpauth_manager_.Autofill(preferred_match, form_manager);
584   DCHECK(!form_manager->GetBestMatches().empty());
585   PasswordWasAutofilled(form_manager->GetBestMatches(),
586                         url::Origin::Create(form_manager->GetURL()), nullptr);
587 }
588 
NotifyUserCredentialsWereLeaked(password_manager::CredentialLeakType leak_type,password_manager::CompromisedSitesCount saved_sites,const GURL & origin,const base::string16 & username)589 void ChromePasswordManagerClient::NotifyUserCredentialsWereLeaked(
590     password_manager::CredentialLeakType leak_type,
591     password_manager::CompromisedSitesCount saved_sites,
592     const GURL& origin,
593     const base::string16& username) {
594 #if defined(OS_ANDROID)
595   if (base::FeatureList::IsEnabled(
596           password_manager::features::kPasswordScriptsFetching) &&
597       GetPasswordFeatureManager()->IsGenerationEnabled()) {
598     PasswordScriptsFetcherFactory::GetInstance()
599         ->GetForBrowserContext(web_contents()->GetBrowserContext())
600         ->PrewarmCache();
601   }
602   if (base::FeatureList::IsEnabled(
603           password_manager::features::kPasswordChange)) {
604     was_leak_dialog_shown_ = true;
605   }
606 
607   save_password_message_delegate_.DismissSavePasswordPrompt();
608   HideSavePasswordInfobar(web_contents());
609 
610   (new CredentialLeakControllerAndroid(
611        leak_type, saved_sites, origin, username,
612        web_contents()->GetTopLevelNativeWindow()))
613       ->ShowDialog();
614 #else   // !defined(OS_ANDROID)
615   PasswordsClientUIDelegate* manage_passwords_ui_controller =
616       PasswordsClientUIDelegateFromWebContents(web_contents());
617   manage_passwords_ui_controller->OnCredentialLeak(leak_type, origin);
618 #endif  // defined(OS_ANDROID)
619 }
620 
TriggerReauthForPrimaryAccount(signin_metrics::ReauthAccessPoint access_point,base::OnceCallback<void (ReauthSucceeded)> reauth_callback)621 void ChromePasswordManagerClient::TriggerReauthForPrimaryAccount(
622     signin_metrics::ReauthAccessPoint access_point,
623     base::OnceCallback<void(ReauthSucceeded)> reauth_callback) {
624 #if defined(OS_ANDROID)
625   std::move(reauth_callback).Run(ReauthSucceeded(false));
626 #else   // !defined(OS_ANDROID)
627   account_storage_auth_helper_.TriggerOptInReauth(access_point,
628                                                   std::move(reauth_callback));
629 #endif  // defined(OS_ANDROID)
630 }
631 
TriggerSignIn(signin_metrics::AccessPoint access_point)632 void ChromePasswordManagerClient::TriggerSignIn(
633     signin_metrics::AccessPoint access_point) {
634 #if !defined(OS_ANDROID)
635   account_storage_auth_helper_.TriggerSignIn(access_point);
636 #endif
637 }
638 
GetPrefs() const639 PrefService* ChromePasswordManagerClient::GetPrefs() const {
640   return profile_->GetPrefs();
641 }
642 
643 password_manager::PasswordStore*
GetProfilePasswordStore() const644 ChromePasswordManagerClient::GetProfilePasswordStore() const {
645   // Always use EXPLICIT_ACCESS as the password manager checks IsIncognito
646   // itself when it shouldn't access the PasswordStore.
647   return PasswordStoreFactory::GetForProfile(profile_,
648                                              ServiceAccessType::EXPLICIT_ACCESS)
649       .get();
650 }
651 
652 password_manager::PasswordStore*
GetAccountPasswordStore() const653 ChromePasswordManagerClient::GetAccountPasswordStore() const {
654   // Always use EXPLICIT_ACCESS as the password manager checks IsIncognito
655   // itself when it shouldn't access the PasswordStore.
656   return AccountPasswordStoreFactory::GetForProfile(
657              profile_, ServiceAccessType::EXPLICIT_ACCESS)
658       .get();
659 }
660 
GetPasswordSyncState() const661 password_manager::SyncState ChromePasswordManagerClient::GetPasswordSyncState()
662     const {
663   const syncer::SyncService* sync_service =
664       ProfileSyncServiceFactory::GetForProfile(profile_);
665   return password_manager_util::GetPasswordSyncState(sync_service);
666 }
667 
WasLastNavigationHTTPError() const668 bool ChromePasswordManagerClient::WasLastNavigationHTTPError() const {
669   DCHECK(web_contents());
670 
671   std::unique_ptr<password_manager::BrowserSavePasswordProgressLogger> logger;
672   if (log_manager_->IsLoggingActive()) {
673     logger =
674         std::make_unique<password_manager::BrowserSavePasswordProgressLogger>(
675             log_manager_.get());
676     logger->LogMessage(Logger::STRING_WAS_LAST_NAVIGATION_HTTP_ERROR_METHOD);
677   }
678 
679   content::NavigationEntry* entry =
680       web_contents()->GetController().GetVisibleEntry();
681   if (!entry)
682     return false;
683   int http_status_code = entry->GetHttpStatusCode();
684 
685   if (logger)
686     logger->LogNumber(Logger::STRING_HTTP_STATUS_CODE, http_status_code);
687 
688   if (http_status_code >= 400 && http_status_code < 600)
689     return true;
690   return false;
691 }
692 
693 #if defined(OS_ANDROID)
WasCredentialLeakDialogShown() const694 bool ChromePasswordManagerClient::WasCredentialLeakDialogShown() const {
695   return was_leak_dialog_shown_;
696 }
697 #endif  // defined(OS_ANDROID)
698 
GetMainFrameCertStatus() const699 net::CertStatus ChromePasswordManagerClient::GetMainFrameCertStatus() const {
700   content::NavigationEntry* entry =
701       web_contents()->GetController().GetLastCommittedEntry();
702   if (!entry)
703     return 0;
704   return entry->GetSSL().cert_status;
705 }
706 
PromptUserToEnableAutosignin()707 void ChromePasswordManagerClient::PromptUserToEnableAutosignin() {
708 #if defined(OS_ANDROID)
709   // Dialog is deleted by the Java counterpart after user interacts with it.
710   AutoSigninFirstRunDialogAndroid* auto_signin_first_run_dialog =
711       new AutoSigninFirstRunDialogAndroid(web_contents());
712   auto_signin_first_run_dialog->ShowDialog();
713 #else
714   PasswordsClientUIDelegateFromWebContents(web_contents())
715       ->OnPromptEnableAutoSignin();
716 #endif
717 }
718 
IsIncognito() const719 bool ChromePasswordManagerClient::IsIncognito() const {
720   return web_contents()->GetBrowserContext()->IsOffTheRecord();
721 }
722 
723 const password_manager::PasswordManager*
GetPasswordManager() const724 ChromePasswordManagerClient::GetPasswordManager() const {
725   return &password_manager_;
726 }
727 
728 const password_manager::PasswordFeatureManager*
GetPasswordFeatureManager() const729 ChromePasswordManagerClient::GetPasswordFeatureManager() const {
730   return &password_feature_manager_;
731 }
732 
733 password_manager::HttpAuthManager*
GetHttpAuthManager()734 ChromePasswordManagerClient::GetHttpAuthManager() {
735   return &httpauth_manager_;
736 }
737 
738 autofill::AutofillDownloadManager*
GetAutofillDownloadManager()739 ChromePasswordManagerClient::GetAutofillDownloadManager() {
740   autofill::ContentAutofillDriverFactory* factory =
741       autofill::ContentAutofillDriverFactory::FromWebContents(web_contents());
742   if (factory) {
743     autofill::ContentAutofillDriver* driver =
744         factory->DriverForFrame(web_contents()->GetMainFrame());
745     // |driver| can be NULL if the tab is being closed.
746     if (driver) {
747       autofill::AutofillManager* autofill_manager = driver->autofill_manager();
748       if (autofill_manager)
749         return autofill_manager->download_manager();
750     }
751   }
752   return nullptr;
753 }
754 
IsCommittedMainFrameSecure() const755 bool ChromePasswordManagerClient::IsCommittedMainFrameSecure() const {
756   return content::IsPotentiallyTrustworthyOrigin(
757       web_contents()->GetMainFrame()->GetLastCommittedOrigin());
758 }
759 
GetLastCommittedURL() const760 const GURL& ChromePasswordManagerClient::GetLastCommittedURL() const {
761   return web_contents()->GetLastCommittedURL();
762 }
763 
GetLastCommittedOrigin() const764 url::Origin ChromePasswordManagerClient::GetLastCommittedOrigin() const {
765   DCHECK(web_contents());
766   return web_contents()->GetMainFrame()->GetLastCommittedOrigin();
767 }
768 const password_manager::CredentialsFilter*
GetStoreResultFilter() const769 ChromePasswordManagerClient::GetStoreResultFilter() const {
770   return &credentials_filter_;
771 }
772 
GetLogManager() const773 const autofill::LogManager* ChromePasswordManagerClient::GetLogManager() const {
774   return log_manager_.get();
775 }
776 
AnnotateNavigationEntry(bool has_password_field)777 void ChromePasswordManagerClient::AnnotateNavigationEntry(
778     bool has_password_field) {
779   if (!ShouldAnnotateNavigationEntries(profile_))
780     return;
781 
782   content::NavigationEntry* entry =
783       web_contents()->GetController().GetLastCommittedEntry();
784   if (!entry)
785     return;
786 
787   SerializedNavigationEntry::PasswordState old_state =
788       sessions::GetPasswordStateFromNavigation(entry);
789 
790   SerializedNavigationEntry::PasswordState new_state =
791       (has_password_field ? SerializedNavigationEntry::HAS_PASSWORD_FIELD
792                           : SerializedNavigationEntry::NO_PASSWORD_FIELD);
793 
794   if (new_state > old_state) {
795     SetPasswordStateInNavigation(new_state, entry);
796   }
797 }
798 
GetPageLanguage() const799 std::string ChromePasswordManagerClient::GetPageLanguage() const {
800   // TODO(crbug.com/912597): iOS vs other platforms extracts language from
801   // the top level frame vs whatever frame directly holds the form.
802   auto* translate_manager =
803       ChromeTranslateClient::GetManagerFromWebContents(web_contents());
804   if (translate_manager)
805     return translate_manager->GetLanguageState()->original_language();
806   return std::string();
807 }
808 
809 #if defined(ON_FOCUS_PING_ENABLED) || defined(PASSWORD_REUSE_DETECTION_ENABLED)
810 safe_browsing::PasswordProtectionService*
GetPasswordProtectionService() const811 ChromePasswordManagerClient::GetPasswordProtectionService() const {
812   return safe_browsing::ChromePasswordProtectionService::
813       GetPasswordProtectionService(profile_);
814 }
815 #endif
816 
817 #if defined(ON_FOCUS_PING_ENABLED)
CheckSafeBrowsingReputation(const GURL & form_action,const GURL & frame_url)818 void ChromePasswordManagerClient::CheckSafeBrowsingReputation(
819     const GURL& form_action,
820     const GURL& frame_url) {
821   safe_browsing::PasswordProtectionService* pps =
822       GetPasswordProtectionService();
823   if (pps) {
824     pps->MaybeStartPasswordFieldOnFocusRequest(
825         web_contents(), web_contents()->GetLastCommittedURL(), form_action,
826         frame_url, pps->GetAccountInfo().hosted_domain);
827   }
828 }
829 #endif  // defined(ON_FOCUS_PING_ENABLED)
830 
831 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
CheckProtectedPasswordEntry(PasswordType password_type,const std::string & username,const std::vector<password_manager::MatchingReusedCredential> & matching_reused_credentials,bool password_field_exists)832 void ChromePasswordManagerClient::CheckProtectedPasswordEntry(
833     PasswordType password_type,
834     const std::string& username,
835     const std::vector<password_manager::MatchingReusedCredential>&
836         matching_reused_credentials,
837     bool password_field_exists) {
838   safe_browsing::PasswordProtectionService* pps =
839       GetPasswordProtectionService();
840   if (!pps)
841     return;
842 
843   pps->MaybeStartProtectedPasswordEntryRequest(
844       web_contents(), web_contents()->GetLastCommittedURL(), username,
845       password_type, matching_reused_credentials, password_field_exists);
846 }
847 #endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
848 
849 #if defined(PASSWORD_REUSE_WARNING_ENABLED)
LogPasswordReuseDetectedEvent()850 void ChromePasswordManagerClient::LogPasswordReuseDetectedEvent() {
851   safe_browsing::PasswordProtectionService* pps =
852       GetPasswordProtectionService();
853   if (pps) {
854     pps->MaybeLogPasswordReuseDetectedEvent(web_contents());
855   }
856 }
857 #endif  // defined(PASSWORD_REUSE_WARNING_ENABLED)
858 
GetUkmSourceId()859 ukm::SourceId ChromePasswordManagerClient::GetUkmSourceId() {
860   return ukm::GetSourceIdForWebContentsDocument(web_contents());
861 }
862 
863 PasswordManagerMetricsRecorder*
GetMetricsRecorder()864 ChromePasswordManagerClient::GetMetricsRecorder() {
865   if (!metrics_recorder_) {
866     metrics_recorder_.emplace(
867         GetUkmSourceId(),
868         std::make_unique<NavigationPasswordMetricsRecorder>(web_contents()));
869   }
870   return base::OptionalOrNullptr(metrics_recorder_);
871 }
872 
873 password_manager::PasswordRequirementsService*
GetPasswordRequirementsService()874 ChromePasswordManagerClient::GetPasswordRequirementsService() {
875   return password_manager::PasswordRequirementsServiceFactory::
876       GetForBrowserContext(
877           Profile::FromBrowserContext(web_contents()->GetBrowserContext()));
878 }
879 
GetFaviconService()880 favicon::FaviconService* ChromePasswordManagerClient::GetFaviconService() {
881   return FaviconServiceFactory::GetForProfile(
882       profile_, ServiceAccessType::EXPLICIT_ACCESS);
883 }
884 
GetIdentityManager()885 signin::IdentityManager* ChromePasswordManagerClient::GetIdentityManager() {
886   return IdentityManagerFactory::GetForProfile(profile_->GetOriginalProfile());
887 }
888 
889 scoped_refptr<network::SharedURLLoaderFactory>
GetURLLoaderFactory()890 ChromePasswordManagerClient::GetURLLoaderFactory() {
891   return content::BrowserContext::GetDefaultStoragePartition(profile_)
892       ->GetURLLoaderFactoryForBrowserProcess();
893 }
894 
GetNetworkContext() const895 network::mojom::NetworkContext* ChromePasswordManagerClient::GetNetworkContext()
896     const {
897   return content::BrowserContext::GetDefaultStoragePartition(profile_)
898       ->GetNetworkContext();
899 }
900 
IsUnderAdvancedProtection() const901 bool ChromePasswordManagerClient::IsUnderAdvancedProtection() const {
902 #if BUILDFLAG(FULL_SAFE_BROWSING)
903   return safe_browsing::AdvancedProtectionStatusManagerFactory::GetForProfile(
904              profile_)
905       ->IsUnderAdvancedProtection();
906 #else
907   return false;
908 #endif
909 }
910 
UpdateFormManagers()911 void ChromePasswordManagerClient::UpdateFormManagers() {
912   password_manager_.UpdateFormManagers();
913 }
914 
NavigateToManagePasswordsPage(password_manager::ManagePasswordsReferrer referrer)915 void ChromePasswordManagerClient::NavigateToManagePasswordsPage(
916     password_manager::ManagePasswordsReferrer referrer) {
917 #if defined(OS_ANDROID)
918   password_manager_launcher::ShowPasswordSettings(web_contents(), referrer);
919 #else
920   ::NavigateToManagePasswordsPage(
921       chrome::FindBrowserWithWebContents(web_contents()), referrer);
922 #endif
923 }
924 
IsIsolationForPasswordSitesEnabled() const925 bool ChromePasswordManagerClient::IsIsolationForPasswordSitesEnabled() const {
926   // TODO(crbug.com/862989): Move the following function (and the feature) to
927   // the password component. Then remove IsIsolationForPasswordsSitesEnabled()
928   // from the PasswordManagerClient interface.
929   return site_isolation::SiteIsolationPolicy::
930       IsIsolationForPasswordSitesEnabled();
931 }
932 
IsNewTabPage() const933 bool ChromePasswordManagerClient::IsNewTabPage() const {
934   auto origin = GetLastCommittedURL().GetOrigin();
935   return origin == GURL(chrome::kChromeSearchLocalNtpUrl).GetOrigin() ||
936          origin == GURL(chrome::kChromeUINewTabPageURL).GetOrigin() ||
937          origin == GURL(chrome::kChromeUINewTabURL).GetOrigin();
938 }
939 
GetFieldInfoManager() const940 FieldInfoManager* ChromePasswordManagerClient::GetFieldInfoManager() const {
941   return FieldInfoManagerFactory::GetForBrowserContext(profile_);
942 }
943 
AutomaticGenerationAvailable(const autofill::password_generation::PasswordGenerationUIData & ui_data)944 void ChromePasswordManagerClient::AutomaticGenerationAvailable(
945     const autofill::password_generation::PasswordGenerationUIData& ui_data) {
946   if (!password_manager::bad_message::CheckChildProcessSecurityPolicyForURL(
947           password_generation_driver_receivers_.GetCurrentTargetFrame(),
948           ui_data.form_data.url,
949           BadMessageReason::
950               CPMD_BAD_ORIGIN_AUTOMATIC_GENERATION_STATUS_CHANGED))
951     return;
952 #if defined(OS_ANDROID)
953   if (PasswordGenerationController::AllowedForWebContents(web_contents())) {
954     PasswordManagerDriver* driver = driver_factory_->GetDriverForFrame(
955         password_generation_driver_receivers_.GetCurrentTargetFrame());
956 
957     PasswordGenerationController* generation_controller =
958         PasswordGenerationController::GetIfExisting(web_contents());
959     DCHECK(generation_controller);
960 
961     gfx::RectF element_bounds_in_screen_space = TransformToRootCoordinates(
962         password_generation_driver_receivers_.GetCurrentTargetFrame(),
963         ui_data.bounds);
964 
965     generation_controller->OnAutomaticGenerationAvailable(
966         driver, ui_data, element_bounds_in_screen_space);
967   }
968 #else
969   password_manager::ContentPasswordManagerDriver* driver =
970       driver_factory_->GetDriverForFrame(
971           password_generation_driver_receivers_.GetCurrentTargetFrame());
972 
973   // Attempt to show the autofill dropdown UI first.
974   gfx::RectF element_bounds_in_top_frame_space =
975       TransformToRootCoordinates(driver->render_frame_host(), ui_data.bounds);
976   if (driver->GetPasswordAutofillManager()
977           ->MaybeShowPasswordSuggestionsWithGeneration(
978               element_bounds_in_top_frame_space, ui_data.text_direction,
979               /*show_password_suggestions=*/
980               ui_data.is_generation_element_password_type)) {
981     return;
982   }
983 
984   ShowPasswordGenerationPopup(PasswordGenerationType::kAutomatic, driver,
985                               ui_data);
986 #endif  // defined(OS_ANDROID)
987 }
988 
ShowPasswordEditingPopup(const gfx::RectF & bounds,const autofill::FormData & form_data,autofill::FieldRendererId field_renderer_id,const base::string16 & password_value)989 void ChromePasswordManagerClient::ShowPasswordEditingPopup(
990     const gfx::RectF& bounds,
991     const autofill::FormData& form_data,
992     autofill::FieldRendererId field_renderer_id,
993     const base::string16& password_value) {
994   if (!password_manager::bad_message::CheckChildProcessSecurityPolicyForURL(
995           password_generation_driver_receivers_.GetCurrentTargetFrame(),
996           form_data.url,
997           BadMessageReason::CPMD_BAD_ORIGIN_SHOW_PASSWORD_EDITING_POPUP))
998     return;
999   auto* driver = driver_factory_->GetDriverForFrame(
1000       password_generation_driver_receivers_.GetCurrentTargetFrame());
1001   gfx::RectF element_bounds_in_screen_space =
1002       GetBoundsInScreenSpace(TransformToRootCoordinates(
1003           password_generation_driver_receivers_.GetCurrentTargetFrame(),
1004           bounds));
1005   autofill::password_generation::PasswordGenerationUIData ui_data(
1006       bounds, /*max_length=*/0, /*generation_element=*/base::string16(),
1007       field_renderer_id, /*is_generation_element_password_type=*/true,
1008       base::i18n::TextDirection(), form_data);
1009   popup_controller_ = PasswordGenerationPopupControllerImpl::GetOrCreate(
1010       popup_controller_, element_bounds_in_screen_space, ui_data,
1011       driver->AsWeakPtr(), observer_, web_contents(),
1012       password_generation_driver_receivers_.GetCurrentTargetFrame());
1013   DCHECK(!password_value.empty());
1014   popup_controller_->UpdatePassword(password_value);
1015   popup_controller_->Show(
1016       PasswordGenerationPopupController::kEditGeneratedPassword);
1017 }
1018 
PasswordGenerationRejectedByTyping()1019 void ChromePasswordManagerClient::PasswordGenerationRejectedByTyping() {
1020   if (popup_controller_)
1021     popup_controller_->GeneratedPasswordRejected();
1022 }
1023 
PresaveGeneratedPassword(const autofill::FormData & form_data,const base::string16 & password_value)1024 void ChromePasswordManagerClient::PresaveGeneratedPassword(
1025     const autofill::FormData& form_data,
1026     const base::string16& password_value) {
1027   if (!password_manager::bad_message::CheckChildProcessSecurityPolicyForURL(
1028           password_generation_driver_receivers_.GetCurrentTargetFrame(),
1029           form_data.url,
1030           BadMessageReason::CPMD_BAD_ORIGIN_PRESAVE_GENERATED_PASSWORD)) {
1031     return;
1032   }
1033   if (popup_controller_)
1034     popup_controller_->UpdatePassword(password_value);
1035 
1036   PasswordManagerDriver* driver = driver_factory_->GetDriverForFrame(
1037       password_generation_driver_receivers_.GetCurrentTargetFrame());
1038   password_manager_.OnPresaveGeneratedPassword(driver, form_data,
1039                                                password_value);
1040 }
1041 
PasswordNoLongerGenerated(const autofill::FormData & form_data)1042 void ChromePasswordManagerClient::PasswordNoLongerGenerated(
1043     const autofill::FormData& form_data) {
1044   if (!password_manager::bad_message::CheckChildProcessSecurityPolicyForURL(
1045           password_generation_driver_receivers_.GetCurrentTargetFrame(),
1046           form_data.url,
1047           BadMessageReason::CPMD_BAD_ORIGIN_PASSWORD_NO_LONGER_GENERATED)) {
1048     return;
1049   }
1050   PasswordManagerDriver* driver = driver_factory_->GetDriverForFrame(
1051       password_generation_driver_receivers_.GetCurrentTargetFrame());
1052   password_manager_.OnPasswordNoLongerGenerated(driver, form_data);
1053 
1054   PasswordGenerationPopupController* controller = popup_controller_.get();
1055   if (controller &&
1056       controller->state() ==
1057           PasswordGenerationPopupController::kEditGeneratedPassword) {
1058     popup_controller_->GeneratedPasswordRejected();
1059   }
1060 }
1061 
FrameWasScrolled()1062 void ChromePasswordManagerClient::FrameWasScrolled() {
1063   if (popup_controller_)
1064     popup_controller_->FrameWasScrolled();
1065 }
1066 
GenerationElementLostFocus()1067 void ChromePasswordManagerClient::GenerationElementLostFocus() {
1068   // TODO(crbug.com/968046): Look into removing this since FocusedInputChanged
1069   // seems to be a good replacement.
1070   if (popup_controller_)
1071     popup_controller_->GenerationElementLostFocus();
1072 }
1073 
1074 #if defined(OS_ANDROID)
OnImeTextCommittedEvent(const base::string16 & text_str)1075 void ChromePasswordManagerClient::OnImeTextCommittedEvent(
1076     const base::string16& text_str) {
1077 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
1078   password_reuse_detection_manager_.OnKeyPressedCommitted(text_str);
1079 #endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
1080 }
1081 
OnImeSetComposingTextEvent(const base::string16 & text_str)1082 void ChromePasswordManagerClient::OnImeSetComposingTextEvent(
1083     const base::string16& text_str) {
1084 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
1085   last_composing_text_ = text_str;
1086   password_reuse_detection_manager_.OnKeyPressedUncommitted(
1087       last_composing_text_);
1088 #endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
1089 }
1090 
OnImeFinishComposingTextEvent()1091 void ChromePasswordManagerClient::OnImeFinishComposingTextEvent() {
1092 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
1093   password_reuse_detection_manager_.OnKeyPressedCommitted(last_composing_text_);
1094   last_composing_text_.clear();
1095 #endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
1096 }
1097 #endif  // defined(OS_ANDROID)
1098 
SetTestObserver(PasswordGenerationPopupObserver * observer)1099 void ChromePasswordManagerClient::SetTestObserver(
1100     PasswordGenerationPopupObserver* observer) {
1101   observer_ = observer;
1102 }
1103 
1104 // static
BindCredentialManager(content::RenderFrameHost * render_frame_host,mojo::PendingReceiver<blink::mojom::CredentialManager> receiver)1105 void ChromePasswordManagerClient::BindCredentialManager(
1106     content::RenderFrameHost* render_frame_host,
1107     mojo::PendingReceiver<blink::mojom::CredentialManager> receiver) {
1108   // Only valid for the main frame.
1109   if (render_frame_host->GetParent())
1110     return;
1111 
1112   content::WebContents* web_contents =
1113       content::WebContents::FromRenderFrameHost(render_frame_host);
1114   DCHECK(web_contents);
1115 
1116   // Only valid for the currently committed RenderFrameHost, and not, e.g. old
1117   // zombie RFH's being swapped out following cross-origin navigations.
1118   if (web_contents->GetMainFrame() != render_frame_host)
1119     return;
1120 
1121   ChromePasswordManagerClient* instance =
1122       ChromePasswordManagerClient::FromWebContents(web_contents);
1123 
1124   // Try to bind to the driver, but if driver is not available for this render
1125   // frame host, the request will be just dropped. This will cause the message
1126   // pipe to be closed, which will raise a connection error on the peer side.
1127   if (!instance)
1128     return;
1129 
1130   // Disable BackForwardCache for this page.
1131   // This is necessary because ContentCredentialManager::DisconnectBinding()
1132   // will be called when the page is navigated away from, leaving it
1133   // in an unusable state if the page is restored from the BackForwardCache.
1134   //
1135   // It looks like in order to remove this workaround, we probably just need to
1136   // make the CredentialManager mojo API rebind on the renderer side when the
1137   // next call is made, if it has become disconnected.
1138   // TODO(https://crbug.com/1015358): Remove this workaround.
1139   content::BackForwardCache::DisableForRenderFrameHost(
1140       render_frame_host, "ChromePasswordManagerClient::BindCredentialManager");
1141 
1142   instance->content_credential_manager_.BindRequest(std::move(receiver));
1143 }
1144 
1145 // static
CanShowBubbleOnURL(const GURL & url)1146 bool ChromePasswordManagerClient::CanShowBubbleOnURL(const GURL& url) {
1147   std::string scheme = url.scheme();
1148   return (content::ChildProcessSecurityPolicy::GetInstance()->IsWebSafeScheme(
1149               scheme) &&
1150 #if BUILDFLAG(ENABLE_EXTENSIONS)
1151           scheme != extensions::kExtensionScheme &&
1152 #endif
1153           scheme != content::kChromeDevToolsScheme);
1154 }
1155 
1156 #if defined(OS_ANDROID)
1157 PasswordAccessoryController*
GetOrCreatePasswordAccessory()1158 ChromePasswordManagerClient::GetOrCreatePasswordAccessory() {
1159   return PasswordAccessoryController::GetOrCreate(web_contents(),
1160                                                   &credential_cache_);
1161 }
1162 
1163 TouchToFillController*
GetOrCreateTouchToFillController()1164 ChromePasswordManagerClient::GetOrCreateTouchToFillController() {
1165   if (!touch_to_fill_controller_)
1166     touch_to_fill_controller_ = std::make_unique<TouchToFillController>(this);
1167 
1168   return touch_to_fill_controller_.get();
1169 }
1170 #endif  // defined(OS_ANDROID)
1171 
ChromePasswordManagerClient(content::WebContents * web_contents,autofill::AutofillClient * autofill_client)1172 ChromePasswordManagerClient::ChromePasswordManagerClient(
1173     content::WebContents* web_contents,
1174     autofill::AutofillClient* autofill_client)
1175     : content::WebContentsObserver(web_contents),
1176       profile_(Profile::FromBrowserContext(web_contents->GetBrowserContext())),
1177       password_manager_(this),
1178       password_feature_manager_(
1179           profile_->GetPrefs(),
1180           ProfileSyncServiceFactory::GetForProfile(profile_)),
1181       httpauth_manager_(this),
1182 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
1183       password_reuse_detection_manager_(this),
1184 #endif
1185       driver_factory_(nullptr),
1186       content_credential_manager_(this),
1187       password_generation_driver_receivers_(web_contents, this),
1188       observer_(nullptr),
1189 #if defined(OS_CHROMEOS) || defined(OS_ANDROID)
1190       credentials_filter_(this, base::BindRepeating(&GetSyncService, profile_)),
1191 #else
1192       credentials_filter_(
1193           this,
1194           base::BindRepeating(&GetSyncService, profile_),
1195           DiceWebSigninInterceptorFactory::GetForProfile(profile_)),
1196 #endif
1197 #if !defined(OS_ANDROID)
1198       account_storage_auth_helper_(profile_, &password_feature_manager_),
1199 #endif
1200       helper_(this) {
1201   ContentPasswordManagerDriverFactory::CreateForWebContents(web_contents, this,
1202                                                             autofill_client);
1203   driver_factory_ =
1204       ContentPasswordManagerDriverFactory::FromWebContents(web_contents);
1205   log_manager_ = autofill::LogManager::Create(
1206       password_manager::PasswordManagerLogRouterFactory::GetForBrowserContext(
1207           profile_),
1208       base::BindRepeating(
1209           &ContentPasswordManagerDriverFactory::RequestSendLoggingAvailability,
1210           base::Unretained(driver_factory_)));
1211 
1212   saving_passwords_enabled_.Init(
1213       password_manager::prefs::kCredentialsEnableService, GetPrefs());
1214   static base::NoDestructor<password_manager::StoreMetricsReporter> reporter(
1215       this, GetSyncService(profile_), GetIdentityManager(), GetPrefs());
1216   driver_factory_->RequestSendLoggingAvailability();
1217 
1218   auto* autofill_assistant_manager =
1219       autofill_assistant::RuntimeManager::GetOrCreateForWebContents(
1220           web_contents);
1221   autofill_assistant_manager->AddObserver(this);
1222 
1223 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
1224   // TODO(https://crbug.com/1104919): Remove this logging.
1225   VLOG(1) << __FUNCTION__ << ": this: " << this;
1226   VLOG(1) << "wc: " << web_contents;
1227   VLOG(1) << "wc->GetRenderViewHost(): "
1228           << web_contents->GetMainFrame()->GetRenderViewHost();
1229 #endif
1230 }
1231 
DidStartNavigation(content::NavigationHandle * navigation_handle)1232 void ChromePasswordManagerClient::DidStartNavigation(
1233     content::NavigationHandle* navigation_handle) {
1234   // Logging has no sense on WebUI sites.
1235   log_manager_->SetSuspended(web_contents()->GetWebUI() != nullptr);
1236 }
1237 
DidFinishNavigation(content::NavigationHandle * navigation_handle)1238 void ChromePasswordManagerClient::DidFinishNavigation(
1239     content::NavigationHandle* navigation_handle) {
1240   if (!navigation_handle->IsInMainFrame() ||
1241       navigation_handle->IsSameDocument() ||
1242       !navigation_handle->HasCommitted()) {
1243     return;
1244   }
1245 
1246   // Send any collected metrics by destroying the metrics recorder.
1247   metrics_recorder_.reset();
1248 
1249   httpauth_manager_.OnDidFinishMainFrameNavigation();
1250 
1251   // From this point on, the ContentCredentialManager will service API calls in
1252   // the context of the new WebContents::GetLastCommittedURL, which may very
1253   // well be cross-origin. Disconnect existing client, and drop pending
1254   // requests.
1255   content_credential_manager_.DisconnectBinding();
1256 
1257 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
1258   password_reuse_detection_manager_.DidNavigateMainFrame(GetLastCommittedURL());
1259 #endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
1260 
1261 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
1262   // TODO(https://crbug.com/1104919): Remove this logging.
1263   VLOG(1) << __FUNCTION__ << ": this: " << this;
1264   VLOG(1) << "wc: " << web_contents();
1265   VLOG(1) << "wc->GetRenderViewHost(): "
1266           << web_contents()->GetMainFrame()->GetRenderViewHost();
1267 #endif
1268   AddToWidgetInputEventObservers(
1269       web_contents()->GetMainFrame()->GetRenderViewHost()->GetWidget(), this);
1270 #if defined(OS_ANDROID)
1271   // This unblacklisted info is only used after form submission to determine
1272   // whether to record PasswordManager.SaveUIDismissalReasonAfterUnblacklisting.
1273   // Therefore it is sufficient to save it only once on navigation and not
1274   // every time the user changes the UI toggle.
1275   password_manager_.MarkWasUnblacklistedInFormManagers(&credential_cache_);
1276   credential_cache_.ClearCredentials();
1277 #endif  // defined(OS_ANDROID)
1278 
1279   // Hide form filling UI on navigating away.
1280   HideFillingUI();
1281 }
1282 
WebContentsDestroyed()1283 void ChromePasswordManagerClient::WebContentsDestroyed() {
1284   // crbug/1090011
1285   // Drop the connection before the WebContentsObserver destructors are invoked.
1286   // Other classes may contain callbacks to the Mojo methods. Those callbacks
1287   // don't like to be destroyed earlier than the pipe itself.
1288   content_credential_manager_.DisconnectBinding();
1289 
1290   DCHECK(web_contents()->GetMainFrame()->GetRenderViewHost());
1291 
1292 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
1293   // TODO(https://crbug.com/1104919): Remove this logging.
1294   VLOG(1) << __FUNCTION__ << ": this: " << this;
1295   VLOG(1) << "wc: " << web_contents();
1296   VLOG(1) << "wc->GetRenderViewHost(): "
1297           << web_contents()->GetMainFrame()->GetRenderViewHost();
1298 #endif
1299   MaybeRemoveFromWidgetInputEventObservers(
1300       web_contents()->GetMainFrame()->GetRenderViewHost()->GetWidget(), this);
1301 
1302   auto* autofill_assistant_manager =
1303       autofill_assistant::RuntimeManager::GetForWebContents(web_contents());
1304   if (autofill_assistant_manager) {
1305     autofill_assistant_manager->RemoveObserver(this);
1306   }
1307 }
1308 
1309 #if !defined(OS_ANDROID)
OnPaste()1310 void ChromePasswordManagerClient::OnPaste() {
1311 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
1312   // TODO(https://crbug.com/1104919): Remove this logging.
1313   VLOG(1) << __FUNCTION__ << ": this: " << this;
1314   VLOG(1) << "wc: " << web_contents();
1315   VLOG(1) << "wc->GetRenderViewHost(): "
1316           << web_contents()->GetMainFrame()->GetRenderViewHost();
1317 #endif
1318 
1319   ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
1320   base::string16 text;
1321   // Given that this clipboard data read happens in the background and not
1322   // initiated by a user gesture, then the user shouldn't see a notification if
1323   // the clipboard is restricted by the rules of data leak prevention policy.
1324   ui::DataTransferEndpoint data_dst = ui::DataTransferEndpoint(
1325       ui::EndpointType::kDefault, /*notify_if_restricted=*/false);
1326   clipboard->ReadText(ui::ClipboardBuffer::kCopyPaste, &data_dst, &text);
1327   was_on_paste_called_ = true;
1328   password_reuse_detection_manager_.OnPaste(std::move(text));
1329 }
1330 #endif
1331 
RenderFrameCreated(content::RenderFrameHost * render_frame_host)1332 void ChromePasswordManagerClient::RenderFrameCreated(
1333     content::RenderFrameHost* render_frame_host) {
1334 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
1335   // TODO(https://crbug.com/1104919): Remove this logging.
1336   VLOG(1) << __FUNCTION__ << ": this: " << this;
1337   VLOG(1) << "rfh: " << render_frame_host;
1338   VLOG(1) << "rfh->GetView(): " << render_frame_host->GetView();
1339 #endif
1340 
1341   // TODO(drubery): We should handle input events on subframes separately, so
1342   // that we can accurately report that the password was reused on a subframe.
1343   // Currently any password reuse for this WebContents will report password
1344   // reuse on the main frame URL.
1345   AddToWidgetInputEventObservers(
1346       render_frame_host->GetView()->GetRenderWidgetHost(), this);
1347 }
1348 
RenderFrameDeleted(content::RenderFrameHost * render_frame_host)1349 void ChromePasswordManagerClient::RenderFrameDeleted(
1350     content::RenderFrameHost* render_frame_host) {
1351 #if !BUILDFLAG(GOOGLE_CHROME_BRANDING)
1352   // TODO(https://crbug.com/1104919): Remove this logging.
1353   VLOG(1) << __FUNCTION__ << ": this: " << this;
1354   VLOG(1) << "rfh: " << render_frame_host;
1355   VLOG(1) << "rfh->GetView(): " << render_frame_host->GetView();
1356 #endif
1357 
1358   if (!render_frame_host->GetView())
1359     return;
1360   MaybeRemoveFromWidgetInputEventObservers(
1361       render_frame_host->GetView()->GetRenderWidgetHost(), this);
1362 }
1363 
OnInputEvent(const blink::WebInputEvent & event)1364 void ChromePasswordManagerClient::OnInputEvent(
1365     const blink::WebInputEvent& event) {
1366 #if defined(OS_ANDROID)
1367 
1368 #if defined(PASSWORD_REUSE_DETECTION_ENABLED)
1369   // On Android, key down events are triggered if a user types in through a
1370   // number bar on Android keyboard. If text is typed in through other parts of
1371   // Android keyboard, ImeTextCommittedEvent is triggered instead.
1372   if (event.GetType() != blink::WebInputEvent::Type::kKeyDown)
1373     return;
1374   const blink::WebKeyboardEvent& key_event =
1375       static_cast<const blink::WebKeyboardEvent&>(event);
1376   password_reuse_detection_manager_.OnKeyPressedCommitted(key_event.text);
1377 #endif  // defined(PASSWORD_REUSE_DETECTION_ENABLED)
1378 
1379 #else   // !defined(OS_ANDROID)
1380   if (event.GetType() != blink::WebInputEvent::Type::kChar)
1381     return;
1382   const blink::WebKeyboardEvent& key_event =
1383       static_cast<const blink::WebKeyboardEvent&>(event);
1384   // Key & 0x1f corresponds to the value of the key when either the control or
1385   // command key is pressed. This detects CTRL+V, COMMAND+V, and CTRL+SHIFT+V.
1386   if (key_event.windows_key_code == (ui::VKEY_V & 0x1f)) {
1387     OnPaste();
1388   } else {
1389     password_reuse_detection_manager_.OnKeyPressedCommitted(key_event.text);
1390   }
1391 #endif  // defined(OS_ANDROID)
1392 }
1393 
GetBoundsInScreenSpace(const gfx::RectF & bounds)1394 gfx::RectF ChromePasswordManagerClient::GetBoundsInScreenSpace(
1395     const gfx::RectF& bounds) {
1396   gfx::Rect client_area = web_contents()->GetContainerBounds();
1397   return bounds + client_area.OffsetFromOrigin();
1398 }
1399 
HideFillingUI()1400 void ChromePasswordManagerClient::HideFillingUI() {
1401 #if defined(OS_ANDROID)
1402   base::WeakPtr<ManualFillingController> mf_controller =
1403       ManualFillingController::Get(web_contents());
1404   // Hides all the manual filling UI if the controller already exists.
1405   if (mf_controller)
1406     mf_controller->Hide();
1407 #endif  // defined(OS_ANDROID)
1408 }
1409 
IsPasswordManagementEnabledForCurrentPage(const GURL & url) const1410 bool ChromePasswordManagerClient::IsPasswordManagementEnabledForCurrentPage(
1411     const GURL& url) const {
1412   bool is_enabled = CanShowBubbleOnURL(url);
1413 
1414   // The password manager is disabled while VR (virtual reality) is being used,
1415   // as the use of conventional UI elements might harm the user experience in
1416   // VR.
1417   if (vr::VrTabHelper::IsUiSuppressedInVr(
1418           web_contents(), vr::UiSuppressedElement::kPasswordManager)) {
1419     is_enabled = false;
1420   }
1421 
1422   // The password manager is disabled on Google Password Manager page.
1423   if (url.GetOrigin() ==
1424       GURL(password_manager::kPasswordManagerAccountDashboardURL)) {
1425     is_enabled = false;
1426   }
1427 
1428   // SafeBrowsing Delayed Warnings experiment can delay some SafeBrowsing
1429   // warnings until user interaction. If the current page has a delayed warning,
1430   // it'll have a user interaction observer attached. Disable password
1431   // management in that case.
1432   if (auto* observer =
1433           safe_browsing::SafeBrowsingUserInteractionObserver::FromWebContents(
1434               web_contents())) {
1435     observer->OnPasswordSaveOrAutofillDenied();
1436     is_enabled = false;
1437   }
1438 
1439   if (log_manager_->IsLoggingActive()) {
1440     password_manager::BrowserSavePasswordProgressLogger logger(
1441         log_manager_.get());
1442     logger.LogURL(Logger::STRING_SECURITY_ORIGIN, url);
1443     logger.LogBoolean(
1444         Logger::STRING_PASSWORD_MANAGEMENT_ENABLED_FOR_CURRENT_PAGE,
1445         is_enabled);
1446   }
1447   return is_enabled;
1448 }
1449 
1450 // static
ShouldAnnotateNavigationEntries(Profile * profile)1451 bool ChromePasswordManagerClient::ShouldAnnotateNavigationEntries(
1452     Profile* profile) {
1453   // Only annotate PasswordState onto the navigation entry if user is
1454   // opted into UMA and they're not syncing w/ a custom passphrase.
1455   if (!ChromeMetricsServiceAccessor::IsMetricsAndCrashReportingEnabled())
1456     return false;
1457 
1458   syncer::SyncService* sync_service =
1459       ProfileSyncServiceFactory::GetForProfile(profile);
1460   if (!sync_service || !sync_service->IsSyncFeatureActive() ||
1461       sync_service->GetUserSettings()->IsUsingSecondaryPassphrase()) {
1462     return false;
1463   }
1464 
1465   return true;
1466 }
1467 
GenerationResultAvailable(PasswordGenerationType type,base::WeakPtr<password_manager::ContentPasswordManagerDriver> driver,const base::Optional<autofill::password_generation::PasswordGenerationUIData> & ui_data)1468 void ChromePasswordManagerClient::GenerationResultAvailable(
1469     PasswordGenerationType type,
1470     base::WeakPtr<password_manager::ContentPasswordManagerDriver> driver,
1471     const base::Optional<
1472         autofill::password_generation::PasswordGenerationUIData>& ui_data) {
1473   if (!ui_data || !driver)
1474     return;
1475   // Check the data because it's a Mojo callback and the input isn't trusted.
1476   if (!password_manager::bad_message::CheckChildProcessSecurityPolicyForURL(
1477           driver->render_frame_host(), ui_data->form_data.url,
1478           BadMessageReason::
1479               CPMD_BAD_ORIGIN_SHOW_MANUAL_PASSWORD_GENERATION_POPUP))
1480     return;
1481 #if defined(OS_ANDROID)
1482   PasswordGenerationController* password_generation_controller =
1483       PasswordGenerationController::GetIfExisting(web_contents());
1484   DCHECK(password_generation_controller);
1485 
1486   password_generation_controller->ShowManualGenerationDialog(driver.get(),
1487                                                              ui_data.value());
1488 #else
1489   ShowPasswordGenerationPopup(type, driver.get(), *ui_data);
1490 #endif
1491 }
1492 
ShowPasswordGenerationPopup(PasswordGenerationType type,password_manager::ContentPasswordManagerDriver * driver,const autofill::password_generation::PasswordGenerationUIData & ui_data)1493 void ChromePasswordManagerClient::ShowPasswordGenerationPopup(
1494     PasswordGenerationType type,
1495     password_manager::ContentPasswordManagerDriver* driver,
1496     const autofill::password_generation::PasswordGenerationUIData& ui_data) {
1497   gfx::RectF element_bounds_in_top_frame_space =
1498       TransformToRootCoordinates(driver->render_frame_host(), ui_data.bounds);
1499 
1500   gfx::RectF element_bounds_in_screen_space =
1501       GetBoundsInScreenSpace(element_bounds_in_top_frame_space);
1502   password_manager_.SetGenerationElementAndTypeForForm(
1503       driver, ui_data.form_data, ui_data.generation_element_id, type);
1504 
1505   popup_controller_ = PasswordGenerationPopupControllerImpl::GetOrCreate(
1506       popup_controller_, element_bounds_in_screen_space, ui_data,
1507       driver->AsWeakPtr(), observer_, web_contents(),
1508       driver->render_frame_host());
1509   popup_controller_->Show(PasswordGenerationPopupController::kOfferGeneration);
1510 }
1511 
TransformToRootCoordinates(content::RenderFrameHost * frame_host,const gfx::RectF & bounds_in_frame_coordinates)1512 gfx::RectF ChromePasswordManagerClient::TransformToRootCoordinates(
1513     content::RenderFrameHost* frame_host,
1514     const gfx::RectF& bounds_in_frame_coordinates) {
1515   content::RenderWidgetHostView* rwhv = frame_host->GetView();
1516   if (!rwhv)
1517     return bounds_in_frame_coordinates;
1518   return gfx::RectF(rwhv->TransformPointToRootCoordSpaceF(
1519                         bounds_in_frame_coordinates.origin()),
1520                     bounds_in_frame_coordinates.size());
1521 }
1522 
OnStateChanged(autofill_assistant::UIState state)1523 void ChromePasswordManagerClient::OnStateChanged(
1524     autofill_assistant::UIState state) {
1525   if (state == autofill_assistant::UIState::kNotShown)
1526     password_manager_.ResetPendingCredentials();
1527 }
1528 
1529 WEB_CONTENTS_USER_DATA_KEY_IMPL(ChromePasswordManagerClient)
1530