// 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/content/browser/autocheckout_manager.h"

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/strings/utf_string_conversions.h"
#include "components/autofill/content/browser/autocheckout_request_manager.h"
#include "components/autofill/content/browser/autocheckout_statistic.h"
#include "components/autofill/content/browser/autocheckout_steps.h"
#include "components/autofill/core/browser/autofill_country.h"
#include "components/autofill/core/browser/autofill_field.h"
#include "components/autofill/core/browser/autofill_manager.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/common/autofill_messages.h"
#include "components/autofill/core/common/form_data.h"
#include "components/autofill/core/common/form_field_data.h"
#include "components/autofill/core/common/web_element_descriptor.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 "net/cookies/cookie_options.h"
#include "net/cookies/cookie_store.h"
#include "net/url_request/url_request_context.h"
#include "net/url_request/url_request_context_getter.h"
#include "ui/gfx/rect.h"
#include "url/gurl.h"

using content::RenderViewHost;
using content::WebContents;

namespace autofill {

namespace {

const char kGoogleAccountsUrl[] = "https://accounts.google.com/";

// Build FormFieldData based on the supplied |autocomplete_attribute|. Will
// fill rest of properties with default values.
FormFieldData BuildField(const std::string& autocomplete_attribute) {
  FormFieldData field;
  field.name = base::string16();
  field.value = base::string16();
  field.autocomplete_attribute = autocomplete_attribute;
  field.form_control_type = "text";
  return field;
}

// Build Autocheckout specific form data to be consumed by
// AutofillDialogController to show the Autocheckout specific UI.
FormData BuildAutocheckoutFormData() {
  FormData formdata;
  formdata.fields.push_back(BuildField("email"));
  formdata.fields.push_back(BuildField("cc-name"));
  formdata.fields.push_back(BuildField("cc-number"));
  formdata.fields.push_back(BuildField("cc-exp-month"));
  formdata.fields.push_back(BuildField("cc-exp-year"));
  formdata.fields.push_back(BuildField("cc-csc"));
  formdata.fields.push_back(BuildField("billing address-line1"));
  formdata.fields.push_back(BuildField("billing address-line2"));
  formdata.fields.push_back(BuildField("billing locality"));
  formdata.fields.push_back(BuildField("billing region"));
  formdata.fields.push_back(BuildField("billing country"));
  formdata.fields.push_back(BuildField("billing postal-code"));
  formdata.fields.push_back(BuildField("billing tel"));
  formdata.fields.push_back(BuildField("shipping name"));
  formdata.fields.push_back(BuildField("shipping address-line1"));
  formdata.fields.push_back(BuildField("shipping address-line2"));
  formdata.fields.push_back(BuildField("shipping locality"));
  formdata.fields.push_back(BuildField("shipping region"));
  formdata.fields.push_back(BuildField("shipping country"));
  formdata.fields.push_back(BuildField("shipping postal-code"));
  formdata.fields.push_back(BuildField("shipping tel"));
  return formdata;
}

AutofillMetrics::AutocheckoutBuyFlowMetric AutocheckoutStatusToUmaMetric(
    AutocheckoutStatus status) {
  switch (status) {
    case SUCCESS:
      return AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_SUCCESS;
    case MISSING_FIELDMAPPING:
      return AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_MISSING_FIELDMAPPING;
    case MISSING_CLICK_ELEMENT_BEFORE_FORM_FILLING:
      return AutofillMetrics::
          AUTOCHECKOUT_BUY_FLOW_MISSING_CLICK_ELEMENT_BEFORE_FORM_FILLING;
    case MISSING_CLICK_ELEMENT_AFTER_FORM_FILLING:
      return AutofillMetrics::
          AUTOCHECKOUT_BUY_FLOW_MISSING_CLICK_ELEMENT_AFTER_FORM_FILLING;
    case MISSING_ADVANCE:
      return AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_MISSING_ADVANCE_ELEMENT;
    case CANNOT_PROCEED:
      return AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_CANNOT_PROCEED;
    case AUTOCHECKOUT_STATUS_NUM_STATUS:
      NOTREACHED();
  }

  NOTREACHED();
  return AutofillMetrics::NUM_AUTOCHECKOUT_BUY_FLOW_METRICS;
}

// Callback for retrieving Google Account cookies. |callback| is passed the
// retrieved cookies and posted back to the UI thread. |cookies| is any Google
// Account cookies.
void GetGoogleCookiesCallback(
    const base::Callback<void(const std::string&)>& callback,
    const std::string& cookies) {
  content::BrowserThread::PostTask(content::BrowserThread::UI,
                                   FROM_HERE,
                                   base::Bind(callback, cookies));
}

// Gets Google Account cookies. Must be called on the IO thread.
// |request_context_getter| is a getter for the current request context.
// |callback| is called when retrieving cookies is completed.
void GetGoogleCookies(
    scoped_refptr<net::URLRequestContextGetter> request_context_getter,
    const base::Callback<void(const std::string&)>& callback) {
  net::URLRequestContext* url_request_context =
      request_context_getter->GetURLRequestContext();
  if (!url_request_context)
    return;

  net::CookieStore* cookie_store = url_request_context->cookie_store();

  base::Callback<void(const std::string&)> cookie_callback = base::Bind(
      &GetGoogleCookiesCallback,
      callback);

  net::CookieOptions cookie_options;
  cookie_options.set_include_httponly();
  cookie_store->GetCookiesWithOptionsAsync(GURL(kGoogleAccountsUrl),
                                           cookie_options,
                                           cookie_callback);
}

bool IsBillingGroup(FieldTypeGroup group) {
  return group == ADDRESS_BILLING ||
         group == PHONE_BILLING ||
         group == NAME_BILLING;
}

const char kTransactionIdNotSet[] = "transaction id not set";

}  // namespace

AutocheckoutManager::AutocheckoutManager(AutofillManager* autofill_manager)
    : autofill_manager_(autofill_manager),
      metric_logger_(new AutofillMetrics),
      should_show_bubble_(true),
      is_autocheckout_bubble_showing_(false),
      in_autocheckout_flow_(false),
      should_preserve_dialog_(false),
      google_transaction_id_(kTransactionIdNotSet),
      weak_ptr_factory_(this) {}

AutocheckoutManager::~AutocheckoutManager() {
}

void AutocheckoutManager::FillForms() {
  // |page_meta_data_| should have been set by OnLoadedPageMetaData.
  DCHECK(page_meta_data_);

  // Fill the forms on the page with data given by user.
  std::vector<FormData> filled_forms;
  const std::vector<FormStructure*>& form_structures =
    autofill_manager_->GetFormStructures();
  for (std::vector<FormStructure*>::const_iterator iter =
           form_structures.begin(); iter != form_structures.end(); ++iter) {
    FormStructure* form_structure = *iter;
    form_structure->set_filled_by_autocheckout(true);
    FormData form = form_structure->ToFormData();
    DCHECK_EQ(form_structure->field_count(), form.fields.size());

    for (size_t i = 0; i < form_structure->field_count(); ++i) {
      const AutofillField* field = form_structure->field(i);
      SetValue(*field, &form.fields[i]);
    }

    filled_forms.push_back(form);
  }

  // Send filled forms along with proceed descriptor to renderer.
  RenderViewHost* host =
      autofill_manager_->GetWebContents()->GetRenderViewHost();
  if (!host)
    return;

  host->Send(new AutofillMsg_FillFormsAndClick(
      host->GetRoutingID(),
      filled_forms,
      page_meta_data_->click_elements_before_form_fill,
      page_meta_data_->click_elements_after_form_fill,
      page_meta_data_->proceed_element_descriptor));
  // Record time taken for navigating current page.
  RecordTimeTaken(page_meta_data_->current_page_number);
}

void AutocheckoutManager::OnAutocheckoutPageCompleted(
    AutocheckoutStatus status) {
  if (!in_autocheckout_flow_)
    return;

  DVLOG(2) << "OnAutocheckoutPageCompleted, page_no: "
           << page_meta_data_->current_page_number
           << " status: "
           << status;

  DCHECK_NE(MISSING_FIELDMAPPING, status);

  SetStepProgressForPage(
      page_meta_data_->current_page_number,
      (status == SUCCESS) ? AUTOCHECKOUT_STEP_COMPLETED :
          AUTOCHECKOUT_STEP_FAILED);

  if (page_meta_data_->IsEndOfAutofillableFlow() || status != SUCCESS)
    EndAutocheckout(status);
}

void AutocheckoutManager::OnLoadedPageMetaData(
    scoped_ptr<AutocheckoutPageMetaData> page_meta_data) {
  scoped_ptr<AutocheckoutPageMetaData> old_meta_data = page_meta_data_.Pass();
  page_meta_data_ = page_meta_data.Pass();

  // If there is no click element in the last page, then it's the real last page
  // of the flow, and the dialog will be closed when the page navigates.
  // Otherwise, the dialog should be preserved for the page loaded by the click
  // element on the last page of the flow.
  // Note, |should_preserve_dialog_| has to be computed at this point because
  // |in_autocheckout_flow_| may change after |OnLoadedPageMetaData| is called.
  should_preserve_dialog_ = in_autocheckout_flow_ ||
      (old_meta_data.get() &&
       old_meta_data->IsEndOfAutofillableFlow() &&
       old_meta_data->proceed_element_descriptor.retrieval_method !=
           WebElementDescriptor::NONE);

  // Don't log that the bubble could be displayed if the user entered an
  // Autocheckout flow and sees the first page of the flow again due to an
  // error.
  if (IsStartOfAutofillableFlow() && !in_autocheckout_flow_) {
    metric_logger_->LogAutocheckoutBubbleMetric(
        AutofillMetrics::BUBBLE_COULD_BE_DISPLAYED);
  }

  // On the first page of an Autocheckout flow, when this function is called the
  // user won't have opted into the flow yet.
  if (!in_autocheckout_flow_)
    return;

  AutocheckoutStatus status = SUCCESS;

  // Missing Autofill server results.
  if (!page_meta_data_.get()) {
    status = MISSING_FIELDMAPPING;
  } else if (IsStartOfAutofillableFlow()) {
    // Not possible unless Autocheckout failed to proceed.
    status = CANNOT_PROCEED;
  } else if (!page_meta_data_->IsInAutofillableFlow()) {
    // Missing Autocheckout meta data in the Autofill server results.
    status = MISSING_FIELDMAPPING;
  } else if (page_meta_data_->current_page_number <=
                 old_meta_data->current_page_number) {
    // Not possible unless Autocheckout failed to proceed.
    status = CANNOT_PROCEED;
  }

  // Encountered an error during the Autocheckout flow, probably to
  // do with a problem on the previous page.
  if (status != SUCCESS) {
    SetStepProgressForPage(old_meta_data->current_page_number,
                           AUTOCHECKOUT_STEP_FAILED);
    EndAutocheckout(status);
    return;
  }

  SetStepProgressForPage(page_meta_data_->current_page_number,
                         AUTOCHECKOUT_STEP_STARTED);

  FillForms();
}

void AutocheckoutManager::OnFormsSeen() {
  should_show_bubble_ = true;
}

bool AutocheckoutManager::ShouldIgnoreAjax() {
  return in_autocheckout_flow_ && page_meta_data_->ignore_ajax;
}

void AutocheckoutManager::MaybeShowAutocheckoutBubble(
    const GURL& frame_url,
    const gfx::RectF& bounding_box) {
  if (!should_show_bubble_ ||
      is_autocheckout_bubble_showing_ ||
      !IsStartOfAutofillableFlow())
    return;

  base::Callback<void(const std::string&)> callback = base::Bind(
      &AutocheckoutManager::ShowAutocheckoutBubble,
      weak_ptr_factory_.GetWeakPtr(),
      frame_url,
      bounding_box);

  content::WebContents* web_contents = autofill_manager_->GetWebContents();
  if (!web_contents)
    return;

  content::BrowserContext* browser_context = web_contents->GetBrowserContext();
  if(!browser_context)
    return;

  scoped_refptr<net::URLRequestContextGetter> request_context =
      scoped_refptr<net::URLRequestContextGetter>(
          browser_context->GetRequestContext());

  if (!request_context.get())
    return;

  base::Closure task = base::Bind(&GetGoogleCookies, request_context, callback);

  content::BrowserThread::PostTask(content::BrowserThread::IO,
                                   FROM_HERE,
                                   task);
}

void AutocheckoutManager::ReturnAutocheckoutData(
    const FormStructure* result,
    const std::string& google_transaction_id) {
  if (!result) {
    // When user cancels the dialog, |result| is NULL.
    // TODO(): add AutocheckoutStatus.USER_CANCELLED, and call
    //         EndAutocheckout(USER_CANCELLED) instead.
    in_autocheckout_flow_ = false;
    return;
  }

  latency_statistics_.clear();
  last_step_completion_timestamp_ = base::TimeTicks().Now();
  google_transaction_id_ = google_transaction_id;
  in_autocheckout_flow_ = true;
  should_preserve_dialog_ = true;
  metric_logger_->LogAutocheckoutBuyFlowMetric(
      AutofillMetrics::AUTOCHECKOUT_BUY_FLOW_STARTED);

  profile_.reset(new AutofillProfile());
  credit_card_.reset(new CreditCard());
  billing_address_.reset(new AutofillProfile());

  for (size_t i = 0; i < result->field_count(); ++i) {
    const AutofillType& type = result->field(i)->Type();
    const base::string16& value = result->field(i)->value;
    if (type.server_type() == CREDIT_CARD_VERIFICATION_CODE) {
      cvv_ = result->field(i)->value;
      continue;
    }
    FieldTypeGroup group = type.group();
    if (group == CREDIT_CARD) {
      credit_card_->SetRawInfo(type.server_type(), value);
      // TODO(dgwallinga): Find a way of cleanly deprecating CREDIT_CARD_NAME.
      // code.google.com/p/chromium/issues/detail?id=263498
      if (type.server_type() == CREDIT_CARD_NAME)
        billing_address_->SetRawInfo(NAME_BILLING_FULL, value);
    } else if (type.server_type() == ADDRESS_HOME_COUNTRY) {
      profile_->SetInfo(type, value, autofill_manager_->app_locale());
    } else if (type.server_type() == ADDRESS_BILLING_COUNTRY) {
      billing_address_->SetInfo(type, value, autofill_manager_->app_locale());
    } else if (IsBillingGroup(group)) {
      billing_address_->SetRawInfo(type.server_type(), value);
    } else {
      profile_->SetRawInfo(type.server_type(), value);
    }
  }

  // Page types only available in first-page meta data, so save
  // them for use later as we navigate.
  page_types_ = page_meta_data_->page_types;
  SetStepProgressForPage(page_meta_data_->current_page_number,
                         AUTOCHECKOUT_STEP_STARTED);

  FillForms();
}

void AutocheckoutManager::set_metric_logger(
    scoped_ptr<AutofillMetrics> metric_logger) {
  metric_logger_ = metric_logger.Pass();
}

void AutocheckoutManager::MaybeShowAutocheckoutDialog(
    const GURL& frame_url,
    AutocheckoutBubbleState state) {
  is_autocheckout_bubble_showing_ = false;

  // User has taken action on the bubble, don't offer bubble again.
  if (state != AUTOCHECKOUT_BUBBLE_IGNORED)
    should_show_bubble_ = false;

  if (state != AUTOCHECKOUT_BUBBLE_ACCEPTED)
    return;

  base::Callback<void(const FormStructure*, const std::string&)> callback =
      base::Bind(&AutocheckoutManager::ReturnAutocheckoutData,
                 weak_ptr_factory_.GetWeakPtr());
  autofill_manager_->ShowRequestAutocompleteDialog(BuildAutocheckoutFormData(),
                                                   frame_url,
                                                   DIALOG_TYPE_AUTOCHECKOUT,
                                                   callback);

  for (std::map<int, std::vector<AutocheckoutStepType> >::const_iterator
          it = page_meta_data_->page_types.begin();
      it != page_meta_data_->page_types.end(); ++it) {
    for (size_t i = 0; i < it->second.size(); ++i) {
      autofill_manager_->delegate()->AddAutocheckoutStep(it->second[i]);
    }
  }
}

void AutocheckoutManager::ShowAutocheckoutBubble(
    const GURL& frame_url,
    const gfx::RectF& bounding_box,
    const std::string& cookies) {
  DCHECK(thread_checker_.CalledOnValidThread());

  base::Callback<void(AutocheckoutBubbleState)> callback = base::Bind(
      &AutocheckoutManager::MaybeShowAutocheckoutDialog,
      weak_ptr_factory_.GetWeakPtr(),
      frame_url);
  autofill_manager_->delegate()->ShowAutocheckoutBubble(
      bounding_box,
      cookies.find("LSID") != std::string::npos,
      callback);
  is_autocheckout_bubble_showing_ = true;
}

bool AutocheckoutManager::IsStartOfAutofillableFlow() const {
  return page_meta_data_ && page_meta_data_->IsStartOfAutofillableFlow();
}

bool AutocheckoutManager::IsInAutofillableFlow() const {
  return page_meta_data_ && page_meta_data_->IsInAutofillableFlow();
}

void AutocheckoutManager::SetValue(const AutofillField& field,
                                   FormFieldData* field_to_fill) {
  // No-op if Autofill server doesn't know about the field.
  if (field.server_type() == NO_SERVER_DATA)
    return;

  const AutofillType& type = field.Type();

  if (type.server_type() == FIELD_WITH_DEFAULT_VALUE) {
    // For a form with radio buttons, like:
    // <form>
    //   <input type="radio" name="sex" value="male">Male<br>
    //   <input type="radio" name="sex" value="female">Female
    // </form>
    // If the default value specified at the server is "female", then
    // Autofill server responds back with following field mappings
    //   (fieldtype: FIELD_WITH_DEFAULT_VALUE, value: "female")
    //   (fieldtype: FIELD_WITH_DEFAULT_VALUE, value: "female")
    // Note that, the field mapping is repeated twice to respond to both the
    // input elements with the same name/signature in the form.
    //
    // FIELD_WITH_DEFAULT_VALUE can also be used for selects, the correspondent
    // example of the radio buttons example above is:
    // <SELECT name="sex">
    //   <OPTION value="female">Female</OPTION>
    //   <OPTION value="male">Male</OPTION>
    // </SELECT>
    base::string16 default_value = UTF8ToUTF16(field.default_value());
    if (field.is_checkable) {
      // Mark the field checked if server says the default value of the field
      // to be this field's value.
      field_to_fill->is_checked = (field.value == default_value);
    } else if (field.form_control_type == "select-one") {
      field_to_fill->value = default_value;
    } else {
      // FIELD_WITH_DEFAULT_VALUE should not be used for other type of fields.
      NOTREACHED();
    }
    return;
  }

  // Handle verification code directly.
  if (type.server_type() == CREDIT_CARD_VERIFICATION_CODE) {
    field_to_fill->value = cvv_;
    return;
  }

  if (type.group() == CREDIT_CARD) {
    credit_card_->FillFormField(
        field, 0, autofill_manager_->app_locale(), field_to_fill);
  } else if (IsBillingGroup(type.group())) {
    billing_address_->FillFormField(
        field, 0, autofill_manager_->app_locale(), field_to_fill);
  } else {
    profile_->FillFormField(
        field, 0, autofill_manager_->app_locale(), field_to_fill);
  }
}

void AutocheckoutManager::SendAutocheckoutStatus(AutocheckoutStatus status) {
  // To ensure stale data isn't being sent.
  DCHECK_NE(kTransactionIdNotSet, google_transaction_id_);

  AutocheckoutRequestManager::CreateForBrowserContext(
      autofill_manager_->GetWebContents()->GetBrowserContext());
  AutocheckoutRequestManager* autocheckout_request_manager =
      AutocheckoutRequestManager::FromBrowserContext(
          autofill_manager_->GetWebContents()->GetBrowserContext());
  // It is assumed that the domain Autocheckout starts on does not change
  // during the flow.  If this proves to be incorrect, the |source_url| from
  // AutofillDialogControllerImpl will need to be provided in its callback in
  // addition to the Google transaction id.
  autocheckout_request_manager->SendAutocheckoutStatus(
      status,
      autofill_manager_->GetWebContents()->GetURL(),
      latency_statistics_,
      google_transaction_id_);

  // Log the result of this Autocheckout flow to UMA.
  metric_logger_->LogAutocheckoutBuyFlowMetric(
      AutocheckoutStatusToUmaMetric(status));

  google_transaction_id_ = kTransactionIdNotSet;
}

void AutocheckoutManager::SetStepProgressForPage(
    int page_number,
    AutocheckoutStepStatus status) {
  if (page_types_.count(page_number) == 1) {
    for (size_t i = 0; i < page_types_[page_number].size(); ++i) {
      autofill_manager_->delegate()->UpdateAutocheckoutStep(
          page_types_[page_number][i], status);
    }
  }
}

void AutocheckoutManager::RecordTimeTaken(int page_number) {
  AutocheckoutStatistic statistic;
  statistic.page_number = page_number;
  if (page_types_.count(page_number) == 1) {
    for (size_t i = 0; i < page_types_[page_number].size(); ++i) {
      statistic.steps.push_back(page_types_[page_number][i]);
    }
  }

  statistic.time_taken =
      base::TimeTicks().Now() - last_step_completion_timestamp_;
  latency_statistics_.push_back(statistic);

  // Reset timestamp.
  last_step_completion_timestamp_ = base::TimeTicks().Now();
}

void AutocheckoutManager::EndAutocheckout(AutocheckoutStatus status) {
  DCHECK(in_autocheckout_flow_);

  DVLOG(2) << "EndAutocheckout at step: "
           << page_meta_data_->current_page_number
           << " with status: "
           << status;

  SendAutocheckoutStatus(status);
  if (status == SUCCESS)
    autofill_manager_->delegate()->OnAutocheckoutSuccess();
  else
    autofill_manager_->delegate()->OnAutocheckoutError();
  in_autocheckout_flow_ = false;
}

}  // namespace autofill
