1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
|
// Copyright (c) 2012 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef CHROME_BROWSER_INSTANT_INSTANT_CONTROLLER_H_
#define CHROME_BROWSER_INSTANT_INSTANT_CONTROLLER_H_
#include <map>
#include <string>
#include <vector>
#include "base/basictypes.h"
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/memory/scoped_ptr.h"
#include "base/string16.h"
#include "base/timer.h"
#include "chrome/browser/instant/instant_commit_type.h"
#include "chrome/browser/instant/instant_loader_delegate.h"
#include "chrome/browser/instant/instant_model.h"
#include "chrome/common/instant_types.h"
#include "content/public/common/page_transition_types.h"
#include "googleurl/src/gurl.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/rect.h"
struct AutocompleteMatch;
class AutocompleteProvider;
class InstantControllerDelegate;
class InstantLoader;
class PrefService;
class Profile;
class TabContents;
class TemplateURL;
// InstantController maintains a WebContents that is intended to give a
// preview of search results. InstantController is owned by Browser via
// BrowserInstantController.
//
// At any time the WebContents maintained by InstantController may be hidden
// from view by way of Hide(), which may result in a change in the model's
// display state and subsequent change in model observers. Similarly the preview
// may be committed at any time by invoking CommitCurrentPreview(), which
// results in CommitInstant() being invoked on the delegate.
class InstantController : public InstantLoaderDelegate {
public:
// Amount of time to wait before starting the animation for suggested text.
static const int kInlineAutocompletePauseTimeMS = 1000;
// Duration of the suggested text animation in which the colors change.
static const int kInlineAutocompleteFadeInTimeMS = 300;
// InstantController may operate in one of these modes:
// EXTENDED: The default search engine is preloaded when the omnibox gets
// focus. Queries are issued as the user types. Predicted queries are
// inline autocompleted into the omnibox. Previews of search results
// as well as predicted URLs are shown. Search suggestions are rendered
// within the search results preview.
// INSTANT: Same as EXTENDED, without URL previews. Search suggestions are
// rendered by the omnibox drop down, and not by the preview page.
// SUGGEST: Same as INSTANT, without visible previews.
// HIDDEN: Same as SUGGEST, without the inline autocompletion.
// SILENT: Same as HIDDEN, without issuing queries as the user types. The
// query is sent only after the user presses <Enter>.
// DISABLED: Instant is disabled.
enum Mode {
EXTENDED,
INSTANT,
SUGGEST,
HIDDEN,
SILENT,
DISABLED,
};
virtual ~InstantController();
// Creates a new InstantController. Caller owns the returned object. The
// |profile| pointer is not cached, so the underlying profile object need not
// live beyond this call. ***NOTE***: May return NULL, which means that
// Instant is disabled in this profile.
static InstantController* CreateInstant(Profile* profile,
InstantControllerDelegate* delegate);
// Returns true if Instant is enabled and supports the extended API.
static bool IsExtendedAPIEnabled(Profile* profile);
// Returns true if Instant is enabled in a visible, preview-showing mode.
static bool IsInstantEnabled(Profile* profile);
// Returns true if Instant will provide autocomplete suggestions.
static bool IsSuggestEnabled(Profile* profile);
// Registers Instant related preferences.
static void RegisterUserPrefs(PrefService* prefs);
// Invoked as the user types into the omnibox. |user_text| is what the user
// has typed. |full_text| is what the omnibox is showing. These may differ if
// the user typed only some text, and the rest was inline autocompleted. If
// |verbatim| is true, search results are shown for the exact omnibox text,
// rather than the best guess as to what the user means. Returns true if the
// update is accepted (i.e., if |match| is a search rather than a URL).
bool Update(const AutocompleteMatch& match,
const string16& user_text,
const string16& full_text,
bool verbatim);
// Sets the bounds of the omnibox dropdown, in screen coordinates.
void SetOmniboxBounds(const gfx::Rect& bounds);
// Send autocomplete results from |providers| to the preview page.
void HandleAutocompleteResults(
const std::vector<AutocompleteProvider*>& providers);
// Called when the user presses up or down. |count| is a repeat count,
// negative for moving up, positive for moving down. Returns true if Instant
// handled the key press.
bool OnUpOrDownKeyPressed(int count);
// The preview TabContents. May be NULL if ReleasePreviewContents() has been
// called, with no subsequent successful call to Update(). InstantController
// retains ownership of the object.
TabContents* GetPreviewContents() const;
// Hides the preview, but doesn't destroy it, in hopes it can be subsequently
// reused. The preview will not be used until a call to Update() succeeds.
void Hide();
// Returns true if the Instant preview can be committed now. This can be true
// even if the preview is not showing yet, because we can commit as long as
// we've processed the last Update() and we know the loader supports Instant.
bool IsCurrent() const;
// Commits the preview. Calls CommitInstant() on the delegate.
void CommitCurrentPreview(InstantCommitType type);
// The autocomplete edit that was initiating the current Instant session has
// lost focus. Commit or discard the preview accordingly.
void OnAutocompleteLostFocus(gfx::NativeView view_gaining_focus);
// The autocomplete edit has gained focus. Preload the Instant URL of the
// default search engine, in anticipation of the user typing a query.
void OnAutocompleteGotFocus();
// The active tab's "NTP status" has changed. Pass the message down to the
// loader which will notify the renderer.
void OnActiveTabModeChanged(bool active_tab_is_ntp);
// Returns whether the preview will be committed when the mouse or touch
// pointer is released.
bool commit_on_pointer_release() const;
// Returns the transition type of the last AutocompleteMatch passed to Update.
content::PageTransition last_transition_type() const {
return last_transition_type_;
}
// InstantLoaderDelegate:
virtual void SetSuggestions(
InstantLoader* loader,
const std::vector<InstantSuggestion>& suggestions) OVERRIDE;
virtual void CommitInstantLoader(InstantLoader* loader) OVERRIDE;
virtual void ShowInstantPreview(InstantLoader* loader,
InstantShownReason reason,
int height,
InstantSizeUnits units) OVERRIDE;
virtual void InstantLoaderPreviewLoaded(InstantLoader* loader) OVERRIDE;
virtual void InstantSupportDetermined(InstantLoader* loader,
bool supports_instant) OVERRIDE;
virtual void SwappedTabContents(InstantLoader* loader) OVERRIDE;
virtual void InstantLoaderContentsFocused(InstantLoader* loader) OVERRIDE;
#if defined(UNIT_TEST)
// Accessors used only in tests.
InstantLoader* loader() const { return loader_.get(); }
#endif
const InstantModel* model() const { return &model_; }
private:
FRIEND_TEST_ALL_PREFIXES(InstantTest, InstantLoaderRefresh);
InstantController(InstantControllerDelegate* delegate, Mode mode);
// Creates a new loader if necessary (for example, if the |instant_url| has
// changed since the last time we created the loader).
void ResetLoader(const std::string& instant_url,
const TabContents* active_tab);
// Ensures that the |loader_| uses the default Instant URL, recreating it if
// necessary, and returns true. Returns false if the Instant URL could not be
// determined or the active tab is NULL (browser is shutting down).
bool CreateDefaultLoader();
// If the |loader_| is not showing, it is deleted and recreated. Else the
// refresh is skipped and the next refresh is scheduled.
void OnStaleLoader();
// Calls OnStaleLoader if |stale_loader_timer_| is not running.
void MaybeOnStaleLoader();
// Destroys the |loader_| and its preview contents.
void DeleteLoader();
// Counterpart to Hide(). Asks the |delegate_| to display the preview with
// the given |height|.
void Show(int height, InstantSizeUnits units);
// Send the omnibox dropdown bounds to the page.
void SendBoundsToPage();
// If |template_url| is a valid TemplateURL for use with Instant, fills in
// |instant_url| and returns true; returns false otherwise.
// Note: If the command-line switch kInstantURL is set, this method uses its
// value for |instant_url| and returns true without examining |template_url|.
bool GetInstantURL(const TemplateURL* template_url,
const GURL& tab_url,
std::string* instant_url) const;
// Returns true if the preview is no longer relevant, say because the last
// Update() was for a URL and not a search query, or the user switched tabs.
bool IsOutOfDate() const;
InstantControllerDelegate* const delegate_;
InstantModel model_;
scoped_ptr<InstantLoader> loader_;
// See the enum description above.
const Mode mode_;
// The active tab at the time of the last Update(). Used by IsOutOfDate() to
// know whether the user switched tabs. ***NEVER DEREFERENCE THIS POINTER.***
// It may be a dangling pointer to a freed object. Should only be used for
// pointer comparisons.
const void* last_active_tab_;
// The most recent full_text passed to Update().
string16 last_full_text_;
// The most recent user_text passed to Update().
string16 last_user_text_;
// The most recent verbatim passed to Update().
bool last_verbatim_;
// The most recent suggestion received from the page, minus any prefix that
// the user has typed.
InstantSuggestion last_suggestion_;
// See comments on the getter above.
content::PageTransition last_transition_type_;
// True if the last match passed to Update() was a search (versus a URL).
bool last_match_was_search_;
// True if we've received a response from the loader for the last Update(),
// thus indicating that the page is ready to be shown.
bool loader_processed_last_update_;
// True if the omnibox is focused, false otherwise.
bool is_omnibox_focused_;
// True if the active tab in the current window is the NTP, false otherwise.
bool active_tab_is_ntp_;
// Current omnibox bounds.
gfx::Rect omnibox_bounds_;
// Last bounds passed to the page.
gfx::Rect last_omnibox_bounds_;
// Timer used to update the bounds of the omnibox.
base::OneShotTimer<InstantController> update_bounds_timer_;
// Timer used to ensure that the Instant page does not get too stale.
base::OneShotTimer<InstantController> stale_loader_timer_;
// For each key K => value N, the map says that we found that the search
// engine identified by Instant URL K didn't support the Instant API in each
// of the last N times that we loaded it. If an Instant URL isn't present in
// the map at all or has a value 0, it means that search engine supports the
// Instant API (or we assume it does, since we haven't determined it doesn't).
std::map<std::string, int> blacklisted_urls_;
// Search terms extraction (for autocomplete history matches) doesn't work
// on Instant URLs. So, whenever the user commits an Instant search, we add
// an equivalent non-Instant search URL to history, so that the search shows
// up in autocomplete history matches.
GURL url_for_history_;
DISALLOW_IMPLICIT_CONSTRUCTORS(InstantController);
};
#endif // CHROME_BROWSER_INSTANT_INSTANT_CONTROLLER_H_
|