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_SEARCH_SEARCH_TAB_HELPER_H_
6#define CHROME_BROWSER_UI_SEARCH_SEARCH_TAB_HELPER_H_
7
8#include <vector>
9
10#include "base/basictypes.h"
11#include "base/compiler_specific.h"
12#include "base/gtest_prod_util.h"
13#include "chrome/browser/search/instant_service_observer.h"
14#include "chrome/browser/ui/search/search_ipc_router.h"
15#include "chrome/browser/ui/search/search_model.h"
16#include "chrome/common/instant_types.h"
17#include "chrome/common/ntp_logging_events.h"
18#include "chrome/common/omnibox_focus_state.h"
19#include "content/public/browser/web_contents_observer.h"
20#include "content/public/browser/web_contents_user_data.h"
21#include "ui/base/window_open_disposition.h"
22
23namespace content {
24class WebContents;
25struct LoadCommittedDetails;
26}
27
28class GURL;
29class InstantPageTest;
30class InstantService;
31class OmniboxView;
32class Profile;
33class SearchIPCRouterTest;
34class SearchTabHelperDelegate;
35
36// Per-tab search "helper".  Acts as the owner and controller of the tab's
37// search UI model.
38//
39// When the page is finished loading, SearchTabHelper determines the instant
40// support for the page. When a navigation entry is committed (except for
41// in-page navigations), SearchTabHelper resets the instant support state to
42// INSTANT_SUPPORT_UNKNOWN and cause support to be determined again.
43class SearchTabHelper : public content::WebContentsObserver,
44                        public content::WebContentsUserData<SearchTabHelper>,
45                        public InstantServiceObserver,
46                        public SearchIPCRouter::Delegate {
47 public:
48  virtual ~SearchTabHelper();
49
50  SearchModel* model() {
51    return &model_;
52  }
53
54  // Sets up the initial state correctly for a preloaded NTP.
55  void InitForPreloadedNTP();
56
57  // Invoked when the omnibox input state is changed in some way that might
58  // affect the search mode.
59  void OmniboxInputStateChanged();
60
61  // Called to indicate that the omnibox focus state changed with the given
62  // |reason|.
63  void OmniboxFocusChanged(OmniboxFocusState state,
64                           OmniboxFocusChangeReason reason);
65
66  // Invoked when the active navigation entry is updated in some way that might
67  // affect the search mode. This is used by Instant when it "fixes up" the
68  // virtual URL of the active entry. Regular navigations are captured through
69  // the notification system and shouldn't call this method.
70  void NavigationEntryUpdated();
71
72  // Invoked to update the instant support state.
73  void InstantSupportChanged(bool supports_instant);
74
75  // Returns true if the page supports instant. If the instant support state is
76  // not determined or if the page does not support instant returns false.
77  bool SupportsInstant() const;
78
79  // Sends the current SearchProvider suggestion to the Instant page if any.
80  void SetSuggestionToPrefetch(const InstantSuggestion& suggestion);
81
82  // Tells the page that the user pressed Enter in the omnibox.
83  void Submit(const base::string16& text);
84
85  // Called when the tab corresponding to |this| instance is activated.
86  void OnTabActivated();
87
88  // Called when the tab corresponding to |this| instance is deactivated.
89  void OnTabDeactivated();
90
91  // Tells the page to toggle voice search.
92  void ToggleVoiceSearch();
93
94  // Returns true if the underlying page is a search results page.
95  bool IsSearchResultsPage();
96
97  void set_delegate(SearchTabHelperDelegate* delegate) { delegate_ = delegate; }
98
99 private:
100  friend class content::WebContentsUserData<SearchTabHelper>;
101  friend class InstantPageTest;
102  friend class SearchIPCRouterPolicyTest;
103  friend class SearchIPCRouterTest;
104  friend class SearchTabHelperPrerenderTest;
105
106  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
107                           DetermineIfPageSupportsInstant_Local);
108  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
109                           DetermineIfPageSupportsInstant_NonLocal);
110  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
111                           PageURLDoesntBelongToInstantRenderer);
112  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
113                           OnChromeIdentityCheckMatch);
114  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
115                           OnChromeIdentityCheckMismatch);
116  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
117                           OnChromeIdentityCheckSignedOutMatch);
118  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
119                           OnChromeIdentityCheckSignedOutMismatch);
120  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
121                           OnChromeIdentityCheckMatchNotSyncing);
122  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperWindowTest,
123                           OnProvisionalLoadFailRedirectNTPToLocal);
124  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperWindowTest,
125                           OnProvisionalLoadFailDontRedirectIfAborted);
126  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperWindowTest,
127                           OnProvisionalLoadFailDontRedirectNonNTP);
128  FRIEND_TEST_ALL_PREFIXES(SearchIPCRouterTest,
129                           IgnoreMessageIfThePageIsNotActive);
130  FRIEND_TEST_ALL_PREFIXES(SearchIPCRouterTest,
131                           DoNotSendSetDisplayInstantResultsMsg);
132  FRIEND_TEST_ALL_PREFIXES(SearchIPCRouterTest, HandleTabChangedEvents);
133  FRIEND_TEST_ALL_PREFIXES(InstantPageTest,
134                           DetermineIfPageSupportsInstant_Local);
135  FRIEND_TEST_ALL_PREFIXES(InstantPageTest,
136                           DetermineIfPageSupportsInstant_NonLocal);
137  FRIEND_TEST_ALL_PREFIXES(InstantPageTest,
138                           PageURLDoesntBelongToInstantRenderer);
139  FRIEND_TEST_ALL_PREFIXES(InstantPageTest, PageSupportsInstant);
140
141  explicit SearchTabHelper(content::WebContents* web_contents);
142
143  // Overridden from contents::WebContentsObserver:
144  virtual void RenderViewCreated(
145      content::RenderViewHost* render_view_host) OVERRIDE;
146  virtual void DidStartNavigationToPendingEntry(
147      const GURL& url,
148      content::NavigationController::ReloadType reload_type) OVERRIDE;
149  virtual void DidNavigateMainFrame(
150      const content::LoadCommittedDetails& details,
151      const content::FrameNavigateParams& params) OVERRIDE;
152  virtual void DidFailProvisionalLoad(
153      content::RenderFrameHost* render_frame_host,
154      const GURL& validated_url,
155      int error_code,
156      const base::string16& error_description) OVERRIDE;
157  virtual void DidFinishLoad(content::RenderFrameHost* render_frame_host,
158                             const GURL& validated_url) OVERRIDE;
159  virtual void NavigationEntryCommitted(
160      const content::LoadCommittedDetails& load_details) OVERRIDE;
161
162  // Overridden from SearchIPCRouter::Delegate:
163  virtual void OnInstantSupportDetermined(bool supports_instant) OVERRIDE;
164  virtual void OnSetVoiceSearchSupport(bool supports_voice_search) OVERRIDE;
165  virtual void FocusOmnibox(OmniboxFocusState state) OVERRIDE;
166  virtual void NavigateToURL(const GURL& url,
167                             WindowOpenDisposition disposition,
168                             bool is_most_visited_item_url) OVERRIDE;
169  virtual void OnDeleteMostVisitedItem(const GURL& url) OVERRIDE;
170  virtual void OnUndoMostVisitedDeletion(const GURL& url) OVERRIDE;
171  virtual void OnUndoAllMostVisitedDeletions() OVERRIDE;
172  virtual void OnLogEvent(NTPLoggingEventType event) OVERRIDE;
173  virtual void OnLogMostVisitedImpression(
174      int position, const base::string16& provider) OVERRIDE;
175  virtual void OnLogMostVisitedNavigation(
176      int position, const base::string16& provider) OVERRIDE;
177  virtual void PasteIntoOmnibox(const base::string16& text) OVERRIDE;
178  virtual void OnChromeIdentityCheck(const base::string16& identity) OVERRIDE;
179
180  // Overridden from InstantServiceObserver:
181  virtual void ThemeInfoChanged(const ThemeBackgroundInfo& theme_info) OVERRIDE;
182  virtual void MostVisitedItemsChanged(
183      const std::vector<InstantMostVisitedItem>& items) OVERRIDE;
184  virtual void OmniboxStartMarginChanged(int omnibox_start_margin) OVERRIDE;
185
186  // Sets the mode of the model based on the current URL of web_contents().
187  // Only updates the origin part of the mode if |update_origin| is true,
188  // otherwise keeps the current origin. If |is_preloaded_ntp| is true, the mode
189  // is set to NTP regardless of the current URL; this is used to ensure that
190  // InstantController can bind InstantTab to new tab pages immediately.
191  void UpdateMode(bool update_origin, bool is_preloaded_ntp);
192
193  // Tells the renderer to determine if the page supports the Instant API, which
194  // results in a call to OnInstantSupportDetermined() when the reply is
195  // received.
196  void DetermineIfPageSupportsInstant();
197
198  // Used by unit tests.
199  SearchIPCRouter& ipc_router() { return ipc_router_; }
200
201  Profile* profile() const;
202
203  // Helper function to navigate the given contents to the local fallback
204  // Instant URL and trim the history correctly.
205  void RedirectToLocalNTP();
206
207  // Returns whether input is in progress, i.e. if the omnibox has focus and the
208  // active tab is in mode SEARCH_SUGGESTIONS.
209  bool IsInputInProgress() const;
210
211  // Returns the OmniboxView for |web_contents_| or NULL if not available.
212  OmniboxView* GetOmniboxView() const;
213
214  typedef bool (*OmniboxHasFocusFn)(OmniboxView*);
215
216  void set_omnibox_has_focus_fn(OmniboxHasFocusFn fn) {
217    omnibox_has_focus_fn_ = fn;
218  }
219
220  const bool is_search_enabled_;
221
222  // Model object for UI that cares about search state.
223  SearchModel model_;
224
225  content::WebContents* web_contents_;
226
227  SearchIPCRouter ipc_router_;
228
229  InstantService* instant_service_;
230
231  // Delegate for notifying our owner about the SearchTabHelper state. Not owned
232  // by us.
233  // NULL on iOS and Android because they don't use the Instant framework.
234  SearchTabHelperDelegate* delegate_;
235
236  // Function to check if the omnibox has focus. Tests use this to modify the
237  // default behavior.
238  OmniboxHasFocusFn omnibox_has_focus_fn_;
239
240  DISALLOW_COPY_AND_ASSIGN(SearchTabHelper);
241};
242
243#endif  // CHROME_BROWSER_UI_SEARCH_SEARCH_TAB_HELPER_H_
244