// 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 "chrome/browser/search_engines/search_provider_install_data.h"

#include <algorithm>
#include <functional>
#include <vector>

#include "base/basictypes.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/sequenced_task_runner_helpers.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/google/google_url_tracker.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search_engines/search_host_to_urls_map.h"
#include "chrome/browser/search_engines/search_terms_data.h"
#include "chrome/browser/search_engines/template_url.h"
#include "chrome/browser/search_engines/template_url_service.h"
#include "chrome/browser/search_engines/util.h"
#include "chrome/browser/webdata/web_data_service.h"
#include "content/public/browser/browser_thread.h"
#include "content/public/browser/notification_observer.h"
#include "content/public/browser/notification_registrar.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_source.h"

using content::BrowserThread;

typedef SearchHostToURLsMap::TemplateURLSet TemplateURLSet;

namespace {

// Implementation of SearchTermsData that may be used on the I/O thread.
class IOThreadSearchTermsData : public SearchTermsData {
 public:
  explicit IOThreadSearchTermsData(const std::string& google_base_url);

  // Implementation of SearchTermsData.
  virtual std::string GoogleBaseURLValue() const OVERRIDE;

 private:
  std::string google_base_url_;

  DISALLOW_COPY_AND_ASSIGN(IOThreadSearchTermsData);
};

IOThreadSearchTermsData::IOThreadSearchTermsData(
    const std::string& google_base_url) : google_base_url_(google_base_url) {
}

std::string IOThreadSearchTermsData::GoogleBaseURLValue() const {
  return google_base_url_;
}

// Handles telling SearchProviderInstallData about changes to the google base
// url. (Ensure that this is deleted on the I/O thread so that the WeakPtr is
// deleted on the correct thread.)
class GoogleURLChangeNotifier
    : public base::RefCountedThreadSafe<GoogleURLChangeNotifier,
                                        BrowserThread::DeleteOnIOThread> {
 public:
  explicit GoogleURLChangeNotifier(
      const base::WeakPtr<SearchProviderInstallData>& install_data);

  // Called on the I/O thread with the Google base URL whenever the value
  // changes.
  void OnChange(const std::string& google_base_url);

 private:
  friend struct BrowserThread::DeleteOnThread<BrowserThread::IO>;
  friend class base::DeleteHelper<GoogleURLChangeNotifier>;

  ~GoogleURLChangeNotifier() {}

  base::WeakPtr<SearchProviderInstallData> install_data_;

  DISALLOW_COPY_AND_ASSIGN(GoogleURLChangeNotifier);
};

GoogleURLChangeNotifier::GoogleURLChangeNotifier(
    const base::WeakPtr<SearchProviderInstallData>& install_data)
    : install_data_(install_data) {
}

void GoogleURLChangeNotifier::OnChange(const std::string& google_base_url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  if (install_data_.get())
    install_data_->OnGoogleURLChange(google_base_url);
}

// Notices changes in the Google base URL and sends them along
// to the SearchProviderInstallData on the I/O thread.
class GoogleURLObserver : public content::NotificationObserver {
 public:
  GoogleURLObserver(Profile* profile,
                    GoogleURLChangeNotifier* change_notifier,
                    int ui_death_notification,
                    const content::NotificationSource& ui_death_source);

  // Implementation of content::NotificationObserver.
  virtual void Observe(int type,
                       const content::NotificationSource& source,
                       const content::NotificationDetails& details) OVERRIDE;

 private:
  virtual ~GoogleURLObserver() {}

  scoped_refptr<GoogleURLChangeNotifier> change_notifier_;
  content::NotificationRegistrar registrar_;

  DISALLOW_COPY_AND_ASSIGN(GoogleURLObserver);
};

GoogleURLObserver::GoogleURLObserver(
    Profile* profile,
    GoogleURLChangeNotifier* change_notifier,
    int ui_death_notification,
    const content::NotificationSource& ui_death_source)
    : change_notifier_(change_notifier) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
  registrar_.Add(this, chrome::NOTIFICATION_GOOGLE_URL_UPDATED,
                 content::Source<Profile>(profile->GetOriginalProfile()));
  registrar_.Add(this, ui_death_notification, ui_death_source);
}

void GoogleURLObserver::Observe(int type,
                                const content::NotificationSource& source,
                                const content::NotificationDetails& details) {
  if (type == chrome::NOTIFICATION_GOOGLE_URL_UPDATED) {
    BrowserThread::PostTask(BrowserThread::IO, FROM_HERE,
        base::Bind(&GoogleURLChangeNotifier::OnChange, change_notifier_.get(),
            content::Details<GoogleURLTracker::UpdatedDetails>(details)->second.
                spec()));
  } else {
    // This must be the death notification.
    delete this;
  }
}

