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/ui/autofill/chrome_autofill_client.h"
6
7#include "base/logging.h"
8#include "base/prefs/pref_service.h"
9#include "chrome/browser/autofill/autofill_cc_infobar_delegate.h"
10#include "chrome/browser/autofill/personal_data_manager_factory.h"
11#include "chrome/browser/infobars/infobar_service.h"
12#include "chrome/browser/password_manager/chrome_password_manager_client.h"
13#include "chrome/browser/profiles/profile.h"
14#include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
15#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
16#include "chrome/browser/ui/browser.h"
17#include "chrome/browser/ui/browser_finder.h"
18#include "chrome/browser/ui/browser_window.h"
19#include "chrome/browser/ui/chrome_pages.h"
20#include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
21#include "chrome/browser/ui/zoom/zoom_controller.h"
22#include "chrome/browser/webdata/web_data_service_factory.h"
23#include "chrome/common/url_constants.h"
24#include "components/autofill/content/browser/content_autofill_driver.h"
25#include "components/autofill/content/common/autofill_messages.h"
26#include "components/autofill/core/common/autofill_pref_names.h"
27#include "content/public/browser/render_view_host.h"
28#include "ui/gfx/rect.h"
29
30#if defined(OS_ANDROID)
31#include "chrome/browser/android/chromium_application.h"
32#include "chrome/browser/ui/android/autofill/autofill_logger_android.h"
33#endif
34
35DEFINE_WEB_CONTENTS_USER_DATA_KEY(autofill::ChromeAutofillClient);
36
37namespace autofill {
38
39ChromeAutofillClient::ChromeAutofillClient(content::WebContents* web_contents)
40    : content::WebContentsObserver(web_contents), web_contents_(web_contents) {
41  DCHECK(web_contents);
42  // Since ZoomController is also a WebContentsObserver, we need to be careful
43  // about disconnecting from it since the relative order of destruction of
44  // WebContentsObservers is not guaranteed. ZoomController silently clears
45  // its ZoomObserver list during WebContentsDestroyed() so there's no need
46  // to explicitly remove ourselves on destruction.
47  ZoomController* zoom_controller =
48      ZoomController::FromWebContents(web_contents);
49  // There may not always be a ZoomController, e.g. on Android.
50  if (zoom_controller)
51    zoom_controller->AddObserver(this);
52#if defined(OS_MACOSX) && !defined(OS_IOS)
53  RegisterForKeystoneNotifications();
54#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
55}
56
57ChromeAutofillClient::~ChromeAutofillClient() {
58  // NOTE: It is too late to clean up the autofill popup; that cleanup process
59  // requires that the WebContents instance still be valid and it is not at
60  // this point (in particular, the WebContentsImpl destructor has already
61  // finished running and we are now in the base class destructor).
62  DCHECK(!popup_controller_);
63#if defined(OS_MACOSX) && !defined(OS_IOS)
64  UnregisterFromKeystoneNotifications();
65#endif  // defined(OS_MACOSX) && !defined(OS_IOS)
66}
67
68void ChromeAutofillClient::TabActivated() {
69  if (dialog_controller_.get())
70    dialog_controller_->TabActivated();
71}
72
73PersonalDataManager* ChromeAutofillClient::GetPersonalDataManager() {
74  Profile* profile =
75      Profile::FromBrowserContext(web_contents_->GetBrowserContext());
76  return PersonalDataManagerFactory::GetForProfile(
77      profile->GetOriginalProfile());
78}
79
80scoped_refptr<AutofillWebDataService> ChromeAutofillClient::GetDatabase() {
81  Profile* profile =
82      Profile::FromBrowserContext(web_contents_->GetBrowserContext());
83  return WebDataServiceFactory::GetAutofillWebDataForProfile(
84      profile, Profile::EXPLICIT_ACCESS);
85}
86
87PrefService* ChromeAutofillClient::GetPrefs() {
88  return Profile::FromBrowserContext(web_contents_->GetBrowserContext())
89      ->GetPrefs();
90}
91
92void ChromeAutofillClient::ShowAutofillSettings() {
93#if defined(OS_ANDROID)
94  chrome::android::ChromiumApplication::ShowAutofillSettings();
95#else
96  Browser* browser = chrome::FindBrowserWithWebContents(web_contents_);
97  if (browser)
98    chrome::ShowSettingsSubPage(browser, chrome::kAutofillSubPage);
99#endif  // #if defined(OS_ANDROID)
100}
101
102void ChromeAutofillClient::ConfirmSaveCreditCard(
103    const AutofillMetrics& metric_logger,
104    const base::Closure& save_card_callback) {
105  InfoBarService* infobar_service =
106      InfoBarService::FromWebContents(web_contents_);
107  AutofillCCInfoBarDelegate::Create(
108      infobar_service, &metric_logger, save_card_callback);
109}
110
111void ChromeAutofillClient::ShowRequestAutocompleteDialog(
112    const FormData& form,
113    const GURL& source_url,
114    const ResultCallback& callback) {
115  HideRequestAutocompleteDialog();
116
117  dialog_controller_ = AutofillDialogController::Create(
118      web_contents_, form, source_url, callback);
119  if (dialog_controller_) {
120    dialog_controller_->Show();
121  } else {
122    callback.Run(AutofillClient::AutocompleteResultErrorDisabled,
123                 base::string16(),
124                 NULL);
125    NOTIMPLEMENTED();
126  }
127}
128
129void ChromeAutofillClient::ShowAutofillPopup(
130    const gfx::RectF& element_bounds,
131    base::i18n::TextDirection text_direction,
132    const std::vector<base::string16>& values,
133    const std::vector<base::string16>& labels,
134    const std::vector<base::string16>& icons,
135    const std::vector<int>& identifiers,
136    base::WeakPtr<AutofillPopupDelegate> delegate) {
137  // Convert element_bounds to be in screen space.
138  gfx::Rect client_area = web_contents_->GetContainerBounds();
139  gfx::RectF element_bounds_in_screen_space =
140      element_bounds + client_area.OffsetFromOrigin();
141
142  // Will delete or reuse the old |popup_controller_|.
143  popup_controller_ =
144      AutofillPopupControllerImpl::GetOrCreate(popup_controller_,
145                                               delegate,
146                                               web_contents(),
147                                               web_contents()->GetNativeView(),
148                                               element_bounds_in_screen_space,
149                                               text_direction);
150
151  popup_controller_->Show(values, labels, icons, identifiers);
152}
153
154void ChromeAutofillClient::UpdateAutofillPopupDataListValues(
155    const std::vector<base::string16>& values,
156    const std::vector<base::string16>& labels) {
157  if (popup_controller_.get())
158    popup_controller_->UpdateDataListValues(values, labels);
159}
160
161void ChromeAutofillClient::HideAutofillPopup() {
162  if (popup_controller_.get())
163    popup_controller_->Hide();
164
165  // Password generation popups behave in the same fashion and should also
166  // be hidden.
167  ChromePasswordManagerClient* password_client =
168      ChromePasswordManagerClient::FromWebContents(web_contents_);
169  if (password_client)
170    password_client->HidePasswordGenerationPopup();
171}
172
173bool ChromeAutofillClient::IsAutocompleteEnabled() {
174  // For browser, Autocomplete is always enabled as part of Autofill.
175  return GetPrefs()->GetBoolean(prefs::kAutofillEnabled);
176}
177
178void ChromeAutofillClient::HideRequestAutocompleteDialog() {
179  if (dialog_controller_.get())
180    dialog_controller_->Hide();
181}
182
183void ChromeAutofillClient::WebContentsDestroyed() {
184  HideAutofillPopup();
185}
186
187void ChromeAutofillClient::OnZoomChanged(
188    const ZoomController::ZoomChangedEventData& data) {
189  HideAutofillPopup();
190}
191
192void ChromeAutofillClient::DetectAccountCreationForms(
193    const std::vector<autofill::FormStructure*>& forms) {
194  password_manager::PasswordGenerationManager* manager =
195      ChromePasswordManagerClient::GetGenerationManagerFromWebContents(
196          web_contents_);
197  if (manager)
198    manager->DetectAccountCreationForms(forms);
199}
200
201void ChromeAutofillClient::DidFillOrPreviewField(
202    const base::string16& autofilled_value,
203    const base::string16& profile_full_name) {
204#if defined(OS_ANDROID)
205  AutofillLoggerAndroid::DidFillOrPreviewField(autofilled_value,
206                                               profile_full_name);
207#endif  // defined(OS_ANDROID)
208}
209
210}  // namespace autofill
211