1// Copyright 2012 The Chromium Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style license that can be 3// found in the LICENSE file. 4 5#ifndef CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_NAVIGATION_OBSERVER_H_ 6#define CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_NAVIGATION_OBSERVER_H_ 7 8#include <string> 9 10#include "base/memory/ref_counted.h" 11#include "base/memory/scoped_ptr.h" 12#include "components/omnibox/autocomplete_match.h" 13#include "content/public/browser/notification_observer.h" 14#include "content/public/browser/notification_registrar.h" 15#include "content/public/browser/web_contents_observer.h" 16#include "net/url_request/url_fetcher_delegate.h" 17 18class Profile; 19class ShortcutsBackend; 20 21namespace net { 22class URLFetcher; 23class URLRequestStatus; 24} 25 26// Monitors omnibox navigations in order to trigger behaviors that depend on 27// successful navigations. 28// 29// Currently two such behaviors exist: 30// (1) For single-word queries where we can't tell if the entry was a search or 31// an intranet hostname, the omnibox opens as a search by default, but this 32// class attempts to open as a URL via an HTTP HEAD request. If successful, 33// displays an infobar once the search result has also loaded. See 34// AlternateNavInfoBarDelegate. 35// (2) Omnibox navigations that complete successfully are added to the 36// Shortcuts backend. 37// 38// TODO(pkasting): Probably NOTIFICATION_OMNIBOX_OPENED_URL should disappear and 39// everyone who listened to it should be triggered from this class instead. 40// 41// The memory management of this object is a bit tricky. The OmniboxEditModel 42// will create us and be responsible for us until we attach as an observer 43// after a pending load starts (it will delete us if this doesn't happen). 44// Once this pending load starts, we're responsible for deleting ourselves. 45class OmniboxNavigationObserver : public content::NotificationObserver, 46 public content::WebContentsObserver, 47 public net::URLFetcherDelegate { 48 public: 49 enum LoadState { 50 LOAD_NOT_SEEN, 51 LOAD_PENDING, 52 LOAD_COMMITTED, 53 }; 54 55 OmniboxNavigationObserver(Profile* profile, 56 const base::string16& text, 57 const AutocompleteMatch& match, 58 const AutocompleteMatch& alternate_nav_match); 59 virtual ~OmniboxNavigationObserver(); 60 61 LoadState load_state() const { return load_state_; } 62 63 // Called directly by OmniboxEditModel when an extension-related navigation 64 // occurs. Such navigations don't trigger an immediate NAV_ENTRY_PENDING and 65 // must be handled separately. 66 void OnSuccessfulNavigation(); 67 68 private: 69 enum FetchState { 70 FETCH_NOT_COMPLETE, 71 FETCH_SUCCEEDED, 72 FETCH_FAILED, 73 }; 74 75 // content::NotificationObserver: 76 virtual void Observe(int type, 77 const content::NotificationSource& source, 78 const content::NotificationDetails& details) OVERRIDE; 79 80 // content::WebContentsObserver: 81 virtual void DidStartNavigationToPendingEntry( 82 const GURL& url, 83 content::NavigationController::ReloadType reload_type) OVERRIDE; 84 virtual void NavigationEntryCommitted( 85 const content::LoadCommittedDetails& load_details) OVERRIDE; 86 virtual void WebContentsDestroyed() OVERRIDE; 87 88 // net::URLFetcherDelegate: 89 virtual void OnURLFetchComplete(const net::URLFetcher* source) OVERRIDE; 90 91 // Once the load has committed and any URL fetch has completed, this displays 92 // the alternate nav infobar if necessary, and deletes |this|. 93 void OnAllLoadingFinished(); 94 95 const base::string16 text_; 96 const AutocompleteMatch match_; 97 const AutocompleteMatch alternate_nav_match_; 98 scoped_refptr<ShortcutsBackend> shortcuts_backend_; // NULL in incognito. 99 scoped_ptr<net::URLFetcher> fetcher_; 100 LoadState load_state_; 101 FetchState fetch_state_; 102 103 content::NotificationRegistrar registrar_; 104 105 DISALLOW_COPY_AND_ASSIGN(OmniboxNavigationObserver); 106}; 107 108#endif // CHROME_BROWSER_UI_OMNIBOX_OMNIBOX_NAVIGATION_OBSERVER_H_ 109