// Copyright (c) 2012 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 "build/build_config.h"

#include "chrome/browser/search_engines/template_url_fetcher.h"

#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_fetcher_callbacks.h"
#include "chrome/browser/search_engines/template_url_parser.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/template_url_service_factory.h"
#include "chrome/browser/search_engines/ui_thread_search_terms_data.h"
#include "content/public/browser/render_frame_host.h"
#include "content/public/browser/render_process_host.h"
#include "content/public/browser/web_contents.h"
#include "content/public/common/url_fetcher.h"
#include "net/base/load_flags.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_fetcher_delegate.h"
#include "net/url_request/url_request_status.h"

// RequestDelegate ------------------------------------------------------------
class TemplateURLFetcher::RequestDelegate : public net::URLFetcherDelegate {
 public:
  // Takes ownership of |callbacks|.
  RequestDelegate(TemplateURLFetcher* fetcher,
                  const base::string16& keyword,
                  const GURL& osdd_url,
                  const GURL& favicon_url,
                  content::WebContents* web_contents,
                  TemplateURLFetcherCallbacks* callbacks,
                  ProviderType provider_type);

  // net::URLFetcherDelegate:
  // If data contains a valid OSDD, a TemplateURL is created and added to
  // the TemplateURLService.
  virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE;

  // URL of the OSDD.
  GURL url() const { return osdd_url_; }

  // Keyword to use.
  base::string16 keyword() const { return keyword_; }

  // The type of search provider being fetched.
  ProviderType provider_type() const { return provider_type_; }

 private:
  void OnLoaded();
  void AddSearchProvider();

  scoped_ptr<net::URLFetcher> url_fetcher_;
  TemplateURLFetcher* fetcher_;
  scoped_ptr<TemplateURL> template_url_;
  base::string16 keyword_;
  const GURL osdd_url_;
  const GURL favicon_url_;
  const ProviderType provider_type_;
  scoped_ptr<TemplateURLFetcherCallbacks> callbacks_;

  scoped_ptr<TemplateURLService::Subscription> template_url_subscription_;

  DISALLOW_COPY_AND_ASSIGN(RequestDelegate);
};

TemplateURLFetcher::RequestDelegate::RequestDelegate(
    TemplateURLFetcher* fetcher,
    const base::string16& keyword,
    const GURL& osdd_url,
    const GURL& favicon_url,
    content::WebContents* web_contents,
    TemplateURLFetcherCallbacks* callbacks,
    ProviderType provider_type)
    : url_fetcher_(net::URLFetcher::Create(
          osdd_url, net::URLFetcher::GET, this)),
      fetcher_(fetcher),
      keyword_(keyword),
      osdd_url_(osdd_url),
      favicon_url_(favicon_url),
      provider_type_(provider_type),
      callbacks_(callbacks) {
  TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(
      fetcher_->profile());
  DCHECK(model);  // TemplateURLFetcher::ScheduleDownload verifies this.

  if (!model->loaded()) {
    // Start the model load and set-up waiting for it.
    template_url_subscription_ = model->RegisterOnLoadedCallback(
        base::Bind(&TemplateURLFetcher::RequestDelegate::OnLoaded,
                   base::Unretained(this)));
    model->Load();
  }

  url_fetcher_->SetRequestContext(fetcher->profile()->GetRequestContext());
  // Can be NULL during tests.
  if (web_contents) {
    content::AssociateURLFetcherWithRenderFrame(
        url_fetcher_.get(),
        web_contents->GetURL(),
        web_contents->GetRenderProcessHost()->GetID(),
        web_contents->GetMainFrame()->GetRoutingID());
  }

  url_fetcher_->Start();
}

void TemplateURLFetcher::RequestDelegate::OnLoaded() {
  template_url_subscription_.reset();
  if (!template_url_.get())
    return;
  AddSearchProvider();
  // WARNING: AddSearchProvider deletes us.
}

void TemplateURLFetcher::RequestDelegate::OnURLFetchComplete(
    const net::URLFetcher* source) {
  // Validation checks.
  // Make sure we can still replace the keyword, i.e. the fetch was successful.
  // If the OSDD file was loaded HTTP, we also have to check the response_code.
  // For other schemes, e.g. when the OSDD file is bundled with an extension,
  // the response_code is not applicable and should be -1. Also, ensure that
  // the returned information results in a valid search URL.
  std::string data;
  if (!source->GetStatus().is_success() ||
      ((source->GetResponseCode() != -1) &&
        (source->GetResponseCode() != 200)) ||
      !source->GetResponseAsString(&data)) {
    fetcher_->RequestCompleted(this);
    // WARNING: RequestCompleted deletes us.
    return;
  }

  template_url_.reset(TemplateURLParser::Parse(fetcher_->profile(), false,
      data.data(), data.length(), NULL));
  if (!template_url_.get() ||
      !template_url_->url_ref().SupportsReplacement(
          UIThreadSearchTermsData(fetcher_->profile()))) {
    fetcher_->RequestCompleted(this);
    // WARNING: RequestCompleted deletes us.
    return;
  }

  if (provider_type_ != AUTODETECTED_PROVIDER || keyword_.empty()) {
    // Use the parser-generated new keyword from the URL in the OSDD for the
    // non-autodetected case.  The existing |keyword_| was generated from the
    // URL that hosted the OSDD, which results in the wrong keyword when the
    // OSDD was located on a third-party site that has nothing in common with
    // search engine described by OSDD.
    keyword_ = template_url_->keyword();
    DCHECK(!keyword_.empty());
  }

  // Wait for the model to be loaded before adding the provider.
  TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(
      fetcher_->profile());
  if (!model->loaded())
    return;
  AddSearchProvider();
  // WARNING: AddSearchProvider deletes us.
}

