14e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 24e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 34e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// found in the LICENSE file. 44e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 54e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/omnibox/omnibox_navigation_observer.h" 64e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 723730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/browser/autocomplete/shortcuts_backend.h" 823730a6e56a168d1879203e4b3819bb36e3d8f1fTorne (Richard Coles)#include "chrome/browser/autocomplete/shortcuts_backend_factory.h" 94e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/infobars/infobar_service.h" 104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/intranet_redirect_detector.h" 114e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "chrome/browser/ui/omnibox/alternate_nav_infobar_delegate.h" 124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/browser_context.h" 134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/navigation_controller.h" 144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/navigation_details.h" 154e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/navigation_entry.h" 164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/notification_service.h" 174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/notification_types.h" 184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "content/public/browser/web_contents.h" 194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/base/load_flags.h" 204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/base/registry_controlled_domains/registry_controlled_domain.h" 214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/url_request/url_fetcher.h" 224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)#include "net/url_request/url_request.h" 234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Helpers -------------------------------------------------------------------- 264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)namespace { 284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// HTTP 2xx, 401, and 407 all indicate that the target address exists. 304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool ResponseCodeIndicatesSuccess(int response_code) { 314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return ((response_code / 100) == 2) || (response_code == 401) || 324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) (response_code == 407); 334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// Returns true if |final_url| doesn't represent an ISP hijack of 364e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// |original_url|, based on the IntranetRedirectDetector's RedirectOrigin(). 374e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)bool IsValidNavigation(const GURL& original_url, const GURL& final_url) { 384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GURL& redirect_url(IntranetRedirectDetector::RedirectOrigin()); 394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) return !redirect_url.is_valid() || 404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) net::registry_controlled_domains::SameDomainOrHost( 414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) original_url, final_url, 424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES) || 434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) !net::registry_controlled_domains::SameDomainOrHost( 444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) final_url, redirect_url, 454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) net::registry_controlled_domains::EXCLUDE_PRIVATE_REGISTRIES); 464e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} // namespace 494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 504e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 514e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)// OmniboxNavigationObserver -------------------------------------------------- 524e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 534e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)OmniboxNavigationObserver::OmniboxNavigationObserver( 544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) Profile* profile, 55a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) const base::string16& text, 564e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const AutocompleteMatch& match, 57f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const AutocompleteMatch& alternate_nav_match) 584e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) : text_(text), 594e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) match_(match), 60f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) alternate_nav_match_(alternate_nav_match), 614e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) shortcuts_backend_(ShortcutsBackendFactory::GetForProfile(profile)), 624e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) load_state_(LOAD_NOT_SEEN), 634e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) fetch_state_(FETCH_NOT_COMPLETE) { 64f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (alternate_nav_match_.destination_url.is_valid()) { 65f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) fetcher_.reset(net::URLFetcher::Create(alternate_nav_match_.destination_url, 664e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) net::URLFetcher::HEAD, this)); 674e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SAVE_COOKIES); 684e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) fetcher_->SetStopOnRedirect(true); 694e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 704e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // We need to start by listening to AllSources, since we don't know which tab 714e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) // the navigation might occur in. 724e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) registrar_.Add(this, content::NOTIFICATION_NAV_ENTRY_PENDING, 734e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) content::NotificationService::AllSources()); 744e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 754e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 764e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)OmniboxNavigationObserver::~OmniboxNavigationObserver() { 774e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 784e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 794e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void OmniboxNavigationObserver::OnSuccessfulNavigation() { 801320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (shortcuts_backend_.get()) 81f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) shortcuts_backend_->AddOrUpdateShortcut(text_, match_); 824e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 834e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 844e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void OmniboxNavigationObserver::Observe( 854e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int type, 864e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const content::NotificationSource& source, 874e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const content::NotificationDetails& details) { 884e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_EQ(content::NOTIFICATION_NAV_ENTRY_PENDING, type); 894e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) registrar_.Remove(this, content::NOTIFICATION_NAV_ENTRY_PENDING, 904e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) content::NotificationService::AllSources()); 914e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) content::NavigationController* controller = 924e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) content::Source<content::NavigationController>(source).ptr(); 934e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (fetcher_) { 944e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) fetcher_->SetRequestContext( 954e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) controller->GetBrowserContext()->GetRequestContext()); 964e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 974e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) WebContentsObserver::Observe(controller->GetWebContents()); 98f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) // DidStartNavigationToPendingEntry() will be called for this load as well. 994e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1004e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1014e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void OmniboxNavigationObserver::NavigationEntryCommitted( 1024e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const content::LoadCommittedDetails& load_details) { 1034e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) load_state_ = LOAD_COMMITTED; 1044e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (ResponseCodeIndicatesSuccess(load_details.http_status_code) && 1054e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) IsValidNavigation(match_.destination_url, load_details.entry->GetURL())) 1064e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OnSuccessfulNavigation(); 1074e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (!fetcher_ || (fetch_state_ != FETCH_NOT_COMPLETE)) 1084e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OnAllLoadingFinished(); // deletes |this|! 1094e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1104e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 111010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)void OmniboxNavigationObserver::WebContentsDestroyed() { 1124e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) delete this; 1134e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1144e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 115f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)void OmniboxNavigationObserver::DidStartNavigationToPendingEntry( 1164e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const GURL& url, 1174e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) content::NavigationController::ReloadType reload_type) { 1184e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (load_state_ == LOAD_NOT_SEEN) { 1194e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) load_state_ = LOAD_PENDING; 1204e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (fetcher_) 1214e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) fetcher_->Start(); 1224e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } else { 1234e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) delete this; 1244e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1254e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1264e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1274e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void OmniboxNavigationObserver::OnURLFetchComplete( 1284e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const net::URLFetcher* source) { 1294e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) DCHECK_EQ(fetcher_.get(), source); 1304e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) const net::URLRequestStatus& status = source->GetStatus(); 1314e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) int response_code = source->GetResponseCode(); 1324e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) fetch_state_ = 1334e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) (status.is_success() && ResponseCodeIndicatesSuccess(response_code)) || 1344e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ((status.status() == net::URLRequestStatus::CANCELED) && 1354e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) ((response_code / 100) == 3) && 136f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) IsValidNavigation(alternate_nav_match_.destination_url, 137f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) source->GetURL())) ? 1384e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) FETCH_SUCCEEDED : FETCH_FAILED; 1394e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (load_state_ == LOAD_COMMITTED) 1404e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) OnAllLoadingFinished(); // deletes |this|! 1414e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 1424e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) 1434e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)void OmniboxNavigationObserver::OnAllLoadingFinished() { 1444e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) if (fetch_state_ == FETCH_SUCCEEDED) { 1454e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) AlternateNavInfoBarDelegate::Create( 146f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) web_contents(), text_, alternate_nav_match_, match_.destination_url); 1474e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) } 1484e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles) delete this; 1494e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)} 150