// 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/ui/omnibox/omnibox_navigation_observer.h"

#include "chrome/browser/autocomplete/shortcuts_backend.h"
#include "chrome/browser/autocomplete/shortcuts_backend_factory.h"
#include "chrome/browser/infobars/infobar_service.h"
#include "chrome/browser/intranet_redirect_detector.h"
#include "chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h"
#include "content/public/browser/browser_context.h"
#include "content/public/browser/navigation_controller.h"
#include "content/public/browser/navigation_details.h"
#include "content/public/browser/navigation_entry.h"
#include "content/public/browser/notification_service.h"
#include "content/public/browser/notification_types.h"
#include "content/public/browser/web_contents.h"
#include "net/base/load_flags.h"
#include "net/base/registry_controlled_domains/registry_controlled_domain.h"
#include "net/url_request/url_fetcher.h"
#include "net/url_request/url_request.h"


// Helpers --------------------------------------------------------------------

namespace {

// HTTP 2xx, 401, and 407 all indicate that the target address exists.
bool ResponseCodeIndicatesSuccess(int response_code) {
  return ((response_code / 100) == 2) || (response_code == 401) ||
      (response_code == 407);
}

// Returns true if |final_url| doesn't represent an ISP hijack of
// |original_url|, based on the IntranetRedirectDetector's RedirectOrigin().
bool IsValidNavigation(const GURL& original_url, const GURL& final_url) {
  const GURL& redirect_url(IntranetRedirectDetector::RedirectOrigin());
  return !redirect_url.is_valid() ||
      net::registry_controlled_domains::SameDomainOrHost(
          original_url, final_url,
          net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES) ||
      !net::registry_controlled_domains::SameDomainOrHost(
          final_url, redirect_url,
          net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES);
}

}  // namespace


// OmniboxNavigationObserver --------------------------------------------------

OmniboxNavigationObserver::OmniboxNavigationObserver(
    Profile* profile,
    const base::string16& text,
    const AutocompleteMatch& match,
    const AutocompleteMatch& alternate_nav_match)
    : text_(text),
      match_(match),
      alternate_nav_match_(alternate_nav_match),
      shortcuts_backend_(ShortcutsBackendFactory::GetForProfile(profile)),
      load_state_(LOAD_NOT_SEEN),
      fetch_state_(FETCH_NOT_COMPLETE) {
  if (alternate_nav_match_.destination_url.is_valid()) {
    fetcher_.reset(net::URLFetcher::Create(alternate_nav_match_.destination_url,
                                           net::URLFetcher::HEAD, this));
    fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES);
    fetcher_->SetStopOnRedirect(true);
  }
  // We need to start by listening to AllSources, since we don't know which tab
  // the navigation might occur in.
  registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
                 content::NotificationService::AllSources());
}

OmniboxNavigationObserver::~OmniboxNavigationObserver() {
}

void OmniboxNavigationObserver::OnSuccessfulNavigation() {
  if (shortcuts_backend_)
    shortcuts_backend_->AddOrUpdateShortcut(text_, match_);
}

void OmniboxNavigationObserver::Observe(
    int type,
    const content::NotificationSource& source,
    const content::NotificationDetails& details) {
  DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_PENDING, type);
  registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING,
                    content::NotificationService::AllSources());
  content::NavigationController* controller =
      content::Source<content::NavigationController>(source).ptr();
  if (fetcher_) {
    fetcher_->SetRequestContext(
        controller->GetBrowserContext()->GetRequestContext());
  }
  WebContentsObserver::Observe(controller->GetWebContents());
  // DidStartNavigationToPendingEntry() will be called for this load as well.
}

void OmniboxNavigationObserver::NavigationEntryCommitted(
    const content::LoadCommittedDetails& load_details) {
  load_state_ = LOAD_COMMITTED;
  if (ResponseCodeIndicatesSuccess(load_details.http_status_code) &&
      IsValidNavigation(match_.destination_url, load_details.entry->GetURL()))
    OnSuccessfulNavigation();
  if (!fetcher_ || (fetch_state_ != FETCH_NOT_COMPLETE))
    OnAllLoadingFinished();  // deletes |this|!
}

void OmniboxNavigationObserver::WebContentsDestroyed() {
  delete this;
}

void OmniboxNavigationObserver::DidStartNavigationToPendingEntry(
    const GURL& url,
    content::NavigationController::ReloadType reload_type) {
  if (load_state_ == LOAD_NOT_SEEN) {
    load_state_ = LOAD_PENDING;
    if (fetcher_)
      fetcher_->Start();
  } else {
    delete this;
  }
}

void OmniboxNavigationObserver::OnURLFetchComplete(
    const net::URLFetcher* source) {
  DCHECK_EQ(fetcher_.get(), source);
  const net::URLRequestStatus& status = source->GetStatus();
  int response_code = source->GetResponseCode();
  fetch_state_ =
      (status.is_success() && ResponseCodeIndicatesSuccess(response_code)) ||
      ((status.status() == net::URLRequestStatus::CANCELED) &&
       ((response_code / 100) == 3) &&
       IsValidNavigation(alternate_nav_match_.destination_url,
                         source->GetURL())) ?
          FETCH_SUCCEEDED : FETCH_FAILED;
  if (load_state_ == LOAD_COMMITTED)
    OnAllLoadingFinished();  // deletes |this|!
}

void OmniboxNavigationObserver::OnAllLoadingFinished() {
  if (fetch_state_ == FETCH_SUCCEEDED) {
    AlternateNavInfoBarDelegate::Create(
        web_contents(), text_, alternate_nav_match_, match_.destination_url);
  }
  delete this;
}
