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_TEST_ALL_PREFIXES(SearchTabHelperTest,
105                           DetermineIfPageSupportsInstant_Local);
106  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
107                           DetermineIfPageSupportsInstant_NonLocal);
108  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
109                           PageURLDoesntBelongToInstantRenderer);
110  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
111                           OnChromeIdentityCheckMatch);
112  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
113                           OnChromeIdentityCheckMismatch);
114  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
115                           OnChromeIdentityCheckSignedOutMatch);
116  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
117                           OnChromeIdentityCheckSignedOutMismatch);
118  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperTest,
119                           OnChromeIdentityCheckMatchNotSyncing);
120  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperWindowTest,
121                           OnProvisionalLoadFailRedirectNTPToLocal);
122  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperWindowTest,
123                           OnProvisionalLoadFailDontRedirectIfAborted);
124  FRIEND_TEST_ALL_PREFIXES(SearchTabHelperWindowTest,
125                           OnProvisionalLoadFailDontRedirectNonNTP);
126  FRIEND_TEST_ALL_PREFIXES(SearchIPCRouterTest,
127                           IgnoreMessageIfThePageIsNotActive);
128  FRIEND_TEST_ALL_PREFIXES(SearchIPCRouterTest,
129                           DoNotSendSetDisplayInstantResultsMsg);
130  FRIEND_TEST_ALL_PREFIXES(SearchIPCRouterTest, HandleTabChangedEvents);
131  FRIEND_TEST_ALL_PREFIXES(InstantPageTest,
132                           DetermineIfPageSupportsInstant_Local);
133  FRIEND_TEST_ALL_PREFIXES(InstantPageTest,
134                           DetermineIfPageSupportsInstant_NonLocal);
135  FRIEND_TEST_ALL_PREFIXES(InstantPageTest,
136                           PageURLDoesntBelongToInstantRenderer);
137  FRIEND_TEST_ALL_PREFIXES(InstantPageTest, PageSupportsInstant);
138
139  explicit SearchTabHelper(content::WebContents* web_contents);
140
141  // Overridden from contents::WebContentsObserver:
142  virtual void RenderViewCreated(
143      content::RenderViewHost* render_view_host) OVERRIDE;
144  virtual void DidStartNavigationToPendingEntry(
145      const GURL& url,
146      content::NavigationController::ReloadType reload_type) OVERRIDE;
147  virtual void DidNavigateMainFrame(
148      const content::LoadCommittedDetails& details,
149      const content::FrameNavigateParams& params) OVERRIDE;
150  virtual void DidFailProvisionalLoad(
151      int64 frame_id,
152      const base::string16& frame_unique_name,
153      bool is_main_frame,
154      const GURL& validated_url,
155      int error_code,
156      const base::string16& error_description,
157      content::RenderViewHost* render_view_host) OVERRIDE;
158  virtual void DidFinishLoad(
159      int64 frame_id,
160      const GURL& validated_url,
161      bool is_main_frame,
162      content::RenderViewHost* render_view_host) OVERRIDE;
163  virtual void NavigationEntryCommitted(
164      const content::LoadCommittedDetails& load_details) OVERRIDE;
165
166  // Overridden from SearchIPCRouter::Delegate:
167  virtual void OnInstantSupportDetermined(bool supports_instant) OVERRIDE;
168  virtual void OnSetVoiceSearchSupport(bool supports_voice_search) OVERRIDE;
169  virtual void FocusOmnibox(OmniboxFocusState state) OVERRIDE;
170  virtual void NavigateToURL(const GURL& url,
171                             WindowOpenDisposition disposition,
172                             bool is_most_visited_item_url) OVERRIDE;
173  virtual void OnDeleteMostVisitedItem(const GURL& url) OVERRIDE;
174  virtual void OnUndoMostVisitedDeletion(const GURL& url) OVERRIDE;
175  virtual void OnUndoAllMostVisitedDeletions() OVERRIDE;
176  virtual void OnLogEvent(NTPLoggingEventType event) OVERRIDE;
177  virtual void OnLogMostVisitedImpression(
178      int position, const base::string16& provider) OVERRIDE;
179  virtual void OnLogMostVisitedNavigation(
180      int position, const base::string16& provider) OVERRIDE;
181  virtual void PasteIntoOmnibox(const base::string16& text) OVERRIDE;
182  virtual void OnChromeIdentityCheck(const base::string16& identity) OVERRIDE;
183
184  // Overridden from InstantServiceObserver:
185  virtual void ThemeInfoChanged(const ThemeBackgroundInfo& theme_info) OVERRIDE;
186  virtual void MostVisitedItemsChanged(
187      const std::vector<InstantMostVisitedItem>& items) OVERRIDE;
188  virtual void OmniboxStartMarginChanged(int omnibox_start_margin) OVERRIDE;
189
190  // Removes recommended URLs if a matching URL is already open in the Browser,
191  // if the Most Visited Tile Placement experiment is enabled, and the client is
192  // in the experiment group.
193  void MaybeRemoveMostVisitedItems(std::vector<InstantMostVisitedItem>* items);
194
195  // Sets the mode of the model based on the current URL of web_contents().
196  // Only updates the origin part of the mode if |update_origin| is true,
197  // otherwise keeps the current origin. If |is_preloaded_ntp| is true, the mode
198  // is set to NTP regardless of the current URL; this is used to ensure that
199  // InstantController can bind InstantTab to new tab pages immediately.
200  void UpdateMode(bool update_origin, bool is_preloaded_ntp);
201
202  // Tells the renderer to determine if the page supports the Instant API, which
203  // results in a call to OnInstantSupportDetermined() when the reply is
204  // received.
205  void DetermineIfPageSupportsInstant();
206
207  // Used by unit tests.
208  SearchIPCRouter& ipc_router() { return ipc_router_; }
209
210  Profile* profile() const;
211
212  // Helper function to navigate the given contents to the local fallback
213  // Instant URL and trim the history correctly.
214  void RedirectToLocalNTP();
215
216  // Returns whether input is in progress, i.e. if the omnibox has focus and the
217  // active tab is in mode SEARCH_SUGGESTIONS.
218  bool IsInputInProgress() const;
219
220  // Returns the OmniboxView for |web_contents_| or NULL if not available.
221  OmniboxView* GetOmniboxView() const;
222
223  const bool is_search_enabled_;
224
225  // Model object for UI that cares about search state.
226  SearchModel model_;
227
228  content::WebContents* web_contents_;
229
230  SearchIPCRouter ipc_router_;
231
232  InstantService* instant_service_;
233
234  // Delegate for notifying our owner about the SearchTabHelper state. Not owned
235  // by us.
236  // NULL on iOS and Android because they don't use the Instant framework.
237  SearchTabHelperDelegate* delegate_;
238
239  DISALLOW_COPY_AND_ASSIGN(SearchTabHelper);
240};
241
242#endif  // CHROME_BROWSER_UI_SEARCH_SEARCH_TAB_HELPER_H_
243