void TemplateURLFetcher::RequestDelegate::AddSearchProvider() {
  DCHECK(template_url_.get());
  DCHECK(!keyword_.empty());
  Profile* profile = fetcher_->profile();
  TemplateURLService* model = TemplateURLServiceFactory::GetForProfile(profile);
  DCHECK(model);
  DCHECK(model->loaded());

  TemplateURL* existing_url = NULL;
  if (model->CanReplaceKeyword(keyword_, GURL(template_url_->url()),
                               &existing_url)) {
    if (existing_url)
      model->Remove(existing_url);
  } else if (provider_type_ == AUTODETECTED_PROVIDER) {
    fetcher_->RequestCompleted(this);  // WARNING: Deletes us!
    return;
  }

  // The short name is what is shown to the user. We preserve original names
  // since it is better when generated keyword in many cases.
  TemplateURLData data(template_url_->data());
  data.SetKeyword(keyword_);
  data.originating_url = osdd_url_;

  // The page may have specified a URL to use for favicons, if not, set it.
  if (!data.favicon_url.is_valid())
    data.favicon_url = favicon_url_;

  switch (provider_type_) {
    case AUTODETECTED_PROVIDER:
      // Mark the keyword as replaceable so it can be removed if necessary.
      data.safe_for_autoreplace = true;
      model->Add(new TemplateURL(data));
      break;

    case EXPLICIT_PROVIDER:
      // Confirm addition and allow user to edit default choices. It's ironic
      // that only *non*-autodetected additions get confirmed, but the user
      // expects feedback that his action did something.
      // The source WebContents' delegate takes care of adding the URL to the
      // model, which takes ownership, or of deleting it if the add is
      // cancelled.
      callbacks_->ConfirmAddSearchProvider(new TemplateURL(data), profile);
      break;

    default:
      NOTREACHED();
      break;
  }

  fetcher_->RequestCompleted(this);
  // WARNING: RequestCompleted deletes us.
}

// TemplateURLFetcher ---------------------------------------------------------

TemplateURLFetcher::TemplateURLFetcher(Profile* profile) : profile_(profile) {
  DCHECK(profile_);
}

TemplateURLFetcher::~TemplateURLFetcher() {
}

void TemplateURLFetcher::ScheduleDownload(
    const base::string16& keyword,
    const GURL& osdd_url,
    const GURL& favicon_url,
    content::WebContents* web_contents,
    TemplateURLFetcherCallbacks* callbacks,
    ProviderType provider_type) {
  DCHECK(osdd_url.is_valid());
  scoped_ptr<TemplateURLFetcherCallbacks> owned_callbacks(callbacks);

  TemplateURLService* url_model =
      TemplateURLServiceFactory::GetForProfile(profile());
  if (!url_model)
    return;

  // For a JS-added OSDD, the provided keyword is irrelevant because we will
  // generate a keyword later from the OSDD content.  For the autodetected case,
  // we need a valid keyword up front.
  if (provider_type == TemplateURLFetcher::AUTODETECTED_PROVIDER) {
    DCHECK(!keyword.empty());

    if (!url_model->loaded()) {
      // We could try to set up a callback to this function again once the model
      // is loaded but since this is an auto-add case anyway, meh.
      url_model->Load();
      return;
    }

    const TemplateURL* template_url =
        url_model->GetTemplateURLForKeyword(keyword);
    if (template_url && (!template_url->safe_for_autoreplace() ||
                         template_url->originating_url() == osdd_url))
      return;
  }

  // Make sure we aren't already downloading this request.
  for (Requests::iterator i = requests_.begin(); i != requests_.end(); ++i) {
    if (((*i)->url() == osdd_url) ||
        ((provider_type == TemplateURLFetcher::AUTODETECTED_PROVIDER) &&
         ((*i)->keyword() == keyword)))
      return;
  }

  requests_.push_back(
      new RequestDelegate(this, keyword, osdd_url, favicon_url, web_contents,
                          owned_callbacks.release(), provider_type));
}

void TemplateURLFetcher::RequestCompleted(RequestDelegate* request) {
  Requests::iterator i =
      std::find(requests_.begin(), requests_.end(), request);
  DCHECK(i != requests_.end());
  requests_.weak_erase(i);
  delete request;
}
