Home | History | Annotate | Download | only in autofill
      1 // Copyright (c) 2012 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/tab_autofill_manager_delegate.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/prefs/pref_service.h"
      9 #include "chrome/browser/autofill/autocheckout_whitelist_manager_factory.h"
     10 #include "chrome/browser/autofill/autofill_cc_infobar_delegate.h"
     11 #include "chrome/browser/autofill/personal_data_manager_factory.h"
     12 #include "chrome/browser/infobars/infobar_service.h"
     13 #include "chrome/browser/profiles/profile.h"
     14 #include "chrome/browser/ui/autofill/autocheckout_bubble.h"
     15 #include "chrome/browser/ui/autofill/autocheckout_bubble_controller.h"
     16 #include "chrome/browser/ui/autofill/autofill_dialog_controller.h"
     17 #include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h"
     18 #include "chrome/browser/ui/browser.h"
     19 #include "chrome/browser/ui/browser_finder.h"
     20 #include "chrome/browser/ui/browser_window.h"
     21 #include "chrome/browser/ui/chrome_pages.h"
     22 #include "chrome/browser/ui/tabs/tab_strip_model_observer.h"
     23 #include "chrome/common/url_constants.h"
     24 #include "components/autofill/content/browser/autofill_driver_impl.h"
     25 #include "components/autofill/core/common/autofill_messages.h"
     26 #include "components/autofill/core/common/autofill_pref_names.h"
     27 #include "content/public/browser/navigation_details.h"
     28 #include "content/public/browser/navigation_entry.h"
     29 #include "content/public/browser/render_view_host.h"
     30 #include "content/public/browser/web_contents_view.h"
     31 #include "ui/gfx/rect.h"
     32 
     33 DEFINE_WEB_CONTENTS_USER_DATA_KEY(autofill::TabAutofillManagerDelegate);
     34 
     35 namespace autofill {
     36 
     37 TabAutofillManagerDelegate::TabAutofillManagerDelegate(
     38     content::WebContents* web_contents)
     39     : content::WebContentsObserver(web_contents),
     40       web_contents_(web_contents) {
     41   DCHECK(web_contents);
     42 }
     43 
     44 TabAutofillManagerDelegate::~TabAutofillManagerDelegate() {
     45   // NOTE: It is too late to clean up the autofill popup; that cleanup process
     46   // requires that the WebContents instance still be valid and it is not at
     47   // this point (in particular, the WebContentsImpl destructor has already
     48   // finished running and we are now in the base class destructor).
     49   DCHECK(!popup_controller_);
     50 }
     51 
     52 void TabAutofillManagerDelegate::TabActivated(int reason) {
     53   if (reason != TabStripModelObserver::CHANGE_REASON_USER_GESTURE)
     54     return;
     55 
     56   if (dialog_controller_.get())
     57     dialog_controller_->TabActivated();
     58 }
     59 
     60 PersonalDataManager* TabAutofillManagerDelegate::GetPersonalDataManager() {
     61   Profile* profile =
     62       Profile::FromBrowserContext(web_contents_->GetBrowserContext());
     63   return PersonalDataManagerFactory::GetForProfile(
     64       profile->GetOriginalProfile());
     65 }
     66 
     67 PrefService* TabAutofillManagerDelegate::GetPrefs() {
     68   return Profile::FromBrowserContext(web_contents_->GetBrowserContext())->
     69       GetPrefs();
     70 }
     71 
     72 autocheckout::WhitelistManager*
     73 TabAutofillManagerDelegate::GetAutocheckoutWhitelistManager() const {
     74   Profile* profile =
     75       Profile::FromBrowserContext(web_contents_->GetBrowserContext());
     76   return autocheckout::WhitelistManagerFactory::GetForProfile(
     77       profile->GetOriginalProfile());
     78 }
     79 
     80 void TabAutofillManagerDelegate::OnAutocheckoutError() {
     81   // |dialog_controller_| is a WeakPtr, but we require it to be present when
     82   // |OnAutocheckoutError| is called, so we intentionally do not do NULL check.
     83   dialog_controller_->OnAutocheckoutError();
     84 }
     85 
     86 void TabAutofillManagerDelegate::OnAutocheckoutSuccess() {
     87   dialog_controller_->OnAutocheckoutSuccess();
     88 }
     89 
     90 void TabAutofillManagerDelegate::ShowAutofillSettings() {
     91 #if defined(OS_ANDROID)
     92   NOTIMPLEMENTED();
     93 #else
     94   Browser* browser = chrome::FindBrowserWithWebContents(web_contents_);
     95   if (browser)
     96     chrome::ShowSettingsSubPage(browser, chrome::kAutofillSubPage);
     97 #endif  // #if defined(OS_ANDROID)
     98 }
     99 
    100 void TabAutofillManagerDelegate::ConfirmSaveCreditCard(
    101     const AutofillMetrics& metric_logger,
    102     const CreditCard& credit_card,
    103     const base::Closure& save_card_callback) {
    104   InfoBarService* infobar_service =
    105       InfoBarService::FromWebContents(web_contents_);
    106   AutofillCCInfoBarDelegate::Create(
    107       infobar_service, &metric_logger, save_card_callback);
    108 }
    109 
    110 bool TabAutofillManagerDelegate::ShowAutocheckoutBubble(
    111     const gfx::RectF& bounding_box,
    112     bool is_google_user,
    113     const base::Callback<void(AutocheckoutBubbleState)>& callback) {
    114 #if !defined(TOOLKIT_VIEWS)
    115   callback.Run(AUTOCHECKOUT_BUBBLE_CANCELED);
    116   NOTIMPLEMENTED();
    117   return false;
    118 #else
    119   HideAutocheckoutBubble();
    120 
    121   // Convert |bounding_box| to be in screen space.
    122   gfx::Rect container_rect;
    123   web_contents_->GetView()->GetContainerBounds(&container_rect);
    124   gfx::RectF anchor = bounding_box + container_rect.OffsetFromOrigin();
    125 
    126   autocheckout_bubble_ =
    127       AutocheckoutBubble::Create(scoped_ptr<AutocheckoutBubbleController>(
    128           new AutocheckoutBubbleController(
    129               anchor,
    130               web_contents_->GetView()->GetTopLevelNativeWindow(),
    131               is_google_user,
    132               callback)));
    133 
    134   if (!autocheckout_bubble_)
    135     return false;
    136 
    137   autocheckout_bubble_->ShowBubble();
    138   return true;
    139 #endif  // #if !defined(TOOLKIT_VIEWS)
    140 }
    141 
    142 void TabAutofillManagerDelegate::HideAutocheckoutBubble() {
    143   if (autocheckout_bubble_.get())
    144     autocheckout_bubble_->HideBubble();
    145 }
    146 
    147 void TabAutofillManagerDelegate::ShowRequestAutocompleteDialog(
    148     const FormData& form,
    149     const GURL& source_url,
    150     DialogType dialog_type,
    151     const base::Callback<void(const FormStructure*,
    152                               const std::string&)>& callback) {
    153   HideRequestAutocompleteDialog();
    154 
    155   dialog_controller_ = AutofillDialogController::Create(web_contents_,
    156                                                         form,
    157                                                         source_url,
    158                                                         dialog_type,
    159                                                         callback);
    160   if (dialog_controller_) {
    161     dialog_controller_->Show();
    162   } else {
    163     callback.Run(NULL, std::string());
    164     NOTIMPLEMENTED();
    165   }
    166 }
    167 
    168 void TabAutofillManagerDelegate::ShowAutofillPopup(
    169     const gfx::RectF& element_bounds,
    170     base::i18n::TextDirection text_direction,
    171     const std::vector<string16>& values,
    172     const std::vector<string16>& labels,
    173     const std::vector<string16>& icons,
    174     const std::vector<int>& identifiers,
    175     base::WeakPtr<AutofillPopupDelegate> delegate) {
    176   // Convert element_bounds to be in screen space.
    177   gfx::Rect client_area;
    178   web_contents_->GetView()->GetContainerBounds(&client_area);
    179   gfx::RectF element_bounds_in_screen_space =
    180       element_bounds + client_area.OffsetFromOrigin();
    181 
    182   // Will delete or reuse the old |popup_controller_|.
    183   popup_controller_ = AutofillPopupControllerImpl::GetOrCreate(
    184       popup_controller_,
    185       delegate,
    186       web_contents()->GetView()->GetNativeView(),
    187       element_bounds_in_screen_space,
    188       text_direction);
    189 
    190   popup_controller_->Show(values, labels, icons, identifiers);
    191 }
    192 
    193 void TabAutofillManagerDelegate::UpdateAutofillPopupDataListValues(
    194     const std::vector<base::string16>& values,
    195     const std::vector<base::string16>& labels) {
    196   if (popup_controller_.get())
    197     popup_controller_->UpdateDataListValues(values, labels);
    198 }
    199 
    200 void TabAutofillManagerDelegate::HideAutofillPopup() {
    201   if (popup_controller_.get())
    202     popup_controller_->Hide();
    203 }
    204 
    205 void TabAutofillManagerDelegate::AddAutocheckoutStep(
    206     AutocheckoutStepType step_type) {
    207   dialog_controller_->AddAutocheckoutStep(step_type);
    208 }
    209 
    210 void TabAutofillManagerDelegate::UpdateAutocheckoutStep(
    211     AutocheckoutStepType step_type,
    212     AutocheckoutStepStatus step_status) {
    213   dialog_controller_->UpdateAutocheckoutStep(step_type, step_status);
    214 }
    215 
    216 bool TabAutofillManagerDelegate::IsAutocompleteEnabled() {
    217   // For browser, Autocomplete is always enabled as part of Autofill.
    218   return GetPrefs()->GetBoolean(prefs::kAutofillEnabled);
    219 }
    220 
    221 void TabAutofillManagerDelegate::HideRequestAutocompleteDialog() {
    222   if (dialog_controller_.get())
    223     dialog_controller_->Hide();
    224 }
    225 
    226 void TabAutofillManagerDelegate::WasShown() {
    227   content::RenderViewHost* host = web_contents()->GetRenderViewHost();
    228   if (!host)
    229     return;
    230   host->Send(new AutofillMsg_PageShown(host->GetRoutingID()));
    231 }
    232 
    233 void TabAutofillManagerDelegate::DidNavigateMainFrame(
    234     const content::LoadCommittedDetails& details,
    235     const content::FrameNavigateParams& params) {
    236 
    237   HideAutocheckoutBubble();
    238 
    239   if (!dialog_controller_.get())
    240     return;
    241 
    242   // A redirect immediately after a successful Autocheckout flow shouldn't hide
    243   // the dialog.
    244   bool preserve_dialog = AutofillDriverImpl::FromWebContents(web_contents())->
    245       autofill_manager()->autocheckout_manager()->should_preserve_dialog();
    246   bool was_redirect = details.entry &&
    247       content::PageTransitionIsRedirect(details.entry->GetTransitionType());
    248 
    249   if (dialog_controller_->GetDialogType() == DIALOG_TYPE_REQUEST_AUTOCOMPLETE ||
    250       (!was_redirect && !preserve_dialog)) {
    251     HideRequestAutocompleteDialog();
    252   }
    253 }
    254 
    255 void TabAutofillManagerDelegate::WebContentsDestroyed(
    256     content::WebContents* web_contents) {
    257   HideAutofillPopup();
    258 }
    259 
    260 }  // namespace autofill
    261