// Indicates if the two inputs have the same security origin.
// |requested_origin| should only be a security origin (no path, etc.).
// It is ok if |template_url| is NULL.
static bool IsSameOrigin(const GURL& requested_origin,
                         TemplateURL* template_url,
                         const SearchTermsData& search_terms_data) {
  DCHECK(requested_origin == requested_origin.GetOrigin());
  DCHECK(template_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION);
  return requested_origin ==
      TemplateURLService::GenerateSearchURLUsingTermsData(template_url,
          search_terms_data).GetOrigin();
}

}  // namespace

SearchProviderInstallData::SearchProviderInstallData(
    Profile* profile,
    int ui_death_notification,
    const content::NotificationSource& ui_death_source)
    : web_service_(WebDataService::FromBrowserContext(profile)),
      load_handle_(0),
      google_base_url_(UIThreadSearchTermsData(profile).GoogleBaseURLValue()) {
  // GoogleURLObserver is responsible for killing itself when
  // the given notification occurs.
  new GoogleURLObserver(profile, new GoogleURLChangeNotifier(AsWeakPtr()),
                        ui_death_notification, ui_death_source);
}

SearchProviderInstallData::~SearchProviderInstallData() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (load_handle_) {
    DCHECK(web_service_.get());
    web_service_->CancelRequest(load_handle_);
  }
}

void SearchProviderInstallData::CallWhenLoaded(const base::Closure& closure) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (provider_map_.get()) {
    closure.Run();
    return;
  }

  closure_queue_.push_back(closure);
  if (load_handle_)
    return;

  if (web_service_.get())
    load_handle_ = web_service_->GetKeywords(this);
  else
    OnLoadFailed();
}

SearchProviderInstallData::State SearchProviderInstallData::GetInstallState(
    const GURL& requested_origin) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
  DCHECK(provider_map_.get());

  // First check to see if the origin is the default search provider.
  if (requested_origin.spec() == default_search_origin_)
    return INSTALLED_AS_DEFAULT;

  // Is the url any search provider?
  const TemplateURLSet* urls = provider_map_->GetURLsForHost(
      requested_origin.host());
  if (!urls)
    return NOT_INSTALLED;

  IOThreadSearchTermsData search_terms_data(google_base_url_);
  for (TemplateURLSet::const_iterator i = urls->begin();
       i != urls->end(); ++i) {
    if (IsSameOrigin(requested_origin, *i, search_terms_data))
      return INSTALLED_BUT_NOT_DEFAULT;
  }
  return NOT_INSTALLED;
}

void SearchProviderInstallData::OnGoogleURLChange(
    const std::string& google_base_url) {
  google_base_url_ = google_base_url;
}

void SearchProviderInstallData::OnWebDataServiceRequestDone(
    WebDataService::Handle h,
    const WDTypedResult* result) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  // Reset the load_handle so that we don't try and cancel the load in
  // the destructor.
  load_handle_ = 0;

  if (!result) {
    // Results are null if the database went away or (most likely) wasn't
    // loaded.
    OnLoadFailed();
    return;
  }

  TemplateURL* default_search_provider = NULL;
  int new_resource_keyword_version = 0;
  std::vector<TemplateURL*> extracted_template_urls;
  GetSearchProvidersUsingKeywordResult(*result, NULL, NULL,
      &extracted_template_urls, &default_search_provider,
      &new_resource_keyword_version, NULL);
  template_urls_.get().insert(template_urls_.get().begin(),
                              extracted_template_urls.begin(),
                              extracted_template_urls.end());
  IOThreadSearchTermsData search_terms_data(google_base_url_);
  provider_map_.reset(new SearchHostToURLsMap());
  provider_map_->Init(template_urls_.get(), search_terms_data);
  SetDefault(default_search_provider);
  NotifyLoaded();
}

void SearchProviderInstallData::SetDefault(const TemplateURL* template_url) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  if (!template_url) {
    default_search_origin_.clear();
    return;
  }

  DCHECK(template_url->GetType() != TemplateURL::OMNIBOX_API_EXTENSION);

  IOThreadSearchTermsData search_terms_data(google_base_url_);
  const GURL url(TemplateURLService::GenerateSearchURLUsingTermsData(
      template_url, search_terms_data));
  if (!url.is_valid() || !url.has_host()) {
    default_search_origin_.clear();
    return;
  }
  default_search_origin_ = url.GetOrigin().spec();
}

void SearchProviderInstallData::OnLoadFailed() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  provider_map_.reset(new SearchHostToURLsMap());
  IOThreadSearchTermsData search_terms_data(google_base_url_);
  provider_map_->Init(template_urls_.get(), search_terms_data);
  SetDefault(NULL);
  NotifyLoaded();
}

void SearchProviderInstallData::NotifyLoaded() {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));

  std::vector<base::Closure> closure_queue;
  closure_queue.swap(closure_queue_);

  std::for_each(closure_queue.begin(),
                closure_queue.end(),
                std::mem_fun_ref(&base::Closure::Run));

  // Since we expect this request to be rare, clear out the information. This
  // also keeps the responses current as the search providers change.
  provider_map_.reset();
  SetDefault(NULL);
}
