// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "components/autofill/core/browser/autofill_manager.h"

#include <stddef.h>

#include <limits>
#include <map>
#include <set>
#include <utility>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/guid.h"
#include "base/logging.h"
#include "base/prefs/pref_service.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/sequenced_worker_pool.h"
#include "components/autofill/content/browser/autocheckout/whitelist_manager.h"
#include "components/autofill/content/browser/autocheckout_manager.h"
#include "components/autofill/core/browser/autocomplete_history_manager.h"
#include "components/autofill/core/browser/autofill_data_model.h"
#include "components/autofill/core/browser/autofill_driver.h"
#include "components/autofill/core/browser/autofill_external_delegate.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_manager_delegate.h"
#include "components/autofill/core/browser/autofill_manager_test_delegate.h"
#include "components/autofill/core/browser/autofill_metrics.h"
#include "components/autofill/core/browser/autofill_profile.h"
#include "components/autofill/core/browser/autofill_type.h"
#include "components/autofill/core/browser/credit_card.h"
#include "components/autofill/core/browser/form_structure.h"
#include "components/autofill/core/browser/personal_data_manager.h"
#include "components/autofill/core/browser/phone_number.h"
#include "components/autofill/core/browser/phone_number_i18n.h"
#include "components/autofill/core/common/autofill_messages.h"
#include "components/autofill/core/common/autofill_pref_names.h"
#include "components/autofill/core/common/autofill_switches.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_data_predictions.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/password_form_fill_data.h"
#include "components/user_prefs/pref_registry_syncable.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "content/public/common/url_constants.h"
#include "grit/component_strings.h"
#include "third_party/WebKit/public/web/WebAutofillClient.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/rect.h"
#include "url/gurl.h"

