OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #ifndef CHROME_BROWSER_INSTANT_INSTANT_LOADER_H_ | 5 #ifndef CHROME_BROWSER_INSTANT_INSTANT_LOADER_H_ |
6 #define CHROME_BROWSER_INSTANT_INSTANT_LOADER_H_ | 6 #define CHROME_BROWSER_INSTANT_INSTANT_LOADER_H_ |
7 | 7 |
8 #include <string> | 8 #include <string> |
9 | 9 |
10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| 11 #include "base/compiler_specific.h" |
11 #include "base/memory/ref_counted.h" | 12 #include "base/memory/ref_counted.h" |
12 #include "base/memory/scoped_ptr.h" | 13 #include "base/memory/scoped_ptr.h" |
13 #include "base/string16.h" | 14 #include "base/string16.h" |
14 #include "base/timer.h" | |
15 #include "chrome/browser/instant/instant_commit_type.h" | 15 #include "chrome/browser/instant/instant_commit_type.h" |
16 #include "chrome/browser/search_engines/template_url_id.h" | |
17 #include "chrome/common/instant_types.h" | |
18 #include "content/public/browser/notification_observer.h" | 16 #include "content/public/browser/notification_observer.h" |
19 #include "content/public/browser/notification_registrar.h" | 17 #include "content/public/browser/notification_registrar.h" |
20 #include "content/public/common/page_transition_types.h" | |
21 #include "googleurl/src/gurl.h" | |
22 #include "ui/gfx/rect.h" | |
23 | 18 |
24 class InstantLoaderDelegate; | 19 class InstantLoaderDelegate; |
25 class InstantLoaderManagerTest; | |
26 class TabContents; | 20 class TabContents; |
27 class TemplateURL; | |
28 | 21 |
29 namespace content { | 22 namespace content { |
30 class SessionStorageNamespace; | 23 class NotificationDetails; |
| 24 class NotificationSource; |
31 } | 25 } |
32 | 26 |
33 // InstantLoader does the loading of a particular URL for InstantController. | 27 namespace gfx { |
34 // InstantLoader notifies its delegate, which is typically InstantController, of | 28 class Rect; |
35 // all interesting events. | 29 } |
36 // | 30 |
37 // InstantLoader is created with a TemplateURLID. If non-zero InstantLoader | 31 namespace history { |
38 // first determines if the site actually supports instant. If it doesn't, the | 32 class HistoryAddPageArgs; |
39 // delegate is notified by way of |InstantLoaderDoesntSupportInstant|. | 33 } |
40 // | 34 |
41 // If the TemplateURLID supplied to the constructor is zero, then the url is | 35 // InstantLoader is created with an "Instant URL". It loads the URL and tells |
42 // loaded as is. | 36 // its delegate (usually InstantController) of all interesting events. For |
| 37 // example, it determines if the page actually supports the Instant API |
| 38 // (http://dev.chromium.org/searchbox) and forwards messages (such as queries |
| 39 // and autocomplete suggestions) between the page and the delegate. |
43 class InstantLoader : public content::NotificationObserver { | 40 class InstantLoader : public content::NotificationObserver { |
44 public: | 41 public: |
45 // Header and value set on loads that originate from instant. | 42 // Creates a new empty WebContents. Use Init() to actually load |instant_url|. |
46 static const char* const kInstantHeader; | 43 // |tab_contents| is the page the preview will be shown on top of and |
47 static const char* const kInstantHeaderValue; | 44 // potentially replace. |instant_url| is typically the instant_url field of |
48 | 45 // the default search engine's TemplateURL, with the "{searchTerms}" parameter |
49 // |group| is an identifier suffixed to histograms to distinguish field trial | 46 // replaced with an empty string. |
50 // statistics from regular operation; can be a blank string. | |
51 InstantLoader(InstantLoaderDelegate* delegate, | 47 InstantLoader(InstantLoaderDelegate* delegate, |
52 TemplateURLID id, | 48 const std::string& instant_url, |
53 const std::string& group); | 49 const TabContents* tab_contents); |
54 virtual ~InstantLoader(); | 50 virtual ~InstantLoader(); |
55 | 51 |
56 // Invoked to load a URL. |tab_contents| is the TabContents the preview | 52 // Initializes |preview_contents_| and loads |instant_url_|. |
57 // is going to be shown on top of and potentially replace. Returns true if the | 53 void Init(); |
58 // arguments differ from the last call to |Update|. | |
59 bool Update(TabContents* tab_contents, | |
60 const TemplateURL* template_url, | |
61 const GURL& url, | |
62 content::PageTransition transition_type, | |
63 const string16& user_text, | |
64 bool verbatim, | |
65 string16* suggested_text); | |
66 | 54 |
67 // Sets the bounds of the omnibox (in screen coordinates). The bounds are | 55 // Tells the preview page that the user typed |user_text| into the omnibox. |
68 // remembered until the preview is committed or destroyed. This is only used | 56 // If |verbatim| is false, the page predicts the query the user means to type |
69 // when showing results for a search provider that supports instant. | 57 // and fetches results for the prediction. If |verbatim| is true, |user_text| |
| 58 // is taken as the exact query (no prediction is made). |
| 59 void Update(const string16& user_text, bool verbatim); |
| 60 |
| 61 // Tells the preview page of the bounds of the omnibox dropdown (in screen |
| 62 // coordinates). This is used by the page to offset the results to avoid them |
| 63 // being covered by the omnibox dropdown. |
70 void SetOmniboxBounds(const gfx::Rect& bounds); | 64 void SetOmniboxBounds(const gfx::Rect& bounds); |
71 | 65 |
72 // Returns true if the mouse or a touch-pointer is down as the result of | 66 // Releases the preview TabContents passing ownership to the caller. This |
73 // activating the preview content. | 67 // should be called when the preview is committed. Notifies the page but not |
74 bool IsPointerDownFromActivate(); | 68 // the delegate. |text| is the final omnibox text being committed. NOTE: The |
| 69 // caller should destroy this loader object right after this method, since |
| 70 // none of the other methods will work once the preview has been released. |
| 71 TabContents* ReleasePreviewContents(InstantCommitType type, |
| 72 const string16& text) WARN_UNUSED_RESULT; |
75 | 73 |
76 // Releases the preview TabContents passing ownership to the caller. | 74 // The preview TabContents. The loader retains ownership. This will be |
77 // This is intended to be called when the preview TabContents is | 75 // non-NULL until ReleasePreviewContents() is called. |
78 // committed. This does not notify the delegate. |tab_contents| is the | 76 TabContents* preview_contents() const { return preview_contents_.get(); } |
79 // underlying tab onto which the preview will be committed. It can be NULL | |
80 // when the underlying tab is irrelevant, for example when |type| is | |
81 // INSTANT_COMMIT_DESTROY. | |
82 TabContents* ReleasePreviewContents(InstantCommitType type, | |
83 TabContents* tab_contents); | |
84 | 77 |
85 // Calls through to method of same name on delegate. | 78 // Returns true if the preview page is known to support the Instant API. This |
86 bool ShouldCommitInstantOnPointerRelease(); | 79 // starts out false, and becomes true whenever we get any message from the |
87 void CommitInstantLoader(); | 80 // page. Once true, it never becomes false (the page isn't expected to drop |
| 81 // Instant API support suddenly). |
| 82 bool supports_instant() const { return supports_instant_; } |
88 | 83 |
89 // Preload |template_url|'s instant URL, if the loader doesn't already have | 84 // Returns the URL that we're loading. |
90 // a |preview_contents()| for it. | 85 const std::string& instant_url() const { return instant_url_; } |
91 void MaybeLoadInstantURL(TabContents* tab_contents, | |
92 const TemplateURL* template_url); | |
93 | 86 |
94 // Returns true if the preview NavigationController's WebContents has a | 87 // Returns info about the last navigation by the Instant page. If the page |
95 // pending NavigationEntry. | 88 // hasn't navigated since the last Update(), this contains NULL. |
96 bool IsNavigationPending() const; | 89 scoped_refptr<history::HistoryAddPageArgs> last_navigation() const { |
| 90 return last_navigation_; |
| 91 } |
| 92 |
| 93 // Returns true if the mouse or a touch pointer is down due to activating the |
| 94 // preview content. |
| 95 bool IsPointerDownFromActivate() const; |
97 | 96 |
98 // content::NotificationObserver: | 97 // content::NotificationObserver: |
99 virtual void Observe(int type, | 98 virtual void Observe(int type, |
100 const content::NotificationSource& source, | 99 const content::NotificationSource& source, |
101 const content::NotificationDetails& details) OVERRIDE; | 100 const content::NotificationDetails& details) OVERRIDE; |
102 | 101 |
103 // The preview TabContents; may be null. | |
104 TabContents* preview_contents() const { | |
105 return preview_contents_.get(); | |
106 } | |
107 | |
108 // Returns true if the preview TabContents is ready to be shown. A | |
109 // non-instant loader is ready once the renderer paints, otherwise it isn't | |
110 // ready until we get a response back from the page. | |
111 bool ready() const { return ready_; } | |
112 | |
113 // Returns true if the current load returned a 200. | |
114 bool http_status_ok() const { return http_status_ok_; } | |
115 | |
116 // Returns true if the url needs to be reloaded. This is set to true for | |
117 // downloads. | |
118 bool needs_reload() const { return needs_reload_; } | |
119 | |
120 const GURL& url() const { return url_; } | |
121 | |
122 bool verbatim() const { return verbatim_; } | |
123 | |
124 // Are we showing instant results? | |
125 bool is_showing_instant() const { return template_url_id_ != 0; } | |
126 | |
127 // If we're showing instant this returns non-zero. | |
128 TemplateURLID template_url_id() const { return template_url_id_; } | |
129 | |
130 // See description above field. | |
131 const string16& user_text() const { return user_text_; } | |
132 | |
133 // Are we waiting for the preview page to finish loading and to determine if | |
134 // it supports instant? | |
135 bool is_determining_if_page_supports_instant() const { | |
136 return frame_load_observer_.get() != NULL; | |
137 } | |
138 | |
139 private: | 102 private: |
140 friend class InstantLoaderManagerTest; | |
141 friend class InstantTest; | |
142 class FrameLoadObserver; | |
143 class PaintObserverImpl; | |
144 class WebContentsDelegateImpl; | 103 class WebContentsDelegateImpl; |
145 | 104 |
146 // Invoked when the page wants to update the suggested text. If |user_text_| | 105 void SetupPreviewContents(); |
147 // starts with |suggested_text|, then the delegate is notified of the change, | 106 void CleanupPreviewContents(); |
148 // which results in updating the omnibox. | 107 void ReplacePreviewContents(TabContents* old_tc, TabContents* new_tc); |
149 void SetCompleteSuggestedText(const string16& suggested_text, | |
150 InstantCompleteBehavior behavior); | |
151 | 108 |
152 // Invoked when the page paints. | 109 InstantLoaderDelegate* const loader_delegate_; |
153 void PreviewPainted(); | |
154 | 110 |
155 // Invoked when the http status code changes. This may notify the delegate. | 111 // See comments on the getter above. |
156 void SetHTTPStatusOK(bool is_ok); | 112 scoped_ptr<TabContents> preview_contents_; |
157 | |
158 // Invoked to show the preview. This is invoked in two possible cases: when | |
159 // the renderer paints, or when an auth dialog is shown. This notifies the | |
160 // delegate the preview is ready to be shown. | |
161 void ShowPreview(); | |
162 | |
163 // Invoked once the page has finished loading and the script has been sent. | |
164 void PageFinishedLoading(); | |
165 | |
166 // Returns the bounds of the omnibox in terms of the preview tab contents. | |
167 gfx::Rect GetOmniboxBoundsInTermsOfPreview(); | |
168 | |
169 // Invoked if it the page doesn't really support instant when we thought it | |
170 // did. If |needs_reload| is true, the text changed since the first load and | |
171 // the page needs to be reloaded. | |
172 void PageDoesntSupportInstant(bool needs_reload); | |
173 | |
174 // Invokes |SetBoundsToPage(false)|. This is called from the timer. | |
175 void ProcessBoundsChange(); | |
176 | |
177 // Notifes the page of the omnibox bounds. If |force_if_loading| is true the | |
178 // bounds are sent down even if we're waiting on the load, otherwise if we're | |
179 // waiting on the load and |force_if_loading| is false this does nothing. | |
180 void SendBoundsToPage(bool force_if_loading); | |
181 | |
182 // Called when the TabContentsDelegate wants to swap a new TabContents | |
183 // into our |preview_contents_|. | |
184 void ReplacePreviewContents(TabContents* old_tc, | |
185 TabContents* new_tc); | |
186 | |
187 // Called to set up the |preview_contents_| based on |tab_contents| when it is | |
188 // created or replaced. | |
189 void SetupPreviewContents(TabContents* tab_contents); | |
190 | |
191 // Creates and sets the preview TabContents. | |
192 void CreatePreviewContents(TabContents* tab_contents); | |
193 | |
194 // Creates and loads the |template_url|'s instant URL. | |
195 void LoadInstantURL(const TemplateURL* template_url, | |
196 content::PageTransition transition_type, | |
197 const string16& user_text, | |
198 bool verbatim, | |
199 bool override_user_agent); | |
200 | |
201 InstantLoaderDelegate* delegate_; | |
202 | |
203 // If we're showing instant results this is the ID of the TemplateURL driving | |
204 // the results. A value of 0 means there is no TemplateURL. | |
205 const TemplateURLID template_url_id_; | |
206 | |
207 // The url we're displaying. | |
208 GURL url_; | |
209 | 113 |
210 // Delegate of the preview WebContents. Used to detect when the user does some | 114 // Delegate of the preview WebContents. Used to detect when the user does some |
211 // gesture on the WebContents and the preview needs to be activated. | 115 // gesture on the WebContents and the preview needs to be activated. |
212 scoped_ptr<WebContentsDelegateImpl> preview_tab_contents_delegate_; | 116 scoped_ptr<WebContentsDelegateImpl> preview_delegate_; |
213 | 117 |
214 // The preview TabContents; may be null. | 118 // See comments on the getter above. |
215 scoped_ptr<TabContents> preview_contents_; | 119 bool supports_instant_; |
216 | 120 |
217 // Is the preview_contents ready to be shown? | 121 // See comments on the getter above. |
218 bool ready_; | 122 const std::string instant_url_; |
219 | |
220 // Was the last status code a 200? | |
221 bool http_status_ok_; | |
222 | |
223 // The text the user typed in the omnibox, stripped of the leading ?, if any. | |
224 string16 user_text_; | |
225 | |
226 // The latest suggestion from the page. | |
227 string16 complete_suggested_text_; | |
228 | |
229 // The latest suggestion (suggested text less the user text). | |
230 string16 last_suggestion_; | |
231 | |
232 // See description above setter. | |
233 gfx::Rect omnibox_bounds_; | |
234 | |
235 // Last bounds passed to the page. | |
236 gfx::Rect last_omnibox_bounds_; | |
237 | |
238 scoped_ptr<FrameLoadObserver> frame_load_observer_; | |
239 | |
240 // Transition type of the match last passed to Update. | |
241 content::PageTransition last_transition_type_; | |
242 | |
243 // Timer used to update the bounds of the omnibox. | |
244 base::OneShotTimer<InstantLoader> update_bounds_timer_; | |
245 | 123 |
246 // Used to get notifications about renderers coming and going. | 124 // Used to get notifications about renderers coming and going. |
247 content::NotificationRegistrar registrar_; | 125 content::NotificationRegistrar registrar_; |
248 | 126 |
249 // Last value of verbatim passed to |Update|. | 127 // See comments on the getter above. |
250 bool verbatim_; | 128 scoped_refptr<history::HistoryAddPageArgs> last_navigation_; |
251 | |
252 // True if the page needs to be reloaded. | |
253 bool needs_reload_; | |
254 | |
255 // See description above constructor. | |
256 std::string group_; | |
257 | |
258 // The session storage namespace identifier of the original tab contents that | |
259 // the preview_contents_ was based upon. | |
260 scoped_refptr<content::SessionStorageNamespace> session_storage_namespace_; | |
261 | 129 |
262 DISALLOW_COPY_AND_ASSIGN(InstantLoader); | 130 DISALLOW_COPY_AND_ASSIGN(InstantLoader); |
263 }; | 131 }; |
264 | 132 |
265 #endif // CHROME_BROWSER_INSTANT_INSTANT_LOADER_H_ | 133 #endif // CHROME_BROWSER_INSTANT_INSTANT_LOADER_H_ |
OLD | NEW |