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