namespace autofill {

typedef PersonalDataManager::GUIDPair GUIDPair;

using base::TimeTicks;
using content::BrowserThread;
using content::RenderViewHost;
using WebKit::WebFormElement;

namespace {

// We only send a fraction of the forms to upload server.
// The rate for positive/negative matches potentially could be different.
const double kAutofillPositiveUploadRateDefaultValue = 0.20;
const double kAutofillNegativeUploadRateDefaultValue = 0.20;

const size_t kMaxRecentFormSignaturesToRemember = 3;

// Set a conservative upper bound on the number of forms we are willing to
// cache, simply to prevent unbounded memory consumption.
const size_t kMaxFormCacheSize = 100;

// Removes duplicate suggestions whilst preserving their original order.
void RemoveDuplicateSuggestions(std::vector<base::string16>* values,
                                std::vector<base::string16>* labels,
                                std::vector<base::string16>* icons,
                                std::vector<int>* unique_ids) {
  DCHECK_EQ(values->size(), labels->size());
  DCHECK_EQ(values->size(), icons->size());
  DCHECK_EQ(values->size(), unique_ids->size());

  std::set<std::pair<base::string16, base::string16> > seen_suggestions;
  std::vector<base::string16> values_copy;
  std::vector<base::string16> labels_copy;
  std::vector<base::string16> icons_copy;
  std::vector<int> unique_ids_copy;

  for (size_t i = 0; i < values->size(); ++i) {
    const std::pair<base::string16, base::string16> suggestion(
        (*values)[i], (*labels)[i]);
    if (seen_suggestions.insert(suggestion).second) {
      values_copy.push_back((*values)[i]);
      labels_copy.push_back((*labels)[i]);
      icons_copy.push_back((*icons)[i]);
      unique_ids_copy.push_back((*unique_ids)[i]);
    }
  }

  values->swap(values_copy);
  labels->swap(labels_copy);
  icons->swap(icons_copy);
  unique_ids->swap(unique_ids_copy);
}

// Precondition: |form_structure| and |form| should correspond to the same
// logical form.  Returns true if any field in the given |section| within |form|
// is auto-filled.
bool SectionIsAutofilled(const FormStructure& form_structure,
                         const FormData& form,
                         const std::string& section) {
  DCHECK_EQ(form_structure.field_count(), form.fields.size());
  for (size_t i = 0; i < form_structure.field_count(); ++i) {
    if (form_structure.field(i)->section() == section &&
        form.fields[i].is_autofilled) {
      return true;
    }
  }

  return false;
}

bool FormIsHTTPS(const FormStructure& form) {
  return form.source_url().SchemeIs(chrome::kHttpsScheme);
}

// Uses the existing personal data in |profiles| and |credit_cards| to determine
// possible field types for the |submitted_form|.  This is potentially
// expensive -- on the order of 50ms even for a small set of |stored_data|.
// Hence, it should not run on the UI thread -- to avoid locking up the UI --
// nor on the IO thread -- to avoid blocking IPC calls.
void DeterminePossibleFieldTypesForUpload(
    const std::vector<AutofillProfile>& profiles,
    const std::vector<CreditCard>& credit_cards,
    const std::string& app_locale,
    FormStructure* submitted_form) {
  DCHECK(BrowserThread::GetBlockingPool()->RunsTasksOnCurrentThread());

  // For each field in the |submitted_form|, extract the value.  Then for each
  // profile or credit card, identify any stored types that match the value.
  for (size_t i = 0; i < submitted_form->field_count(); ++i) {
    AutofillField* field = submitted_form->field(i);
    base::string16 value = CollapseWhitespace(field->value, false);

    ServerFieldTypeSet matching_types;
    for (std::vector<AutofillProfile>::const_iterator it = profiles.begin();
         it != profiles.end(); ++it) {
      it->GetMatchingTypes(value, app_locale, &matching_types);
    }
    for (std::vector<CreditCard>::const_iterator it = credit_cards.begin();
          it != credit_cards.end(); ++it) {
      it->GetMatchingTypes(value, app_locale, &matching_types);
    }

    if (matching_types.empty())
      matching_types.insert(UNKNOWN_TYPE);

    field->set_possible_types(matching_types);
  }
}

// Returns true if server returned known field types to one or more fields in
// this form.
bool HasServerSpecifiedFieldTypes(const FormStructure& form_structure) {
  for (size_t i = 0; i < form_structure.field_count(); ++i) {
    if (form_structure.field(i)->server_type() != NO_SERVER_DATA)
      return true;
  }
  return false;
}

}  // namespace

AutofillManager::AutofillManager(
    AutofillDriver* driver,
    autofill::AutofillManagerDelegate* delegate,
    const std::string& app_locale,
    AutofillDownloadManagerState enable_download_manager)
    : driver_(driver),
      manager_delegate_(delegate),
      app_locale_(app_locale),
      personal_data_(delegate->GetPersonalDataManager()),
      autocomplete_history_manager_(
          new AutocompleteHistoryManager(driver, delegate)),
      autocheckout_manager_(this),
      metric_logger_(new AutofillMetrics),
      has_logged_autofill_enabled_(false),
      has_logged_address_suggestions_count_(false),
      did_show_suggestions_(false),
      user_did_type_(false),
      user_did_autofill_(false),
      user_did_edit_autofilled_field_(false),
      external_delegate_(NULL),
      test_delegate_(NULL),
      weak_ptr_factory_(this) {
  if (enable_download_manager == ENABLE_AUTOFILL_DOWNLOAD_MANAGER) {
    download_manager_.reset(
        new AutofillDownloadManager(
            driver->GetWebContents()->GetBrowserContext(), this));
  }
}

AutofillManager::~AutofillManager() {}

// static
void AutofillManager::RegisterProfilePrefs(
    user_prefs::PrefRegistrySyncable* registry) {
  registry->RegisterBooleanPref(
      prefs::kAutofillEnabled,
      true,
      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
#if defined(OS_MACOSX) || defined(OS_ANDROID)
  registry->RegisterBooleanPref(
      prefs::kAutofillAuxiliaryProfilesEnabled,
      true,
      user_prefs::PrefRegistrySyncable::SYNCABLE_PREF);
#else
  registry->RegisterBooleanPref(
      prefs::kAutofillAuxiliaryProfilesEnabled,
      false,
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
#endif
  registry->RegisterDoublePref(
      prefs::kAutofillPositiveUploadRate,
      kAutofillPositiveUploadRateDefaultValue,
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
  registry->RegisterDoublePref(
      prefs::kAutofillNegativeUploadRate,
      kAutofillNegativeUploadRateDefaultValue,
      user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
}

void AutofillManager::SetExternalDelegate(AutofillExternalDelegate* delegate) {
  // TODO(jrg): consider passing delegate into the ctor.  That won't
  // work if the delegate has a pointer to the AutofillManager, but
  // future directions may not need such a pointer.
  external_delegate_ = delegate;
  autocomplete_history_manager_->SetExternalDelegate(delegate);
}

bool AutofillManager::OnFormSubmitted(const FormData& form,
                                      const TimeTicks& timestamp) {
  // Let Autocomplete know as well.
  autocomplete_history_manager_->OnFormSubmitted(form);

  if (!IsAutofillEnabled())
    return false;

  if (driver_->GetWebContents()->GetBrowserContext()->IsOffTheRecord())
    return false;

  // Don't save data that was submitted through JavaScript.
  if (!form.user_submitted)
    return false;

  // Grab a copy of the form data.
  scoped_ptr<FormStructure> submitted_form(
      new FormStructure(form, GetAutocheckoutURLPrefix()));

  // Disregard forms that we wouldn't ever autofill in the first place.
  if (!submitted_form->ShouldBeParsed(true))
    return false;

  // Ignore forms not present in our cache.  These are typically forms with
  // wonky JavaScript that also makes them not auto-fillable.
  FormStructure* cached_submitted_form;
  if (!FindCachedForm(form, &cached_submitted_form))
    return false;

  submitted_form->UpdateFromCache(*cached_submitted_form);
  // Don't prompt the user to save data entered by Autocheckout.
  if (submitted_form->IsAutofillable(true) &&
      !submitted_form->filled_by_autocheckout())
    ImportFormData(*submitted_form);

  // Only upload server statistics and UMA metrics if at least some local data
  // is available to use as a baseline.
  const std::vector<AutofillProfile*>& profiles = personal_data_->GetProfiles();
  const std::vector<CreditCard*>& credit_cards =
      personal_data_->GetCreditCards();
  if (!profiles.empty() || !credit_cards.empty()) {
    // Copy the profile and credit card data, so that it can be accessed on a
    // separate thread.
    std::vector<AutofillProfile> copied_profiles;
    copied_profiles.reserve(profiles.size());
    for (std::vector<AutofillProfile*>::const_iterator it = profiles.begin();
         it != profiles.end(); ++it) {
      copied_profiles.push_back(**it);
    }

    std::vector<CreditCard> copied_credit_cards;
    copied_credit_cards.reserve(credit_cards.size());
    for (std::vector<CreditCard*>::const_iterator it = credit_cards.begin();
         it != credit_cards.end(); ++it) {
      copied_credit_cards.push_back(**it);
    }

    // Note that ownership of |submitted_form| is passed to the second task,
    // using |base::Owned|.
    FormStructure* raw_submitted_form = submitted_form.get();
    BrowserThread::GetBlockingPool()->PostTaskAndReply(
        FROM_HERE,
        base::Bind(&DeterminePossibleFieldTypesForUpload,
                   copied_profiles,
                   copied_credit_cards,
                   app_locale_,
                   raw_submitted_form),
        base::Bind(&AutofillManager::UploadFormDataAsyncCallback,
                   weak_ptr_factory_.GetWeakPtr(),
                   base::Owned(submitted_form.release()),
                   forms_loaded_timestamp_,
                   initial_interaction_timestamp_,
                   timestamp));
  }

  return true;
}

void AutofillManager::OnFormsSeen(const std::vector<FormData>& forms,
                                  const TimeTicks& timestamp,
                                  autofill::FormsSeenState state) {
  bool is_post_document_load = state == autofill::DYNAMIC_FORMS_SEEN;
  bool has_more_forms = state == autofill::PARTIAL_FORMS_SEEN;
  // If new forms were added dynamically, and the autocheckout manager
  // doesn't tell us to ignore ajax on this page, treat as a new page.
  if (is_post_document_load) {
    if (autocheckout_manager_.ShouldIgnoreAjax())
      return;

    Reset();
  }

  RenderViewHost* host = driver_->GetWebContents()->GetRenderViewHost();
  if (!host)
    return;

  if (!GetAutocheckoutURLPrefix().empty()) {
    // If whitelisted URL, fetch all the forms.
    if (has_more_forms)
      host->Send(new AutofillMsg_GetAllForms(host->GetRoutingID()));
    if (!is_post_document_load) {
      host->Send(
          new AutofillMsg_AutocheckoutSupported(host->GetRoutingID()));
    }
    // Now return early, as OnFormsSeen will get called again with all forms.
    if (has_more_forms)
      return;
  }

  autocheckout_manager_.OnFormsSeen();
  bool enabled = IsAutofillEnabled();
  if (!has_logged_autofill_enabled_) {
    metric_logger_->LogIsAutofillEnabledAtPageLoad(enabled);
    has_logged_autofill_enabled_ = true;
  }

  if (!enabled)
    return;

  forms_loaded_timestamp_ = timestamp;
  ParseForms(forms);
}

void AutofillManager::OnTextFieldDidChange(const FormData& form,
                                           const FormFieldData& field,
                                           const TimeTicks& timestamp) {
  FormStructure* form_structure = NULL;
  AutofillField* autofill_field = NULL;
  if (!GetCachedFormAndField(form, field, &form_structure, &autofill_field))
    return;

  if (!user_did_type_) {
    autocheckout_manager_.set_should_show_bubble(false);
    user_did_type_ = true;
    metric_logger_->LogUserHappinessMetric(AutofillMetrics::USER_DID_TYPE);
  }

  if (autofill_field->is_autofilled) {
    autofill_field->is_autofilled = false;
    metric_logger_->LogUserHappinessMetric(
        AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD);

    if (!user_did_edit_autofilled_field_) {
      user_did_edit_autofilled_field_ = true;
      metric_logger_->LogUserHappinessMetric(
          AutofillMetrics::USER_DID_EDIT_AUTOFILLED_FIELD_ONCE);
    }
  }

  UpdateInitialInteractionTimestamp(timestamp);
}

void AutofillManager::OnQueryFormFieldAutofill(int query_id,
                                               const FormData& form,
                                               const FormFieldData& field,
                                               const gfx::RectF& bounding_box,
                                               bool display_warning) {
  if (autocheckout_manager_.is_autocheckout_bubble_showing())
    return;

  std::vector<base::string16> values;
  std::vector<base::string16> labels;
  std::vector<base::string16> icons;
  std::vector<int> unique_ids;

  external_delegate_->OnQuery(query_id,
                              form,
                              field,
                              bounding_box,
                              display_warning);

  RenderViewHost* host = NULL;
  FormStructure* form_structure = NULL;
  AutofillField* autofill_field = NULL;
  if (GetHost(&host) &&
      GetCachedFormAndField(form, field, &form_structure, &autofill_field) &&
      // Don't send suggestions for forms that aren't auto-fillable.
      form_structure->IsAutofillable(false)) {
    AutofillType type = autofill_field->Type();
    bool is_filling_credit_card = (type.group() == CREDIT_CARD);
    if (is_filling_credit_card) {
      GetCreditCardSuggestions(
          field, type, &values, &labels, &icons, &unique_ids);
    } else {
      GetProfileSuggestions(
          form_structure, field, type, &values, &labels, &icons, &unique_ids);
    }

    DCHECK_EQ(values.size(), labels.size());
    DCHECK_EQ(values.size(), icons.size());
    DCHECK_EQ(values.size(), unique_ids.size());

    if (!values.empty()) {
      // Don't provide Autofill suggestions when Autofill is disabled, and don't
      // provide credit card suggestions for non-HTTPS pages. However, provide a
      // warning to the user in these cases.
      int warning = 0;
      if (!form_structure->IsAutofillable(true))
        warning = IDS_AUTOFILL_WARNING_FORM_DISABLED;
      else if (is_filling_credit_card && !FormIsHTTPS(*form_structure))
        warning = IDS_AUTOFILL_WARNING_INSECURE_CONNECTION;
      if (warning) {
        values.assign(1, l10n_util::GetStringUTF16(warning));
        labels.assign(1, base::string16());
        icons.assign(1, base::string16());
        unique_ids.assign(1,
                          WebKit::WebAutofillClient::MenuItemIDWarningMessage);
      } else {
        bool section_is_autofilled =
            SectionIsAutofilled(*form_structure, form,
                                autofill_field->section());
        if (section_is_autofilled) {
          // If the relevant section is auto-filled and the renderer is querying
          // for suggestions, then the user is editing the value of a field.
          // In this case, mimic autocomplete: don't display labels or icons,
          // as that information is redundant.
          labels.assign(labels.size(), base::string16());
          icons.assign(icons.size(), base::string16());
        }

        // When filling credit card suggestions, the values and labels are
        // typically obfuscated, which makes detecting duplicates hard.  Since
        // duplicates only tend to be a problem when filling address forms
        // anyway, only don't de-dup credit card suggestions.
        if (!is_filling_credit_card)
          RemoveDuplicateSuggestions(&values, &labels, &icons, &unique_ids);

        // The first time we show suggestions on this page, log the number of
        // suggestions shown.
        if (!has_logged_address_suggestions_count_ && !section_is_autofilled) {
          metric_logger_->LogAddressSuggestionsCount(values.size());
          has_logged_address_suggestions_count_ = true;
        }
      }
    }
  }

  // Add the results from AutoComplete.  They come back asynchronously, so we
  // hand off what we generated and they will send the results back to the
  // renderer.
  autocomplete_history_manager_->OnGetAutocompleteSuggestions(
      query_id, field.name, field.value, values, labels, icons, unique_ids);
}

void AutofillManager::OnFillAutofillFormData(int query_id,
                                             const FormData& form,
                                             const FormFieldData& field,
                                             int unique_id) {
  RenderViewHost* host = NULL;
  const AutofillDataModel* data_model = NULL;
  size_t variant = 0;
  FormStructure* form_structure = NULL;
  AutofillField* autofill_field = NULL;
  // NOTE: GetHost may invalidate |data_model| because it causes the
  // PersonalDataManager to reload Mac address book entries. Thus it must
  // come before GetProfileOrCreditCard.
  if (!GetHost(&host) ||
      !GetProfileOrCreditCard(unique_id, &data_model, &variant) ||
      !GetCachedFormAndField(form, field, &form_structure, &autofill_field))
    return;

  DCHECK(host);
  DCHECK(form_structure);
  DCHECK(autofill_field);

  FormData result = form;

  // If the relevant section is auto-filled, we should fill |field| but not the
  // rest of the form.
  if (SectionIsAutofilled(*form_structure, form, autofill_field->section())) {
    for (std::vector<FormFieldData>::iterator iter = result.fields.begin();
         iter != result.fields.end(); ++iter) {
      if ((*iter) == field) {
        data_model->FillFormField(
            *autofill_field, variant, app_locale_, &(*iter));
        // Mark the cached field as autofilled, so that we can detect when a
        // user edits an autofilled field (for metrics).
        autofill_field->is_autofilled = true;
        break;
      }
    }

    driver_->SendFormDataToRenderer(query_id, result);
    return;
  }

  // Cache the field type for the field from which the user initiated autofill.
  FieldTypeGroup initiating_group_type = autofill_field->Type().group();
  DCHECK_EQ(form_structure->field_count(), form.fields.size());
  for (size_t i = 0; i < form_structure->field_count(); ++i) {
    if (form_structure->field(i)->section() != autofill_field->section())
      continue;

    DCHECK_EQ(*form_structure->field(i), result.fields[i]);

    const AutofillField* cached_field = form_structure->field(i);
    FieldTypeGroup field_group_type = cached_field->Type().group();
    if (field_group_type != NO_GROUP) {
      // If the field being filled is either
      //   (a) the field that the user initiated the fill from, or
      //   (b) part of the same logical unit, e.g. name or phone number,
      // then take the multi-profile "variant" into account.
      // Otherwise fill with the default (zeroth) variant.
      size_t use_variant = 0;
      if (result.fields[i] == field ||
          field_group_type == initiating_group_type) {
        use_variant = variant;
      }
      data_model->FillFormField(*cached_field,
                                use_variant,
                                app_locale_,
                                &result.fields[i]);
      // Mark the cached field as autofilled, so that we can detect when a user
      // edits an autofilled field (for metrics).
      form_structure->field(i)->is_autofilled = true;
    }
  }

  autofilled_form_signatures_.push_front(form_structure->FormSignature());
  // Only remember the last few forms that we've seen, both to avoid false
  // positives and to avoid wasting memory.
  if (autofilled_form_signatures_.size() > kMaxRecentFormSignaturesToRemember)
    autofilled_form_signatures_.pop_back();

  driver_->SendFormDataToRenderer(query_id, result);
}

void AutofillManager::OnShowAutofillDialog() {
  manager_delegate_->ShowAutofillSettings();
}

void AutofillManager::OnDidPreviewAutofillFormData() {
  if (test_delegate_)
    test_delegate_->DidPreviewFormData();
}

void AutofillManager::OnDidFillAutofillFormData(const TimeTicks& timestamp) {
  if (test_delegate_)
    test_delegate_->DidFillFormData();

  metric_logger_->LogUserHappinessMetric(AutofillMetrics::USER_DID_AUTOFILL);
  if (!user_did_autofill_) {
    user_did_autofill_ = true;
    metric_logger_->LogUserHappinessMetric(
        AutofillMetrics::USER_DID_AUTOFILL_ONCE);
  }

  UpdateInitialInteractionTimestamp(timestamp);
}

void AutofillManager::OnDidShowAutofillSuggestions(bool is_new_popup) {
  if (test_delegate_)
    test_delegate_->DidShowSuggestions();

  if (is_new_popup) {
    metric_logger_->LogUserHappinessMetric(AutofillMetrics::SUGGESTIONS_SHOWN);

    if (!did_show_suggestions_) {
      did_show_suggestions_ = true;
      metric_logger_->LogUserHappinessMetric(
          AutofillMetrics::SUGGESTIONS_SHOWN_ONCE);
    }
  }
}

void AutofillManager::OnHideAutofillUI() {
  if (!IsAutofillEnabled())
    return;

  manager_delegate_->HideAutofillPopup();
  manager_delegate_->HideAutocheckoutBubble();
}

void AutofillManager::RemoveAutofillProfileOrCreditCard(int unique_id) {
  const AutofillDataModel* data_model = NULL;
  size_t variant = 0;
  if (!GetProfileOrCreditCard(unique_id, &data_model, &variant)) {
    NOTREACHED();
    return;
  }

  // TODO(csharp): If we are dealing with a variant only the variant should
  // be deleted, instead of doing nothing.
  // http://crbug.com/124211
  if (variant != 0)
    return;

  personal_data_->RemoveByGUID(data_model->guid());
}

void AutofillManager::RemoveAutocompleteEntry(const base::string16& name,
                                              const base::string16& value) {
  autocomplete_history_manager_->OnRemoveAutocompleteEntry(name, value);
}

content::WebContents* AutofillManager::GetWebContents() const {
  return driver_->GetWebContents();
}

const std::vector<FormStructure*>& AutofillManager::GetFormStructures() {
  return form_structures_.get();
}

void AutofillManager::ShowRequestAutocompleteDialog(
    const FormData& form,
    const GURL& source_url,
    autofill::DialogType dialog_type,
    const base::Callback<void(const FormStructure*,
                              const std::string&)>& callback) {
  manager_delegate_->ShowRequestAutocompleteDialog(
      form, source_url, dialog_type, callback);
}

void AutofillManager::SetTestDelegate(
    autofill::AutofillManagerTestDelegate* delegate) {
  test_delegate_ = delegate;
}

void AutofillManager::OnAddPasswordFormMapping(
      const FormFieldData& form,
      const PasswordFormFillData& fill_data) {
  external_delegate_->AddPasswordFormMapping(form, fill_data);
}

void AutofillManager::OnShowPasswordSuggestions(
    const FormFieldData& field,
    const gfx::RectF& bounds,
    const std::vector<base::string16>& suggestions,
    const std::vector<base::string16>& realms) {
  external_delegate_->OnShowPasswordSuggestions(suggestions,
                                                realms,
                                                field,
                                                bounds);
}

void AutofillManager::OnSetDataList(const std::vector<base::string16>& values,
                                    const std::vector<base::string16>& labels) {
  if (values.size() != labels.size())
    return;

  external_delegate_->SetCurrentDataListValues(values, labels);
}

void AutofillManager::OnRequestAutocomplete(
    const FormData& form,
    const GURL& frame_url) {
  if (!IsAutofillEnabled()) {
    ReturnAutocompleteResult(WebFormElement::AutocompleteResultErrorDisabled,
                             FormData());
    return;
  }

  base::Callback<void(const FormStructure*, const std::string&)> callback =
      base::Bind(&AutofillManager::ReturnAutocompleteData,
                 weak_ptr_factory_.GetWeakPtr());
  ShowRequestAutocompleteDialog(
      form, frame_url, autofill::DIALOG_TYPE_REQUEST_AUTOCOMPLETE, callback);
}

void AutofillManager::ReturnAutocompleteResult(
    WebFormElement::AutocompleteResult result, const FormData& form_data) {
  // driver_->GetWebContents() will be NULL when the interactive autocomplete
  // is closed due to a tab or browser window closing.
  if (!driver_->GetWebContents())
    return;

  RenderViewHost* host = driver_->GetWebContents()->GetRenderViewHost();
  if (!host)
    return;

  host->Send(new AutofillMsg_RequestAutocompleteResult(host->GetRoutingID(),
                                                       result,
                                                       form_data));
}

void AutofillManager::ReturnAutocompleteData(
    const FormStructure* result,
    const std::string& unused_transaction_id) {
  if (!result) {
    ReturnAutocompleteResult(WebFormElement::AutocompleteResultErrorCancel,
                             FormData());
  } else {
    ReturnAutocompleteResult(WebFormElement::AutocompleteResultSuccess,
                             result->ToFormData());
  }
}

void AutofillManager::OnLoadedServerPredictions(
    const std::string& response_xml) {
  scoped_ptr<autofill::AutocheckoutPageMetaData> page_meta_data(
      new autofill::AutocheckoutPageMetaData());

  // Parse and store the server predictions.
  FormStructure::ParseQueryResponse(response_xml,
                                    form_structures_.get(),
                                    page_meta_data.get(),
                                    *metric_logger_);

  if (page_meta_data->IsInAutofillableFlow()) {
    RenderViewHost* host = driver_->GetWebContents()->GetRenderViewHost();
    if (host)
      host->Send(new AutofillMsg_AutocheckoutSupported(host->GetRoutingID()));
  }

  // TODO(ahutter): Remove this once Autocheckout is implemented on other
  // platforms. See http://crbug.com/173416.
#if defined(TOOLKIT_VIEWS)
  if (!GetAutocheckoutURLPrefix().empty())
    autocheckout_manager_.OnLoadedPageMetaData(page_meta_data.Pass());
#endif  // #if defined(TOOLKIT_VIEWS)

  // If the corresponding flag is set, annotate forms with the predicted types.
  driver_->SendAutofillTypePredictionsToRenderer(form_structures_.get());
}

void AutofillManager::OnDidEndTextFieldEditing() {
  external_delegate_->DidEndTextFieldEditing();
}

void AutofillManager::OnAutocheckoutPageCompleted(
    autofill::AutocheckoutStatus status) {
  autocheckout_manager_.OnAutocheckoutPageCompleted(status);
}

std::string AutofillManager::GetAutocheckoutURLPrefix() const {
  if (!driver_->GetWebContents())
    return std::string();

  autofill::autocheckout::WhitelistManager* whitelist_manager =
      manager_delegate_->GetAutocheckoutWhitelistManager();

  return whitelist_manager ? whitelist_manager->GetMatchedURLPrefix(
      driver_->GetWebContents()->GetURL()) : std::string();
}

bool AutofillManager::IsAutofillEnabled() const {
  return manager_delegate_->GetPrefs()->GetBoolean(prefs::kAutofillEnabled);
}

void AutofillManager::ImportFormData(const FormStructure& submitted_form) {
  const CreditCard* imported_credit_card;
  if (!personal_data_->ImportFormData(submitted_form, &imported_credit_card))
    return;

  // If credit card information was submitted, we need to confirm whether to
  // save it.
  if (imported_credit_card) {
    manager_delegate_->ConfirmSaveCreditCard(
        *metric_logger_,
        *imported_credit_card,
        base::Bind(&PersonalDataManager::SaveImportedCreditCard,
                   base::Unretained(personal_data_), *imported_credit_card));
  }
}

// Note that |submitted_form| is passed as a pointer rather than as a reference
// so that we can get memory management right across threads.  Note also that we
// explicitly pass in all the time stamps of interest, as the cached ones might
// get reset before this method executes.
void AutofillManager::UploadFormDataAsyncCallback(
    const FormStructure* submitted_form,
    const TimeTicks& load_time,
    const TimeTicks& interaction_time,
    const TimeTicks& submission_time) {
  submitted_form->LogQualityMetrics(*metric_logger_,
                                    load_time,
                                    interaction_time,
                                    submission_time);

  if (submitted_form->ShouldBeCrowdsourced())
    UploadFormData(*submitted_form);
}

void AutofillManager::OnMaybeShowAutocheckoutBubble(
    const FormData& form,
    const gfx::RectF& bounding_box) {
  if (!IsAutofillEnabled())
    return;

  // Don't show bubble if corresponding FormStructure doesn't have anything to
  // autofill.
  FormStructure* cached_form;
  if (!FindCachedForm(form, &cached_form))
    return;

  // Don't offer Autocheckout bubble if Autofill server is not aware of this
  // form in the context of Autocheckout experiment.
  if (!HasServerSpecifiedFieldTypes(*cached_form))
    return;

  autocheckout_manager_.MaybeShowAutocheckoutBubble(form.origin, bounding_box);
}

void AutofillManager::UploadFormData(const FormStructure& submitted_form) {
  if (!download_manager_)
    return;

  // Check if the form is among the forms that were recently auto-filled.
  bool was_autofilled = false;
  std::string form_signature = submitted_form.FormSignature();
  for (std::list<std::string>::const_iterator it =
           autofilled_form_signatures_.begin();
       it != autofilled_form_signatures_.end() && !was_autofilled;
       ++it) {
    if (*it == form_signature)
      was_autofilled = true;
  }

  ServerFieldTypeSet non_empty_types;
  personal_data_->GetNonEmptyTypes(&non_empty_types);

  download_manager_->StartUploadRequest(submitted_form, was_autofilled,
                                       non_empty_types);
}

void AutofillManager::Reset() {
  form_structures_.clear();
  has_logged_autofill_enabled_ = false;
  has_logged_address_suggestions_count_ = false;
  did_show_suggestions_ = false;
  user_did_type_ = false;
  user_did_autofill_ = false;
  user_did_edit_autofilled_field_ = false;
  forms_loaded_timestamp_ = TimeTicks();
  initial_interaction_timestamp_ = TimeTicks();
  external_delegate_->Reset();
}

AutofillManager::AutofillManager(AutofillDriver* driver,
                                 autofill::AutofillManagerDelegate* delegate,
                                 PersonalDataManager* personal_data)
    : driver_(driver),
      manager_delegate_(delegate),
      app_locale_("en-US"),
      personal_data_(personal_data),
      autocomplete_history_manager_(
          new AutocompleteHistoryManager(driver, delegate)),
      autocheckout_manager_(this),
      metric_logger_(new AutofillMetrics),
      has_logged_autofill_enabled_(false),
      has_logged_address_suggestions_count_(false),
      did_show_suggestions_(false),
      user_did_type_(false),
      user_did_autofill_(false),
      user_did_edit_autofilled_field_(false),
      external_delegate_(NULL),
      test_delegate_(NULL),
      weak_ptr_factory_(this) {
  DCHECK(driver_);
  DCHECK(driver_->GetWebContents());
  DCHECK(manager_delegate_);
}

void AutofillManager::set_metric_logger(const AutofillMetrics* metric_logger) {
  metric_logger_.reset(metric_logger);
}

bool AutofillManager::GetHost(RenderViewHost** host) const {
  if (!IsAutofillEnabled())
    return false;

  // No autofill data to return if the profiles are empty.
  if (personal_data_->GetProfiles().empty() &&
      personal_data_->GetCreditCards().empty()) {
    return false;
  }

  if (!driver_->RendererIsAvailable())
    return false;

  *host = driver_->GetWebContents()->GetRenderViewHost();
  return true;
}

bool AutofillManager::GetProfileOrCreditCard(
    int unique_id,
    const AutofillDataModel** data_model,
    size_t* variant) const {
  // Unpack the |unique_id| into component parts.
  GUIDPair credit_card_guid;
  GUIDPair profile_guid;
  UnpackGUIDs(unique_id, &credit_card_guid, &profile_guid);
  DCHECK(!base::IsValidGUID(credit_card_guid.first) ||
         !base::IsValidGUID(profile_guid.first));

  // Find the profile that matches the |profile_guid|, if one is specified.
  // Otherwise find the credit card that matches the |credit_card_guid|,
  // if specified.
  if (base::IsValidGUID(profile_guid.first)) {
    *data_model = personal_data_->GetProfileByGUID(profile_guid.first);
    *variant = profile_guid.second;
  } else if (base::IsValidGUID(credit_card_guid.first)) {
    *data_model = personal_data_->GetCreditCardByGUID(credit_card_guid.first);
    *variant = credit_card_guid.second;
  }

  return !!*data_model;
}

bool AutofillManager::FindCachedForm(const FormData& form,
                                     FormStructure** form_structure) const {
  // Find the FormStructure that corresponds to |form|.
  // Scan backward through the cached |form_structures_|, as updated versions of
  // forms are added to the back of the list, whereas original versions of these
  // forms might appear toward the beginning of the list.  The communication
  // protocol with the crowdsourcing server does not permit us to discard the
  // original versions of the forms.
  *form_structure = NULL;
  for (std::vector<FormStructure*>::const_reverse_iterator iter =
           form_structures_.rbegin();
       iter != form_structures_.rend(); ++iter) {
    if (**iter == form) {
      *form_structure = *iter;

      // The same form might be cached with multiple field counts: in some
      // cases, non-autofillable fields are filtered out, whereas in other cases
      // they are not.  To avoid thrashing the cache, keep scanning until we
      // find a cached version with the same number of fields, if there is one.
      if ((*iter)->field_count() == form.fields.size())
        break;
    }
  }

  if (!(*form_structure))
    return false;

  return true;
}

bool AutofillManager::GetCachedFormAndField(const FormData& form,
                                            const FormFieldData& field,
                                            FormStructure** form_structure,
                                            AutofillField** autofill_field) {
  // Find the FormStructure that corresponds to |form|.
  // If we do not have this form in our cache but it is parseable, we'll add it
  // in the call to |UpdateCachedForm()|.
  if (!FindCachedForm(form, form_structure) &&
      !FormStructure(form, GetAutocheckoutURLPrefix()).ShouldBeParsed(false)) {
    return false;
  }

  // Update the cached form to reflect any dynamic changes to the form data, if
  // necessary.
  if (!UpdateCachedForm(form, *form_structure, form_structure))
    return false;

  // No data to return if there are no auto-fillable fields.
  if (!(*form_structure)->autofill_count())
    return false;

  // Find the AutofillField that corresponds to |field|.
  *autofill_field = NULL;
  for (std::vector<AutofillField*>::const_iterator iter =
           (*form_structure)->begin();
       iter != (*form_structure)->end(); ++iter) {
    if ((**iter) == field) {
      *autofill_field = *iter;
      break;
    }
  }

  // Even though we always update the cache, the field might not exist if the
  // website disables autocomplete while the user is interacting with the form.
  // See http://crbug.com/160476
  return *autofill_field != NULL;
}

bool AutofillManager::UpdateCachedForm(const FormData& live_form,
                                       const FormStructure* cached_form,
                                       FormStructure** updated_form) {
  bool needs_update =
      (!cached_form ||
       live_form.fields.size() != cached_form->field_count());
  for (size_t i = 0; !needs_update && i < cached_form->field_count(); ++i) {
    needs_update = *cached_form->field(i) != live_form.fields[i];
  }

  if (!needs_update)
    return true;

  if (form_structures_.size() >= kMaxFormCacheSize)
    return false;

  // Add the new or updated form to our cache.
  form_structures_.push_back(
      new FormStructure(live_form, GetAutocheckoutURLPrefix()));
  *updated_form = *form_structures_.rbegin();
  (*updated_form)->DetermineHeuristicTypes(*metric_logger_);

  // If we have cached data, propagate it to the updated form.
  if (cached_form) {
    std::map<base::string16, const AutofillField*> cached_fields;
    for (size_t i = 0; i < cached_form->field_count(); ++i) {
      const AutofillField* field = cached_form->field(i);
      cached_fields[field->unique_name()] = field;
    }

    for (size_t i = 0; i < (*updated_form)->field_count(); ++i) {
      AutofillField* field = (*updated_form)->field(i);
      std::map<base::string16, const AutofillField*>::iterator cached_field =
          cached_fields.find(field->unique_name());
      if (cached_field != cached_fields.end()) {
        field->set_server_type(cached_field->second->server_type());
        field->is_autofilled = cached_field->second->is_autofilled;
      }
    }

    // Note: We _must not_ remove the original version of the cached form from
    // the list of |form_structures_|.  Otherwise, we break parsing of the
    // crowdsourcing server's response to our query.
  }

  // Annotate the updated form with its predicted types.
  std::vector<FormStructure*> forms(1, *updated_form);
  driver_->SendAutofillTypePredictionsToRenderer(forms);

  return true;
}

void AutofillManager::GetProfileSuggestions(
    FormStructure* form,
    const FormFieldData& field,
    const AutofillType& type,
    std::vector<base::string16>* values,
    std::vector<base::string16>* labels,
    std::vector<base::string16>* icons,
    std::vector<int>* unique_ids) const {
  std::vector<ServerFieldType> field_types(form->field_count());
  for (size_t i = 0; i < form->field_count(); ++i) {
    field_types.push_back(form->field(i)->Type().GetStorableType());
  }
  std::vector<GUIDPair> guid_pairs;

  personal_data_->GetProfileSuggestions(
      type, field.value, field.is_autofilled, field_types,
      values, labels, icons, &guid_pairs);

  for (size_t i = 0; i < guid_pairs.size(); ++i) {
    unique_ids->push_back(PackGUIDs(GUIDPair(std::string(), 0),
                                    guid_pairs[i]));
  }
}

void AutofillManager::GetCreditCardSuggestions(
    const FormFieldData& field,
    const AutofillType& type,
    std::vector<base::string16>* values,
    std::vector<base::string16>* labels,
    std::vector<base::string16>* icons,
    std::vector<int>* unique_ids) const {
  std::vector<GUIDPair> guid_pairs;
  personal_data_->GetCreditCardSuggestions(
      type, field.value, values, labels, icons, &guid_pairs);

  for (size_t i = 0; i < guid_pairs.size(); ++i) {
    unique_ids->push_back(PackGUIDs(guid_pairs[i], GUIDPair(std::string(), 0)));
  }
}

void AutofillManager::ParseForms(const std::vector<FormData>& forms) {
  std::vector<FormStructure*> non_queryable_forms;
  std::string autocheckout_url_prefix = GetAutocheckoutURLPrefix();
  for (std::vector<FormData>::const_iterator iter = forms.begin();
       iter != forms.end(); ++iter) {
    scoped_ptr<FormStructure> form_structure(
        new FormStructure(*iter, autocheckout_url_prefix));
    if (!form_structure->ShouldBeParsed(false))
      continue;

    form_structure->DetermineHeuristicTypes(*metric_logger_);

    // Set aside forms with method GET or author-specified types, so that they
    // are not included in the query to the server.
    if (form_structure->ShouldBeCrowdsourced())
      form_structures_.push_back(form_structure.release());
    else
      non_queryable_forms.push_back(form_structure.release());
  }

  if (form_structures_.empty()) {
    // Call OnLoadedPageMetaData with no page metadata immediately if there is
    // no form in the page. This give |autocheckout_manager| a chance to
    // terminate Autocheckout and send Autocheckout status.
    autocheckout_manager_.OnLoadedPageMetaData(
        scoped_ptr<autofill::AutocheckoutPageMetaData>());
  } else if (download_manager_) {
    // Query the server if we have at least one of the forms were parsed.
    download_manager_->StartQueryRequest(form_structures_.get(),
                                        *metric_logger_);
  }

  for (std::vector<FormStructure*>::const_iterator iter =
           non_queryable_forms.begin();
       iter != non_queryable_forms.end(); ++iter) {
    form_structures_.push_back(*iter);
  }

  if (!form_structures_.empty())
    metric_logger_->LogUserHappinessMetric(AutofillMetrics::FORMS_LOADED);

  // For the |non_queryable_forms|, we have all the field type info we're ever
  // going to get about them.  For the other forms, we'll wait until we get a
  // response from the server.
  driver_->SendAutofillTypePredictionsToRenderer(non_queryable_forms);
}

int AutofillManager::GUIDToID(const GUIDPair& guid) const {
  if (!base::IsValidGUID(guid.first))
    return 0;

  std::map<GUIDPair, int>::const_iterator iter = guid_id_map_.find(guid);
  if (iter == guid_id_map_.end()) {
    int id = guid_id_map_.size() + 1;
    guid_id_map_[guid] = id;
    id_guid_map_[id] = guid;
    return id;
  } else {
    return iter->second;
  }
}

const GUIDPair AutofillManager::IDToGUID(int id) const {
  if (id == 0)
    return GUIDPair(std::string(), 0);

  std::map<int, GUIDPair>::const_iterator iter = id_guid_map_.find(id);
  if (iter == id_guid_map_.end()) {
    NOTREACHED();
    return GUIDPair(std::string(), 0);
  }

  return iter->second;
}

// When sending IDs (across processes) to the renderer we pack credit card and
// profile IDs into a single integer.  Credit card IDs are sent in the high
// word and profile IDs are sent in the low word.
int AutofillManager::PackGUIDs(const GUIDPair& cc_guid,
                               const GUIDPair& profile_guid) const {
  int cc_id = GUIDToID(cc_guid);
  int profile_id = GUIDToID(profile_guid);

  DCHECK(cc_id <= std::numeric_limits<unsigned short>::max());
  DCHECK(profile_id <= std::numeric_limits<unsigned short>::max());

  return cc_id << std::numeric_limits<unsigned short>::digits | profile_id;
}

// When receiving IDs (across processes) from the renderer we unpack credit card
// and profile IDs from a single integer.  Credit card IDs are stored in the
// high word and profile IDs are stored in the low word.
void AutofillManager::UnpackGUIDs(int id,
                                  GUIDPair* cc_guid,
                                  GUIDPair* profile_guid) const {
  int cc_id = id >> std::numeric_limits<unsigned short>::digits &
      std::numeric_limits<unsigned short>::max();
  int profile_id = id & std::numeric_limits<unsigned short>::max();

  *cc_guid = IDToGUID(cc_id);
  *profile_guid = IDToGUID(profile_id);
}

void AutofillManager::UpdateInitialInteractionTimestamp(
    const TimeTicks& interaction_timestamp) {
  if (initial_interaction_timestamp_.is_null() ||
      interaction_timestamp < initial_interaction_timestamp_) {
    initial_interaction_timestamp_ = interaction_timestamp;
  }
}

}  // namespace autofill
