OLD | NEW |
---|---|
1 // Copyright 2012 The Chromium Authors. All rights reserved. | 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 | 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 #include "chrome/browser/instant/instant_controller.h" | 5 #include "chrome/browser/instant/instant_controller.h" |
6 | 6 |
7 #include "base/command_line.h" | 7 #include "base/command_line.h" |
8 #include "base/metrics/histogram.h" | 8 #include "base/metrics/histogram.h" |
9 #include "base/string_util.h" | 9 #include "base/string_util.h" |
10 #include "base/stringprintf.h" | 10 #include "base/stringprintf.h" |
11 #include "base/utf_string_conversions.h" | 11 #include "base/utf_string_conversions.h" |
12 #include "chrome/browser/autocomplete/autocomplete_provider.h" | 12 #include "chrome/browser/autocomplete/autocomplete_provider.h" |
13 #include "chrome/browser/google/google_util.h" | 13 #include "chrome/browser/google/google_util.h" |
14 #include "chrome/browser/history/history_service.h" | 14 #include "chrome/browser/history/history_service.h" |
15 #include "chrome/browser/history/history_service_factory.h" | 15 #include "chrome/browser/history/history_service_factory.h" |
16 #include "chrome/browser/history/history_tab_helper.h" | 16 #include "chrome/browser/history/history_tab_helper.h" |
17 #include "chrome/browser/instant/instant_loader.h" | 17 #include "chrome/browser/instant/instant_ntp.h" |
18 #include "chrome/browser/instant/instant_overlay.h" | |
18 #include "chrome/browser/instant/instant_tab.h" | 19 #include "chrome/browser/instant/instant_tab.h" |
19 #include "chrome/browser/platform_util.h" | 20 #include "chrome/browser/platform_util.h" |
20 #include "chrome/browser/search_engines/template_url_service.h" | 21 #include "chrome/browser/search_engines/template_url_service.h" |
21 #include "chrome/browser/search_engines/template_url_service_factory.h" | 22 #include "chrome/browser/search_engines/template_url_service_factory.h" |
22 #include "chrome/browser/ui/browser_instant_controller.h" | 23 #include "chrome/browser/ui/browser_instant_controller.h" |
23 #include "chrome/browser/ui/search/search_tab_helper.h" | 24 #include "chrome/browser/ui/search/search_tab_helper.h" |
24 #include "chrome/common/chrome_notification_types.h" | 25 #include "chrome/common/chrome_notification_types.h" |
25 #include "chrome/common/chrome_switches.h" | 26 #include "chrome/common/chrome_switches.h" |
26 #include "content/public/browser/navigation_entry.h" | 27 #include "content/public/browser/navigation_entry.h" |
27 #include "content/public/browser/notification_service.h" | 28 #include "content/public/browser/notification_service.h" |
(...skipping 10 matching lines...) Expand all Loading... | |
38 | 39 |
39 // An artificial delay (in milliseconds) we introduce before telling the Instant | 40 // An artificial delay (in milliseconds) we introduce before telling the Instant |
40 // page about the new omnibox bounds, in cases where the bounds shrink. This is | 41 // page about the new omnibox bounds, in cases where the bounds shrink. This is |
41 // to avoid the page jumping up/down very fast in response to bounds changes. | 42 // to avoid the page jumping up/down very fast in response to bounds changes. |
42 const int kUpdateBoundsDelayMS = 1000; | 43 const int kUpdateBoundsDelayMS = 1000; |
43 | 44 |
44 // The maximum number of times we'll load a non-Instant-supporting search engine | 45 // The maximum number of times we'll load a non-Instant-supporting search engine |
45 // before we give up and blacklist it for the rest of the browsing session. | 46 // before we give up and blacklist it for the rest of the browsing session. |
46 const int kMaxInstantSupportFailures = 10; | 47 const int kMaxInstantSupportFailures = 10; |
47 | 48 |
48 // If an Instant page has not been used in these many milliseconds, it is | |
49 // reloaded so that the page does not become stale. | |
50 const int kStaleLoaderTimeoutMS = 3 * 3600 * 1000; | |
51 | |
52 // For reporting events of interest. | 49 // For reporting events of interest. |
53 enum InstantControllerEvent { | 50 enum InstantControllerEvent { |
54 INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST = 0, | 51 INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST = 0, |
55 INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST = 1, | 52 INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST = 1, |
56 INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST = 2, | 53 INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST = 2, |
57 INSTANT_CONTROLLER_EVENT_MAX = 3, | 54 INSTANT_CONTROLLER_EVENT_MAX = 3, |
58 }; | 55 }; |
59 | 56 |
60 void RecordEventHistogram(InstantControllerEvent event) { | 57 void RecordEventHistogram(InstantControllerEvent event) { |
61 UMA_HISTOGRAM_ENUMERATION("Instant.InstantControllerEvent", | 58 UMA_HISTOGRAM_ENUMERATION("Instant.InstantControllerEvent", |
(...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
153 return true; | 150 return true; |
154 } | 151 } |
155 | 152 |
156 return false; | 153 return false; |
157 } | 154 } |
158 | 155 |
159 bool IsFullHeight(const InstantModel& model) { | 156 bool IsFullHeight(const InstantModel& model) { |
160 return model.height() == 100 && model.height_units() == INSTANT_SIZE_PERCENT; | 157 return model.height() == 100 && model.height_units() == INSTANT_SIZE_PERCENT; |
161 } | 158 } |
162 | 159 |
160 bool ContentsFrom(const InstantPage* page, | |
dhollowa
2013/01/29 02:37:53
nit: IsContentsFrom
samarth
2013/01/29 05:42:01
Done.
| |
161 const content::WebContents* contents) { | |
162 return page && (page->contents() == contents); | |
163 } | |
164 | |
163 } // namespace | 165 } // namespace |
164 | 166 |
165 // static | 167 // static |
166 const char* InstantController::kLocalOmniboxPopupURL = | 168 const char* InstantController::kLocalOmniboxPopupURL = |
167 "chrome://local-omnibox-popup/local-omnibox-popup.html"; | 169 "chrome://local-omnibox-popup/local-omnibox-popup.html"; |
168 | 170 |
169 InstantController::InstantController(chrome::BrowserInstantController* browser, | 171 InstantController::InstantController(chrome::BrowserInstantController* browser, |
170 bool extended_enabled, | 172 bool extended_enabled, |
171 bool use_local_preview_only) | 173 bool use_local_preview_only) |
172 : browser_(browser), | 174 : browser_(browser), |
(...skipping 38 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
211 is_keyword_search)); | 213 is_keyword_search)); |
212 | 214 |
213 // TODO(dhollowa): Complete keyword match UI. For now just hide suggestions. | 215 // TODO(dhollowa): Complete keyword match UI. For now just hide suggestions. |
214 // http://crbug.com/153932. Note, this early escape is happens prior to the | 216 // http://crbug.com/153932. Note, this early escape is happens prior to the |
215 // DCHECKs below because |user_text| and |full_text| have different semantics | 217 // DCHECKs below because |user_text| and |full_text| have different semantics |
216 // when keyword search is in effect. | 218 // when keyword search is in effect. |
217 if (is_keyword_search) { | 219 if (is_keyword_search) { |
218 if (instant_tab_) | 220 if (instant_tab_) |
219 instant_tab_->Update(string16(), 0, 0, true); | 221 instant_tab_->Update(string16(), 0, 0, true); |
220 else | 222 else |
221 HideLoader(); | 223 HideOverlay(); |
222 last_match_was_search_ = false; | 224 last_match_was_search_ = false; |
223 return false; | 225 return false; |
224 } | 226 } |
225 | 227 |
226 // If the popup is open, the user has to be typing. | 228 // If the popup is open, the user has to be typing. |
227 DCHECK(!omnibox_popup_is_open || user_input_in_progress); | 229 DCHECK(!omnibox_popup_is_open || user_input_in_progress); |
228 | 230 |
229 // If the popup is closed, there should be no inline autocompletion. | 231 // If the popup is closed, there should be no inline autocompletion. |
230 DCHECK(omnibox_popup_is_open || user_text.empty() || user_text == full_text) | 232 DCHECK(omnibox_popup_is_open || user_text.empty() || user_text == full_text) |
231 << user_text << "|" << full_text; | 233 << user_text << "|" << full_text; |
232 | 234 |
233 // If there's no text in the omnibox, the user can't have typed any. | 235 // If there's no text in the omnibox, the user can't have typed any. |
234 DCHECK(!full_text.empty() || user_text.empty()) << user_text; | 236 DCHECK(!full_text.empty() || user_text.empty()) << user_text; |
235 | 237 |
236 // If the user isn't typing, and the popup is closed, there can't be any | 238 // If the user isn't typing, and the popup is closed, there can't be any |
237 // user-typed text. | 239 // user-typed text. |
238 DCHECK(user_input_in_progress || omnibox_popup_is_open || user_text.empty()) | 240 DCHECK(user_input_in_progress || omnibox_popup_is_open || user_text.empty()) |
239 << user_text; | 241 << user_text; |
240 | 242 |
241 // The preview is being clicked and will commit soon. Don't change anything. | 243 // The preview is being clicked and will commit soon. Don't change anything. |
242 // TODO(sreeram): Add a browser test for this. | 244 // TODO(sreeram): Add a browser test for this. |
243 if (loader_ && loader_->is_pointer_down_from_activate()) | 245 if (overlay_ && overlay_->is_pointer_down_from_activate()) |
244 return false; | 246 return false; |
245 | 247 |
246 // In non-extended mode, SearchModeChanged() is never called, so fake it. The | 248 // In non-extended mode, SearchModeChanged() is never called, so fake it. The |
247 // mode is set to "disallow suggestions" here, so that if one of the early | 249 // mode is set to "disallow suggestions" here, so that if one of the early |
248 // "return false" conditions is hit, suggestions will be disallowed. If the | 250 // "return false" conditions is hit, suggestions will be disallowed. If the |
249 // query is sent to the loader, the mode is set to "allow" further below. | 251 // query is sent to the overlay, the mode is set to "allow" further below. |
250 if (!extended_enabled_) | 252 if (!extended_enabled_) |
251 search_mode_.mode = chrome::search::Mode::MODE_DEFAULT; | 253 search_mode_.mode = chrome::search::Mode::MODE_DEFAULT; |
252 | 254 |
253 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && | 255 last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && |
254 !user_text.empty(); | 256 !user_text.empty(); |
255 | 257 |
256 // In non extended mode, Instant is disabled for URLs and keyword mode. | 258 // In non extended mode, Instant is disabled for URLs and keyword mode. |
257 if (!extended_enabled_ && | 259 if (!extended_enabled_ && |
258 (!last_match_was_search_ || | 260 (!last_match_was_search_ || |
259 match.type == AutocompleteMatch::SEARCH_OTHER_ENGINE)) { | 261 match.type == AutocompleteMatch::SEARCH_OTHER_ENGINE)) { |
260 HideLoader(); | 262 HideOverlay(); |
261 return false; | 263 return false; |
262 } | 264 } |
263 | 265 |
264 // If we have an |instant_tab_| use it, else ensure we have a loader. | 266 // If we have an |instant_tab_| use it, else ensure we have a overlay. |
265 if (!instant_tab_ && !EnsureLoaderIsCurrent()) { | 267 if (!instant_tab_ && !EnsureOverlayIsCurrent()) { |
266 HideLoader(); | 268 HideOverlay(); |
267 return false; | 269 return false; |
268 } | 270 } |
269 | 271 |
270 if (extended_enabled_) { | 272 if (extended_enabled_) { |
271 if (!omnibox_popup_is_open) { | 273 if (!omnibox_popup_is_open) { |
272 if (!user_input_in_progress) { | 274 if (!user_input_in_progress) { |
273 // If the user isn't typing and the omnibox popup is closed, it means a | 275 // If the user isn't typing and the omnibox popup is closed, it means a |
274 // regular navigation, tab-switch or the user hitting Escape. | 276 // regular navigation, tab-switch or the user hitting Escape. |
275 if (instant_tab_) { | 277 if (instant_tab_) { |
276 // The user is on a search results page. It may be showing results for | 278 // The user is on a search results page. It may be showing results for |
277 // a partial query the user typed before they hit Escape. Send the | 279 // a partial query the user typed before they hit Escape. Send the |
278 // omnibox text to the page to restore the original results. | 280 // omnibox text to the page to restore the original results. |
279 // | 281 // |
280 // In a tab switch, |instant_tab_| won't have updated yet, so it may | 282 // In a tab switch, |instant_tab_| won't have updated yet, so it may |
281 // be pointing to the previous tab (which was a search results page). | 283 // be pointing to the previous tab (which was a search results page). |
282 // Ensure we don't send the omnibox text to a random webpage (the new | 284 // Ensure we don't send the omnibox text to a random webpage (the new |
283 // tab), by comparing the old and new WebContents. | 285 // tab), by comparing the old and new WebContents. |
284 if (escape_pressed && | 286 if (escape_pressed && |
285 instant_tab_->contents() == browser_->GetActiveWebContents()) { | 287 instant_tab_->contents() == browser_->GetActiveWebContents()) { |
286 instant_tab_->Submit(full_text); | 288 instant_tab_->Submit(full_text); |
287 } | 289 } |
288 } else if (!full_text.empty()) { | 290 } else if (!full_text.empty()) { |
289 // If |full_text| is empty, the user is on the NTP. The preview may | 291 // If |full_text| is empty, the user is on the NTP. The preview may |
290 // be showing custom NTP content; hide only if that's not the case. | 292 // be showing custom NTP content; hide only if that's not the case. |
291 HideLoader(); | 293 HideOverlay(); |
292 } | 294 } |
293 } else if (full_text.empty()) { | 295 } else if (full_text.empty()) { |
294 // The user is typing, and backspaced away all omnibox text. Clear | 296 // The user is typing, and backspaced away all omnibox text. Clear |
295 // |last_omnibox_text_| so that we don't attempt to set suggestions. | 297 // |last_omnibox_text_| so that we don't attempt to set suggestions. |
296 last_omnibox_text_.clear(); | 298 last_omnibox_text_.clear(); |
297 last_suggestion_ = InstantSuggestion(); | 299 last_suggestion_ = InstantSuggestion(); |
298 if (instant_tab_) { | 300 if (instant_tab_) { |
299 // On a search results page, tell it to clear old results. | 301 // On a search results page, tell it to clear old results. |
300 instant_tab_->Update(string16(), 0, 0, true); | 302 instant_tab_->Update(string16(), 0, 0, true); |
301 } else if (search_mode_.is_origin_ntp()) { | 303 } else if (search_mode_.is_origin_ntp()) { |
302 // On the NTP, tell the preview to clear old results. Don't hide the | 304 // On the NTP, tell the preview to clear old results. Don't hide the |
303 // preview so it can show a blank page or logo if it wants. | 305 // preview so it can show a blank page or logo if it wants. |
304 loader_->Update(string16(), 0, 0, true); | 306 overlay_->Update(string16(), 0, 0, true); |
305 } else { | 307 } else { |
306 HideLoader(); | 308 HideOverlay(); |
307 } | 309 } |
308 } else { | 310 } else { |
309 // The user switched to a tab with partial text already in the omnibox. | 311 // The user switched to a tab with partial text already in the omnibox. |
310 HideLoader(); | 312 HideOverlay(); |
311 | 313 |
312 // The new tab may or may not be a search results page; we don't know | 314 // The new tab may or may not be a search results page; we don't know |
313 // since SearchModeChanged() hasn't been called yet. If it later turns | 315 // since SearchModeChanged() hasn't been called yet. If it later turns |
314 // out to be, we should store |full_text| now, so that if the user hits | 316 // out to be, we should store |full_text| now, so that if the user hits |
315 // Enter, we'll send the correct query to instant_tab_->Submit(). If the | 317 // Enter, we'll send the correct query to instant_tab_->Submit(). If the |
316 // partial text is not a query (|last_match_was_search_| is false), we | 318 // partial text is not a query (|last_match_was_search_| is false), we |
317 // won't Submit(), so no need to worry about that. | 319 // won't Submit(), so no need to worry about that. |
318 last_omnibox_text_ = full_text; | 320 last_omnibox_text_ = full_text; |
319 last_suggestion_ = InstantSuggestion(); | 321 last_suggestion_ = InstantSuggestion(); |
320 } | 322 } |
321 return false; | 323 return false; |
322 } else if (full_text.empty()) { | 324 } else if (full_text.empty()) { |
323 // The user typed a solitary "?". Same as the backspace case above. | 325 // The user typed a solitary "?". Same as the backspace case above. |
324 last_omnibox_text_.clear(); | 326 last_omnibox_text_.clear(); |
325 last_suggestion_ = InstantSuggestion(); | 327 last_suggestion_ = InstantSuggestion(); |
326 if (instant_tab_) | 328 if (instant_tab_) |
327 instant_tab_->Update(string16(), 0, 0, true); | 329 instant_tab_->Update(string16(), 0, 0, true); |
328 else if (search_mode_.is_origin_ntp()) | 330 else if (search_mode_.is_origin_ntp()) |
329 loader_->Update(string16(), 0, 0, true); | 331 overlay_->Update(string16(), 0, 0, true); |
330 else | 332 else |
331 HideLoader(); | 333 HideOverlay(); |
332 return false; | 334 return false; |
333 } | 335 } |
334 } else if (!omnibox_popup_is_open || full_text.empty()) { | 336 } else if (!omnibox_popup_is_open || full_text.empty()) { |
335 // In the non-extended case, hide the preview as long as the user isn't | 337 // In the non-extended case, hide the preview as long as the user isn't |
336 // actively typing a non-empty query. | 338 // actively typing a non-empty query. |
337 HideLoader(); | 339 HideOverlay(); |
338 return false; | 340 return false; |
339 } | 341 } |
340 | 342 |
341 last_omnibox_text_has_inline_autocompletion_ = user_text != full_text; | 343 last_omnibox_text_has_inline_autocompletion_ = user_text != full_text; |
342 | 344 |
343 // If the user continues typing the same query as the suggested text is | 345 // If the user continues typing the same query as the suggested text is |
344 // showing, reuse the suggestion (but only for INSTANT_COMPLETE_NEVER). | 346 // showing, reuse the suggestion (but only for INSTANT_COMPLETE_NEVER). |
345 bool reused_suggestion = false; | 347 bool reused_suggestion = false; |
346 if (last_suggestion_.behavior == INSTANT_COMPLETE_NEVER && | 348 if (last_suggestion_.behavior == INSTANT_COMPLETE_NEVER && |
347 !last_omnibox_text_has_inline_autocompletion_) { | 349 !last_omnibox_text_has_inline_autocompletion_) { |
(...skipping 28 matching lines...) Expand all Loading... | |
376 // this, but it's not called in non-extended mode, so fake it. | 378 // this, but it's not called in non-extended mode, so fake it. |
377 if (!extended_enabled_) | 379 if (!extended_enabled_) |
378 search_mode_.mode = chrome::search::Mode::MODE_SEARCH_SUGGESTIONS; | 380 search_mode_.mode = chrome::search::Mode::MODE_SEARCH_SUGGESTIONS; |
379 | 381 |
380 if (instant_tab_) { | 382 if (instant_tab_) { |
381 instant_tab_->Update(user_text, selection_start, selection_end, verbatim); | 383 instant_tab_->Update(user_text, selection_start, selection_end, verbatim); |
382 } else { | 384 } else { |
383 if (first_interaction_time_.is_null()) | 385 if (first_interaction_time_.is_null()) |
384 first_interaction_time_ = base::Time::Now(); | 386 first_interaction_time_ = base::Time::Now(); |
385 allow_preview_to_show_search_suggestions_ = true; | 387 allow_preview_to_show_search_suggestions_ = true; |
386 loader_->Update(extended_enabled_ ? user_text : full_text, | 388 overlay_->Update(extended_enabled_ ? user_text : full_text, |
387 selection_start, selection_end, verbatim); | 389 selection_start, selection_end, verbatim); |
388 } | 390 } |
389 | 391 |
390 content::NotificationService::current()->Notify( | 392 content::NotificationService::current()->Notify( |
391 chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED, | 393 chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED, |
392 content::Source<InstantController>(this), | 394 content::Source<InstantController>(this), |
393 content::NotificationService::NoDetails()); | 395 content::NotificationService::NoDetails()); |
394 | 396 |
395 // We don't have new suggestions yet, but we can either reuse the existing | 397 // We don't have new suggestions yet, but we can either reuse the existing |
396 // suggestion or reset the existing "gray text". | 398 // suggestion or reset the existing "gray text". |
397 browser_->SetInstantSuggestion(last_suggestion_); | 399 browser_->SetInstantSuggestion(last_suggestion_); |
398 | 400 |
399 return true; | 401 return true; |
400 } | 402 } |
401 | 403 |
404 scoped_ptr<content::WebContents> InstantController::ReleaseNTPContents() { | |
405 if (!extended_enabled_ || !ntp_) | |
dhollowa
2013/01/29 02:37:53
Seems like the caller is in error if they try to r
samarth
2013/01/29 05:42:01
Done. Note that as I mentioned earlier, ntp_ may
| |
406 return scoped_ptr<content::WebContents>(NULL); | |
407 | |
408 LOG_INSTANT_DEBUG_EVENT(this, "ReleaseNTPContents"); | |
409 | |
410 scoped_ptr<content::WebContents> ntp_contents = ntp_->ReleaseContents(); | |
411 ntp_.reset(); | |
412 ResetNTP(); | |
413 return ntp_contents.Pass(); | |
414 } | |
415 | |
402 // TODO(tonyg): This method only fires when the omnibox bounds change. It also | 416 // TODO(tonyg): This method only fires when the omnibox bounds change. It also |
403 // needs to fire when the preview bounds change (e.g.: open/close info bar). | 417 // needs to fire when the preview bounds change (e.g.: open/close info bar). |
404 void InstantController::SetPopupBounds(const gfx::Rect& bounds) { | 418 void InstantController::SetPopupBounds(const gfx::Rect& bounds) { |
405 if (!extended_enabled_ && !instant_enabled_) | 419 if (!extended_enabled_ && !instant_enabled_) |
406 return; | 420 return; |
407 | 421 |
408 if (popup_bounds_ == bounds) | 422 if (popup_bounds_ == bounds) |
409 return; | 423 return; |
410 | 424 |
411 popup_bounds_ = bounds; | 425 popup_bounds_ = bounds; |
412 if (popup_bounds_.height() > last_popup_bounds_.height()) { | 426 if (popup_bounds_.height() > last_popup_bounds_.height()) { |
413 update_bounds_timer_.Stop(); | 427 update_bounds_timer_.Stop(); |
414 SendPopupBoundsToPage(); | 428 SendPopupBoundsToPage(); |
415 } else if (!update_bounds_timer_.IsRunning()) { | 429 } else if (!update_bounds_timer_.IsRunning()) { |
416 update_bounds_timer_.Start(FROM_HERE, | 430 update_bounds_timer_.Start(FROM_HERE, |
417 base::TimeDelta::FromMilliseconds(kUpdateBoundsDelayMS), this, | 431 base::TimeDelta::FromMilliseconds(kUpdateBoundsDelayMS), this, |
418 &InstantController::SendPopupBoundsToPage); | 432 &InstantController::SendPopupBoundsToPage); |
419 } | 433 } |
420 } | 434 } |
421 | 435 |
422 void InstantController::SetMarginSize(int start, int end) { | 436 void InstantController::SetMarginSize(int start, int end) { |
423 if (!extended_enabled_ || (start_margin_ == start && end_margin_ == end)) | 437 if (!extended_enabled_ || (start_margin_ == start && end_margin_ == end)) |
424 return; | 438 return; |
425 | 439 |
426 start_margin_ = start; | 440 start_margin_ = start; |
427 end_margin_ = end; | 441 end_margin_ = end; |
428 if (loader_) | 442 if (overlay_) |
429 loader_->SetMarginSize(start_margin_, end_margin_); | 443 overlay_->SetMarginSize(start_margin_, end_margin_); |
444 if (ntp_) | |
445 ntp_->SetMarginSize(start_margin_, end_margin_); | |
430 if (instant_tab_) | 446 if (instant_tab_) |
431 instant_tab_->SetMarginSize(start_margin_, end_margin_); | 447 instant_tab_->SetMarginSize(start_margin_, end_margin_); |
432 } | 448 } |
433 | 449 |
434 void InstantController::HandleAutocompleteResults( | 450 void InstantController::HandleAutocompleteResults( |
435 const std::vector<AutocompleteProvider*>& providers) { | 451 const std::vector<AutocompleteProvider*>& providers) { |
436 if (!extended_enabled_) | 452 if (!extended_enabled_) |
437 return; | 453 return; |
438 | 454 |
439 if (!instant_tab_ && !loader_) | 455 if (!instant_tab_ && !overlay_) |
440 return; | 456 return; |
441 | 457 |
442 DVLOG(1) << "AutocompleteResults:"; | 458 DVLOG(1) << "AutocompleteResults:"; |
443 std::vector<InstantAutocompleteResult> results; | 459 std::vector<InstantAutocompleteResult> results; |
444 for (ACProviders::const_iterator provider = providers.begin(); | 460 for (ACProviders::const_iterator provider = providers.begin(); |
445 provider != providers.end(); ++provider) { | 461 provider != providers.end(); ++provider) { |
446 for (ACMatches::const_iterator match = (*provider)->matches().begin(); | 462 for (ACMatches::const_iterator match = (*provider)->matches().begin(); |
447 match != (*provider)->matches().end(); ++match) { | 463 match != (*provider)->matches().end(); ++match) { |
448 InstantAutocompleteResult result; | 464 InstantAutocompleteResult result; |
449 result.provider = UTF8ToUTF16((*provider)->GetName()); | 465 result.provider = UTF8ToUTF16((*provider)->GetName()); |
450 result.type = UTF8ToUTF16(AutocompleteMatch::TypeToString(match->type)); | 466 result.type = UTF8ToUTF16(AutocompleteMatch::TypeToString(match->type)); |
451 result.description = match->description; | 467 result.description = match->description; |
452 result.destination_url = UTF8ToUTF16(match->destination_url.spec()); | 468 result.destination_url = UTF8ToUTF16(match->destination_url.spec()); |
453 result.transition = match->transition; | 469 result.transition = match->transition; |
454 result.relevance = match->relevance; | 470 result.relevance = match->relevance; |
455 DVLOG(1) << " " << result.relevance << " " << result.type << " " | 471 DVLOG(1) << " " << result.relevance << " " << result.type << " " |
456 << result.provider << " " << result.destination_url << " '" | 472 << result.provider << " " << result.destination_url << " '" |
457 << result.description << "' " << result.transition; | 473 << result.description << "' " << result.transition; |
458 results.push_back(result); | 474 results.push_back(result); |
459 } | 475 } |
460 } | 476 } |
461 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 477 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
462 "HandleAutocompleteResults: total_results=%d", | 478 "HandleAutocompleteResults: total_results=%d", |
463 static_cast<int>(results.size()))); | 479 static_cast<int>(results.size()))); |
464 | 480 |
465 if (instant_tab_) | 481 if (instant_tab_) |
466 instant_tab_->SendAutocompleteResults(results); | 482 instant_tab_->SendAutocompleteResults(results); |
467 else | 483 else |
468 loader_->SendAutocompleteResults(results); | 484 overlay_->SendAutocompleteResults(results); |
469 } | 485 } |
470 | 486 |
471 bool InstantController::OnUpOrDownKeyPressed(int count) { | 487 bool InstantController::OnUpOrDownKeyPressed(int count) { |
472 if (!extended_enabled_) | 488 if (!extended_enabled_) |
473 return false; | 489 return false; |
474 | 490 |
475 if (!instant_tab_ && !loader_) | 491 if (!instant_tab_ && !overlay_) |
476 return false; | 492 return false; |
477 | 493 |
478 if (instant_tab_) | 494 if (instant_tab_) |
479 instant_tab_->UpOrDownKeyPressed(count); | 495 instant_tab_->UpOrDownKeyPressed(count); |
480 else | 496 else |
481 loader_->UpOrDownKeyPressed(count); | 497 overlay_->UpOrDownKeyPressed(count); |
482 | 498 |
483 return true; | 499 return true; |
484 } | 500 } |
485 | 501 |
486 content::WebContents* InstantController::GetPreviewContents() const { | 502 content::WebContents* InstantController::GetPreviewContents() const { |
487 return loader_ ? loader_->contents() : NULL; | 503 return overlay_ ? overlay_->contents() : NULL; |
488 } | 504 } |
489 | 505 |
490 bool InstantController::IsPreviewingSearchResults() const { | 506 bool InstantController::IsPreviewingSearchResults() const { |
491 return model_.mode().is_search_suggestions() && IsFullHeight(model_) && | 507 return model_.mode().is_search_suggestions() && IsFullHeight(model_) && |
492 (last_match_was_search_ || | 508 (last_match_was_search_ || |
493 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER); | 509 last_suggestion_.behavior == INSTANT_COMPLETE_NEVER); |
494 } | 510 } |
495 | 511 |
496 bool InstantController::CommitIfPossible(InstantCommitType type) { | 512 bool InstantController::CommitIfPossible(InstantCommitType type) { |
497 if (!extended_enabled_ && !instant_enabled_) | 513 if (!extended_enabled_ && !instant_enabled_) |
(...skipping 16 matching lines...) Expand all Loading... | |
514 return true; | 530 return true; |
515 } | 531 } |
516 return false; | 532 return false; |
517 } | 533 } |
518 | 534 |
519 if (!IsPreviewingSearchResults() && type != INSTANT_COMMIT_NAVIGATED) | 535 if (!IsPreviewingSearchResults() && type != INSTANT_COMMIT_NAVIGATED) |
520 return false; | 536 return false; |
521 | 537 |
522 // There may re-entrance here, from the call to browser_->CommitInstant below, | 538 // There may re-entrance here, from the call to browser_->CommitInstant below, |
523 // which can cause a TabDeactivated notification which gets back here. | 539 // which can cause a TabDeactivated notification which gets back here. |
524 // In this case, loader_->ReleaseContents() was called already. | 540 // In this case, overlay_->ReleaseContents() was called already. |
525 if (!GetPreviewContents()) | 541 if (!GetPreviewContents()) |
526 return false; | 542 return false; |
527 | 543 |
528 // Never commit the local omnibox. | 544 // Never commit the local omnibox. |
529 if (loader_->IsUsingLocalPreview()) | 545 if (overlay_->IsUsingLocalPreview()) |
530 return false; | 546 return false; |
531 | 547 |
532 if (type == INSTANT_COMMIT_FOCUS_LOST) | 548 if (type == INSTANT_COMMIT_FOCUS_LOST) |
533 loader_->Cancel(last_omnibox_text_); | 549 overlay_->Cancel(last_omnibox_text_); |
534 else if (type != INSTANT_COMMIT_NAVIGATED && | 550 else if (type != INSTANT_COMMIT_NAVIGATED && |
535 type != INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION) | 551 type != INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION) |
536 loader_->Submit(last_omnibox_text_); | 552 overlay_->Submit(last_omnibox_text_); |
537 | 553 |
538 content::WebContents* preview = loader_->ReleaseContents(); | 554 scoped_ptr<content::WebContents> preview = overlay_->ReleaseContents(); |
539 | 555 |
540 if (extended_enabled_) { | 556 if (extended_enabled_) { |
541 // Consider what's happening: | 557 // Consider what's happening: |
542 // 1. The user has typed a query in the omnibox and committed it (either | 558 // 1. The user has typed a query in the omnibox and committed it (either |
543 // by pressing Enter or clicking on the preview). | 559 // by pressing Enter or clicking on the preview). |
544 // 2. We commit the preview to the tab strip, and tell the page. | 560 // 2. We commit the preview to the tab strip, and tell the page. |
545 // 3. The page will update the URL hash fragment with the query terms. | 561 // 3. The page will update the URL hash fragment with the query terms. |
546 // After steps 1 and 3, the omnibox will show the query terms. However, if | 562 // After steps 1 and 3, the omnibox will show the query terms. However, if |
547 // the URL we are committing at step 2 doesn't already have query terms, it | 563 // the URL we are committing at step 2 doesn't already have query terms, it |
548 // will flash for a brief moment as a plain URL. So, avoid that flicker by | 564 // will flash for a brief moment as a plain URL. So, avoid that flicker by |
549 // pretending that the plain URL is actually the typed query terms. | 565 // pretending that the plain URL is actually the typed query terms. |
550 // TODO(samarth,beaudoin): Instead of this hack, we should add a new field | 566 // TODO(samarth,beaudoin): Instead of this hack, we should add a new field |
551 // to NavigationEntry to keep track of what the correct query, if any, is. | 567 // to NavigationEntry to keep track of what the correct query, if any, is. |
552 content::NavigationEntry* entry = | 568 content::NavigationEntry* entry = |
553 preview->GetController().GetVisibleEntry(); | 569 preview->GetController().GetVisibleEntry(); |
554 std::string url = entry->GetVirtualURL().spec(); | 570 std::string url = entry->GetVirtualURL().spec(); |
555 if (!google_util::IsInstantExtendedAPIGoogleSearchUrl(url) && | 571 if (!google_util::IsInstantExtendedAPIGoogleSearchUrl(url) && |
556 google_util::IsGoogleDomainUrl(url, google_util::ALLOW_SUBDOMAIN, | 572 google_util::IsGoogleDomainUrl(url, google_util::ALLOW_SUBDOMAIN, |
557 google_util::ALLOW_NON_STANDARD_PORTS)) { | 573 google_util::ALLOW_NON_STANDARD_PORTS)) { |
558 // Hitting ENTER searches for what the user typed, so use | 574 // Hitting ENTER searches for what the user typed, so use |
559 // last_omnibox_text_. Clicking on the overlay commits what is currently | 575 // last_omnibox_text_. Clicking on the overlay commits what is currently |
560 // showing, so add in the gray text in that case. | 576 // showing, so add in the gray text in that case. |
561 std::string query(UTF16ToUTF8(last_omnibox_text_)); | 577 std::string query(UTF16ToUTF8(last_omnibox_text_)); |
562 if (type != INSTANT_COMMIT_PRESSED_ENTER) | 578 if (type != INSTANT_COMMIT_PRESSED_ENTER) |
563 query += UTF16ToUTF8(last_suggestion_.text); | 579 query += UTF16ToUTF8(last_suggestion_.text); |
564 entry->SetVirtualURL(GURL( | 580 entry->SetVirtualURL(GURL( |
565 url + "#q=" + | 581 url + "#q=" + |
566 net::EscapeQueryParamValue(query, true))); | 582 net::EscapeQueryParamValue(query, true))); |
567 chrome::search::SearchTabHelper::FromWebContents(preview)-> | 583 chrome::search::SearchTabHelper::FromWebContents(preview.get())-> |
568 NavigationEntryUpdated(); | 584 NavigationEntryUpdated(); |
569 } | 585 } |
570 } | 586 } |
571 | 587 |
572 // If the preview page has navigated since the last Update(), we need to add | 588 // If the preview page has navigated since the last Update(), we need to add |
573 // the navigation to history ourselves. Else, the page will navigate after | 589 // the navigation to history ourselves. Else, the page will navigate after |
574 // commit, and it will be added to history in the usual manner. | 590 // commit, and it will be added to history in the usual manner. |
575 const history::HistoryAddPageArgs& last_navigation = | 591 const history::HistoryAddPageArgs& last_navigation = |
576 loader_->last_navigation(); | 592 overlay_->last_navigation(); |
577 if (!last_navigation.url.is_empty()) { | 593 if (!last_navigation.url.is_empty()) { |
578 content::NavigationEntry* entry = preview->GetController().GetActiveEntry(); | 594 content::NavigationEntry* entry = preview->GetController().GetActiveEntry(); |
579 | 595 |
580 // The last navigation should be the same as the active entry if the loader | 596 // The last navigation should be the same as the active entry if the overlay |
581 // is in search mode. During navigation, the active entry could have | 597 // is in search mode. During navigation, the active entry could have |
582 // changed since DidCommitProvisionalLoadForFrame is called after the entry | 598 // changed since DidCommitProvisionalLoadForFrame is called after the entry |
583 // is changed. | 599 // is changed. |
584 // TODO(shishir): Should we commit the last navigation for | 600 // TODO(shishir): Should we commit the last navigation for |
585 // INSTANT_COMMIT_NAVIGATED. | 601 // INSTANT_COMMIT_NAVIGATED. |
586 DCHECK(type == INSTANT_COMMIT_NAVIGATED || | 602 DCHECK(type == INSTANT_COMMIT_NAVIGATED || |
587 last_navigation.url == entry->GetURL()); | 603 last_navigation.url == entry->GetURL()); |
588 | 604 |
589 // Add the page to history. | 605 // Add the page to history. |
590 HistoryTabHelper* history_tab_helper = | 606 HistoryTabHelper* history_tab_helper = |
591 HistoryTabHelper::FromWebContents(preview); | 607 HistoryTabHelper::FromWebContents(preview.get()); |
592 history_tab_helper->UpdateHistoryForNavigation(last_navigation); | 608 history_tab_helper->UpdateHistoryForNavigation(last_navigation); |
593 | 609 |
594 // Update the page title. | 610 // Update the page title. |
595 history_tab_helper->UpdateHistoryPageTitle(*entry); | 611 history_tab_helper->UpdateHistoryPageTitle(*entry); |
596 } | 612 } |
597 | 613 |
598 // Add a fake history entry with a non-Instant search URL, so that search | 614 // Add a fake history entry with a non-Instant search URL, so that search |
599 // terms extraction (for autocomplete history matches) works. | 615 // terms extraction (for autocomplete history matches) works. |
600 HistoryService* history = HistoryServiceFactory::GetForProfile( | 616 HistoryService* history = HistoryServiceFactory::GetForProfile( |
601 Profile::FromBrowserContext(preview->GetBrowserContext()), | 617 Profile::FromBrowserContext(preview->GetBrowserContext()), |
602 Profile::EXPLICIT_ACCESS); | 618 Profile::EXPLICIT_ACCESS); |
603 if (history) { | 619 if (history) { |
604 history->AddPage(url_for_history_, base::Time::Now(), NULL, 0, GURL(), | 620 history->AddPage(url_for_history_, base::Time::Now(), NULL, 0, GURL(), |
605 history::RedirectList(), last_transition_type_, | 621 history::RedirectList(), last_transition_type_, |
606 history::SOURCE_BROWSED, false); | 622 history::SOURCE_BROWSED, false); |
607 } | 623 } |
608 | 624 |
609 preview->GetController().PruneAllButActive(); | 625 preview->GetController().PruneAllButActive(); |
610 | 626 |
611 if (type != INSTANT_COMMIT_PRESSED_ALT_ENTER) { | 627 if (type != INSTANT_COMMIT_PRESSED_ALT_ENTER) { |
612 content::WebContents* active_tab = browser_->GetActiveWebContents(); | 628 content::WebContents* active_tab = browser_->GetActiveWebContents(); |
613 AddSessionStorageHistogram(extended_enabled_, active_tab, preview); | 629 AddSessionStorageHistogram(extended_enabled_, active_tab, preview.get()); |
614 preview->GetController().CopyStateFromAndPrune( | 630 preview->GetController().CopyStateFromAndPrune( |
615 &active_tab->GetController()); | 631 &active_tab->GetController()); |
616 } | 632 } |
617 | 633 |
618 // Browser takes ownership of the preview. | 634 // Save notification source before we release the preview. |
619 browser_->CommitInstant(preview, type == INSTANT_COMMIT_PRESSED_ALT_ENTER); | 635 const content::NotificationSource& notification_source = |
636 content::Source<content::WebContents>(preview.get()); | |
637 | |
638 browser_->CommitInstant(preview.Pass(), | |
639 type == INSTANT_COMMIT_PRESSED_ALT_ENTER); | |
620 | 640 |
621 content::NotificationService::current()->Notify( | 641 content::NotificationService::current()->Notify( |
622 chrome::NOTIFICATION_INSTANT_COMMITTED, | 642 chrome::NOTIFICATION_INSTANT_COMMITTED, |
623 content::Source<content::WebContents>(preview), | 643 notification_source, |
624 content::NotificationService::NoDetails()); | 644 content::NotificationService::NoDetails()); |
625 | 645 |
626 // Hide explicitly. See comments in HideLoader() for why. | 646 // Hide explicitly. See comments in HideOverlay() for why. |
627 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); | 647 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); |
628 | 648 |
629 // Delay deletion as we could've gotten here from an InstantLoader method. | 649 // Delay deletion as we could've gotten here from an InstantOverlay method. |
630 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); | 650 MessageLoop::current()->DeleteSoon(FROM_HERE, overlay_.release()); |
631 | 651 |
632 // Try to create another loader immediately so that it is ready for the next | 652 // Try to create another overlay immediately so that it is ready for the next |
633 // user interaction. | 653 // user interaction. |
634 EnsureLoaderIsCurrent(); | 654 EnsureOverlayIsCurrent(); |
635 | 655 |
636 LOG_INSTANT_DEBUG_EVENT(this, "Committed"); | 656 LOG_INSTANT_DEBUG_EVENT(this, "Committed"); |
637 return true; | 657 return true; |
638 } | 658 } |
639 | 659 |
640 void InstantController::OmniboxFocusChanged( | 660 void InstantController::OmniboxFocusChanged( |
641 OmniboxFocusState state, | 661 OmniboxFocusState state, |
642 OmniboxFocusChangeReason reason, | 662 OmniboxFocusChangeReason reason, |
643 gfx::NativeView view_gaining_focus) { | 663 gfx::NativeView view_gaining_focus) { |
644 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 664 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
645 "OmniboxFocusChanged: %d to %d for reason %d", omnibox_focus_state_, | 665 "OmniboxFocusChanged: %d to %d for reason %d", omnibox_focus_state_, |
646 state, reason)); | 666 state, reason)); |
647 | 667 |
648 OmniboxFocusState old_focus_state = omnibox_focus_state_; | 668 OmniboxFocusState old_focus_state = omnibox_focus_state_; |
649 omnibox_focus_state_ = state; | 669 omnibox_focus_state_ = state; |
650 if (!extended_enabled_ && !instant_enabled_) | 670 if (!extended_enabled_ && !instant_enabled_) |
651 return; | 671 return; |
652 | 672 |
653 // Tell the page if the key capture mode changed unless the focus state | 673 // Tell the page if the key capture mode changed unless the focus state |
654 // changed because of TYPING. This is because in that case, the browser hasn't | 674 // changed because of TYPING. This is because in that case, the browser hasn't |
655 // really stopped capturing key strokes. | 675 // really stopped capturing key strokes. |
656 // | 676 // |
657 // (More practically, if we don't do this check, the page would receive | 677 // (More practically, if we don't do this check, the page would receive |
658 // onkeycapturechange before the corresponding onchange, and the page would | 678 // onkeycapturechange before the corresponding onchange, and the page would |
659 // have no way of telling whether the keycapturechange happened because of | 679 // have no way of telling whether the keycapturechange happened because of |
660 // some actual user action or just because they started typing.) | 680 // some actual user action or just because they started typing.) |
661 if (extended_enabled_ && GetPreviewContents() && | 681 if (extended_enabled_ && GetPreviewContents() && |
662 reason != OMNIBOX_FOCUS_CHANGE_TYPING) | 682 reason != OMNIBOX_FOCUS_CHANGE_TYPING) { |
663 loader_->KeyCaptureChanged(omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); | 683 const bool is_key_capture_enabled = |
684 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE; | |
685 if (overlay_) | |
686 overlay_->KeyCaptureChanged(is_key_capture_enabled); | |
687 if (instant_tab_) | |
688 instant_tab_->KeyCaptureChanged(is_key_capture_enabled); | |
689 } | |
664 | 690 |
665 // If focus went from outside the omnibox to the omnibox, preload the default | 691 // If focus went from outside the omnibox to the omnibox, preload the default |
666 // search engine, in anticipation of the user typing a query. If the reverse | 692 // search engine, in anticipation of the user typing a query. If the reverse |
667 // happened, commit or discard the preview. | 693 // happened, commit or discard the preview. |
668 if (state != OMNIBOX_FOCUS_NONE && old_focus_state == OMNIBOX_FOCUS_NONE) | 694 if (state != OMNIBOX_FOCUS_NONE && old_focus_state == OMNIBOX_FOCUS_NONE) |
669 EnsureLoaderIsCurrent(); | 695 EnsureOverlayIsCurrent(); |
670 else if (state == OMNIBOX_FOCUS_NONE && old_focus_state != OMNIBOX_FOCUS_NONE) | 696 else if (state == OMNIBOX_FOCUS_NONE && old_focus_state != OMNIBOX_FOCUS_NONE) |
671 OmniboxLostFocus(view_gaining_focus); | 697 OmniboxLostFocus(view_gaining_focus); |
672 } | 698 } |
673 | 699 |
674 void InstantController::SearchModeChanged( | 700 void InstantController::SearchModeChanged( |
675 const chrome::search::Mode& old_mode, | 701 const chrome::search::Mode& old_mode, |
676 const chrome::search::Mode& new_mode) { | 702 const chrome::search::Mode& new_mode) { |
677 if (!extended_enabled_) | 703 if (!extended_enabled_) |
678 return; | 704 return; |
679 | 705 |
680 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 706 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
681 "SearchModeChanged: [origin:mode] %d:%d to %d:%d", old_mode.origin, | 707 "SearchModeChanged: [origin:mode] %d:%d to %d:%d", old_mode.origin, |
682 old_mode.mode, new_mode.origin, new_mode.mode)); | 708 old_mode.mode, new_mode.origin, new_mode.mode)); |
683 | 709 |
684 search_mode_ = new_mode; | 710 search_mode_ = new_mode; |
685 if (!new_mode.is_search_suggestions()) | 711 if (!new_mode.is_search_suggestions()) |
686 HideLoader(); | 712 HideOverlay(); |
687 | 713 |
688 if (loader_) | 714 if (overlay_) |
689 loader_->SearchModeChanged(new_mode); | 715 overlay_->SearchModeChanged(new_mode); |
690 | 716 |
691 ResetInstantTab(); | 717 ResetInstantTab(); |
692 } | 718 } |
693 | 719 |
694 void InstantController::ActiveTabChanged() { | 720 void InstantController::ActiveTabChanged() { |
695 if (!extended_enabled_ && !instant_enabled_) | 721 if (!extended_enabled_ && !instant_enabled_) |
696 return; | 722 return; |
697 | 723 |
698 LOG_INSTANT_DEBUG_EVENT(this, "ActiveTabChanged"); | 724 LOG_INSTANT_DEBUG_EVENT(this, "ActiveTabChanged"); |
699 | 725 |
700 // When switching tabs, always hide the preview, except if it's showing NTP | 726 // When switching tabs, always hide the preview. |
701 // content, and the new tab is also an NTP. | 727 HideOverlay(); |
702 if (!search_mode_.is_ntp() || !model_.mode().is_ntp()) | |
703 HideLoader(); | |
704 | 728 |
705 if (extended_enabled_) | 729 if (extended_enabled_) |
706 ResetInstantTab(); | 730 ResetInstantTab(); |
707 } | 731 } |
708 | 732 |
709 void InstantController::TabDeactivated(content::WebContents* contents) { | 733 void InstantController::TabDeactivated(content::WebContents* contents) { |
710 LOG_INSTANT_DEBUG_EVENT(this, "TabDeactivated"); | 734 LOG_INSTANT_DEBUG_EVENT(this, "TabDeactivated"); |
711 if (extended_enabled_ && !contents->IsBeingDestroyed()) | 735 if (extended_enabled_ && !contents->IsBeingDestroyed()) |
712 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); | 736 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); |
713 } | 737 } |
714 | 738 |
715 void InstantController::SetInstantEnabled(bool instant_enabled) { | 739 void InstantController::SetInstantEnabled(bool instant_enabled) { |
716 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 740 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
717 "SetInstantEnabled: %d", instant_enabled)); | 741 "SetInstantEnabled: %d", instant_enabled)); |
718 instant_enabled_ = instant_enabled; | 742 instant_enabled_ = instant_enabled; |
719 HideInternal(); | 743 HideInternal(); |
720 loader_.reset(); | 744 overlay_.reset(); |
721 if (extended_enabled_ || instant_enabled_) | 745 if (extended_enabled_ || instant_enabled_) |
722 EnsureLoaderIsCurrent(); | 746 EnsureOverlayIsCurrent(); |
747 if (extended_enabled_) | |
748 ResetNTP(); | |
723 if (instant_tab_) | 749 if (instant_tab_) |
724 instant_tab_->SetDisplayInstantResults(instant_enabled_); | 750 instant_tab_->SetDisplayInstantResults(instant_enabled_); |
725 } | 751 } |
726 | 752 |
727 void InstantController::ThemeChanged(const ThemeBackgroundInfo& theme_info) { | 753 void InstantController::ThemeChanged(const ThemeBackgroundInfo& theme_info) { |
728 if (!extended_enabled_) | 754 if (!extended_enabled_) |
729 return; | 755 return; |
730 | 756 |
731 if (loader_) | 757 if (overlay_) |
732 loader_->SendThemeBackgroundInfo(theme_info); | 758 overlay_->SendThemeBackgroundInfo(theme_info); |
759 if (ntp_) | |
760 ntp_->SendThemeBackgroundInfo(theme_info); | |
733 } | 761 } |
734 | 762 |
735 void InstantController::ThemeAreaHeightChanged(int height) { | 763 void InstantController::ThemeAreaHeightChanged(int height) { |
736 if (!extended_enabled_) | 764 if (!extended_enabled_) |
737 return; | 765 return; |
738 | 766 |
739 if (loader_) | 767 if (overlay_) |
740 loader_->SendThemeAreaHeight(height); | 768 overlay_->SendThemeAreaHeight(height); |
769 if (ntp_) | |
770 ntp_->SendThemeAreaHeight(height); | |
771 } | |
772 | |
773 void InstantController::SwappedOverlayContents() { | |
774 model_.SetPreviewContents(GetPreviewContents()); | |
775 } | |
776 | |
777 void InstantController::FocusedOverlayContents() { | |
778 #if defined(USE_AURA) | |
779 // On aura the omnibox only receives a focus lost if we initiate the focus | |
780 // change. This does that. | |
781 if (!model_.mode().is_default()) | |
782 browser_->InstantPreviewFocused(); | |
783 #endif | |
784 } | |
785 | |
786 void InstantController::HandleStaleOverlay() { | |
787 // The local popup is never stale. | |
788 if (overlay_ && overlay_->IsUsingLocalPreview()) | |
789 return; | |
790 | |
791 // If the preview is showing or the omnibox has focus, don't delete the | |
792 // overlay. It will get refreshed the next time the preview is hidden or the | |
793 // omnibox loses focus. | |
794 if ((!overlay_ || overlay_->is_stale()) && | |
795 omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && | |
796 model_.mode().is_default()) { | |
797 overlay_.reset(); | |
798 EnsureOverlayIsCurrent(); | |
799 } | |
800 } | |
801 | |
802 void InstantController::LogDebugEvent(const std::string& info) const { | |
803 DVLOG(1) << info; | |
804 | |
805 debug_events_.push_front(std::make_pair( | |
806 base::Time::Now().ToInternalValue(), info)); | |
807 static const size_t kMaxDebugEventSize = 2000; | |
808 if (debug_events_.size() > kMaxDebugEventSize) | |
809 debug_events_.pop_back(); | |
810 } | |
811 | |
812 void InstantController::InstantSupportDetermined( | |
813 const content::WebContents* contents, | |
814 bool supports_instant) { | |
815 if (ContentsFrom(instant_tab_.get(), contents)) { | |
816 if (!supports_instant) | |
817 MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release()); | |
818 } else if (ContentsFrom(ntp_.get(), contents)) { | |
819 if (supports_instant) | |
820 RemoveFromBlacklist(ntp_->instant_url()); | |
821 else | |
822 BlacklistAndResetNTP(); | |
823 } else if (ContentsFrom(overlay_.get(), contents)) { | |
824 if (supports_instant) | |
825 RemoveFromBlacklist(overlay_->instant_url()); | |
826 else | |
827 BlacklistAndResetOverlay(); | |
828 | |
829 content::NotificationService::current()->Notify( | |
dhollowa
2013/01/29 02:37:53
This doesn't indicate *which* page's Instant suppo
samarth
2013/01/29 05:42:01
Luckily it turns out the only user of this is the
| |
830 chrome::NOTIFICATION_INSTANT_SUPPORT_DETERMINED, | |
831 content::Source<InstantController>(this), | |
832 content::NotificationService::NoDetails()); | |
833 } | |
834 } | |
835 | |
836 void InstantController::InstantPageRenderViewGone( | |
837 const content::WebContents* contents) { | |
838 if (ContentsFrom(overlay_.get(), contents)) | |
839 BlacklistAndResetOverlay(); | |
840 else if (ContentsFrom(ntp_.get(), contents)) | |
841 BlacklistAndResetNTP(); | |
842 } | |
843 | |
844 void InstantController::InstantPageAboutToNavigateMainFrame( | |
845 const content::WebContents* contents, | |
846 const GURL& url) { | |
847 if (!ContentsFrom(overlay_.get(), contents)) | |
848 return; | |
849 | |
850 // If the page does not yet support instant, we allow redirects and other | |
851 // navigations to go through since the instant URL can redirect - e.g. to | |
852 // country specific pages. | |
853 if (!overlay_->supports_instant()) | |
854 return; | |
855 | |
856 GURL instant_url(overlay_->instant_url()); | |
857 | |
858 // If we are navigating to the instant URL, do nothing. | |
859 if (url == instant_url) | |
860 return; | |
861 | |
862 // Commit the navigation if either: | |
863 // - The page is in NTP mode (so it could only navigate on a user click) or | |
864 // - The page is not in NTP mode and we are navigating to a URL with a | |
865 // different host or path than the instant URL. This enables the instant | |
866 // page when it is showing search results to change the query parameters | |
867 // and fragments of the URL without it navigating. | |
868 if (model_.mode().is_ntp() || | |
869 (url.host() != instant_url.host() || url.path() != instant_url.path())) { | |
870 CommitIfPossible(INSTANT_COMMIT_NAVIGATED); | |
871 } | |
741 } | 872 } |
742 | 873 |
743 void InstantController::SetSuggestions( | 874 void InstantController::SetSuggestions( |
744 const content::WebContents* contents, | 875 const content::WebContents* contents, |
745 const std::vector<InstantSuggestion>& suggestions) { | 876 const std::vector<InstantSuggestion>& suggestions) { |
746 LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions"); | 877 LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions"); |
747 | 878 |
748 // Ignore if the message is from an unexpected source. | 879 // Ignore if the message is from an unexpected source. |
749 if (instant_tab_) { | 880 if (ContentsFrom(ntp_.get(), contents)) |
750 if (instant_tab_->contents() != contents) | |
751 return; | |
752 } else if (!loader_ || loader_->contents() != contents || | |
753 !allow_preview_to_show_search_suggestions_) { | |
754 return; | 881 return; |
755 } | 882 if (instant_tab_ && !ContentsFrom(instant_tab_.get(), contents)) |
883 return; | |
884 if (ContentsFrom(overlay_.get(), contents) && | |
885 !allow_preview_to_show_search_suggestions_) | |
886 return; | |
756 | 887 |
757 InstantSuggestion suggestion; | 888 InstantSuggestion suggestion; |
758 if (!suggestions.empty()) | 889 if (!suggestions.empty()) |
759 suggestion = suggestions[0]; | 890 suggestion = suggestions[0]; |
760 | 891 |
761 if (instant_tab_ && search_mode_.is_search_results() && | 892 if (instant_tab_ && search_mode_.is_search_results() && |
762 suggestion.behavior == INSTANT_COMPLETE_REPLACE) { | 893 suggestion.behavior == INSTANT_COMPLETE_REPLACE) { |
763 // This means a committed page in state search called setValue(). We should | 894 // This means a committed page in state search called setValue(). We should |
764 // update the omnibox to reflect what the search page says. | 895 // update the omnibox to reflect what the search page says. |
765 browser_->SetInstantSuggestion(suggestion); | 896 browser_->SetInstantSuggestion(suggestion); |
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
823 last_suggestion_ = suggestion; | 954 last_suggestion_ = suggestion; |
824 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 955 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
825 "SetInstantSuggestion: text='%s' behavior=%d", | 956 "SetInstantSuggestion: text='%s' behavior=%d", |
826 UTF16ToUTF8(suggestion.text).c_str(), suggestion.behavior)); | 957 UTF16ToUTF8(suggestion.text).c_str(), suggestion.behavior)); |
827 browser_->SetInstantSuggestion(suggestion); | 958 browser_->SetInstantSuggestion(suggestion); |
828 } else { | 959 } else { |
829 last_suggestion_ = InstantSuggestion(); | 960 last_suggestion_ = InstantSuggestion(); |
830 } | 961 } |
831 } | 962 } |
832 | 963 |
833 // Extended mode pages will call ShowLoader() when they are ready. | 964 // Extended mode pages will call ShowOverlay() when they are ready. |
834 if (!extended_enabled_) | 965 if (!extended_enabled_) |
835 ShowLoader(INSTANT_SHOWN_QUERY_SUGGESTIONS, 100, INSTANT_SIZE_PERCENT); | 966 ShowOverlay(INSTANT_SHOWN_QUERY_SUGGESTIONS, 100, INSTANT_SIZE_PERCENT); |
836 } | 967 } |
837 | 968 |
838 void InstantController::InstantSupportDetermined( | 969 void InstantController::ShowInstantPreview(const content::WebContents* contents, |
839 const content::WebContents* contents, | 970 InstantShownReason reason, |
840 bool supports_instant) { | 971 int height, |
841 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 972 InstantSizeUnits units) { |
842 "InstantSupportDetermined: supports_instant= %d", supports_instant)); | 973 if (extended_enabled_ && ContentsFrom(overlay_.get(), contents)) |
974 ShowOverlay(reason, height, units); | |
975 } | |
843 | 976 |
844 if (instant_tab_ && instant_tab_->contents() == contents) { | 977 void InstantController::StartCapturingKeyStrokes( |
845 if (!supports_instant) | 978 const content::WebContents* contents) { |
846 MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release()); | 979 if (!extended_enabled_) |
847 return; | 980 return; |
848 } | |
849 | 981 |
850 if (loader_ && loader_->contents() == contents) { | 982 // Only honor the call if it comes from an active InstantTab or from an |
851 if (supports_instant) { | 983 // InstantOverlay that is being shown. |
852 if (blacklisted_urls_.erase(loader_->instant_url())) { | 984 if (ContentsFrom(instant_tab_.get(), contents) || |
853 RecordEventHistogram( | 985 (ContentsFrom(overlay_.get(), contents) && !model_.mode().is_default())) { |
854 INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST); | 986 browser_->FocusOmniboxInvisibly(); |
855 } | |
856 } else { | |
857 ++blacklisted_urls_[loader_->instant_url()]; | |
858 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST); | |
859 HideInternal(); | |
860 delete loader_->ReleaseContents(); | |
861 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); | |
862 EnsureLoaderIsCurrent(); | |
863 } | |
864 content::NotificationService::current()->Notify( | |
865 chrome::NOTIFICATION_INSTANT_SUPPORT_DETERMINED, | |
866 content::Source<InstantController>(this), | |
867 content::NotificationService::NoDetails()); | |
868 } | 987 } |
869 } | 988 } |
870 | 989 |
871 void InstantController::ShowInstantPreview(InstantShownReason reason, | 990 void InstantController::StopCapturingKeyStrokes( |
872 int height, | 991 content::WebContents* contents) { |
873 InstantSizeUnits units) { | 992 // Nothing to do if omnibox doesn't have invisible focus. |
874 if (extended_enabled_) | 993 if (!extended_enabled_ || omnibox_focus_state_ != OMNIBOX_FOCUS_INVISIBLE) |
875 ShowLoader(reason, height, units); | |
876 } | |
877 | |
878 void InstantController::StartCapturingKeyStrokes() { | |
879 // Ignore unless the loader is active and on the NTP. | |
880 if (extended_enabled_ && !instant_tab_ && model_.mode().is_ntp()) | |
881 browser_->FocusOmniboxInvisibly(); | |
882 } | |
883 | |
884 void InstantController::StopCapturingKeyStrokes() { | |
885 // Ignore unless the loader is active and on the NTP, and the omnibox has | |
886 // invisible focus. | |
887 if (extended_enabled_ && !instant_tab_ && model_.mode().is_ntp() && | |
888 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE) | |
889 loader_->contents()->Focus(); | |
890 } | |
891 | |
892 void InstantController::SwappedWebContents() { | |
893 model_.SetPreviewContents(GetPreviewContents()); | |
894 } | |
895 | |
896 void InstantController::InstantLoaderContentsFocused() { | |
897 #if defined(USE_AURA) | |
898 // On aura the omnibox only receives a focus lost if we initiate the focus | |
899 // change. This does that. | |
900 if (!model_.mode().is_default()) | |
901 browser_->InstantPreviewFocused(); | |
902 #endif | |
903 } | |
904 | |
905 void InstantController::InstantLoaderRenderViewGone() { | |
906 ++blacklisted_urls_[loader_->instant_url()]; | |
907 HideInternal(); | |
908 delete loader_->ReleaseContents(); | |
909 // Delay deletion as we have gotten here from an InstantLoader method. | |
910 MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); | |
911 EnsureLoaderIsCurrent(); | |
912 } | |
913 | |
914 void InstantController::InstantLoaderAboutToNavigateMainFrame(const GURL& url) { | |
915 // If the page does not yet support instant, we allow redirects and other | |
916 // navigations to go through since the instant URL can redirect - e.g. to | |
917 // country specific pages. | |
918 if (!loader_->supports_instant()) | |
919 return; | 994 return; |
920 | 995 |
921 GURL instant_url(loader_->instant_url()); | 996 // Only honor the call if it comes from an active InstantTab or from an |
922 | 997 // InstantOverlay that is being shown. |
923 // If we are navigating to the instant URL, do nothing. | 998 if (ContentsFrom(instant_tab_.get(), contents) || |
924 if (url == instant_url) | 999 (ContentsFrom(overlay_.get(), contents) && !model_.mode().is_default())) { |
925 return; | 1000 contents->Focus(); |
926 | |
927 // Commit the navigation if either: | |
928 // - The page is in NTP mode (so it could only navigate on a user click) or | |
929 // - The page is not in NTP mode and we are navigating to a URL with a | |
930 // different host or path than the instant URL. This enables the instant | |
931 // page when it is showing search results to change the query parameters | |
932 // and fragments of the URL without it navigating. | |
933 if (model_.mode().is_ntp() || | |
934 (url.host() != instant_url.host() || url.path() != instant_url.path())) { | |
935 CommitIfPossible(INSTANT_COMMIT_NAVIGATED); | |
936 } | 1001 } |
937 } | 1002 } |
938 | 1003 |
1004 void InstantController::NavigateToURL(const content::WebContents* contents, | |
1005 const GURL& url, | |
1006 content::PageTransition transition) { | |
1007 // TODO(samarth): handle case where contents are no longer "active" (e.g. user | |
1008 // has switched tabs). | |
1009 if (!extended_enabled_) | |
1010 return; | |
1011 if (overlay_) | |
1012 HideOverlay(); | |
1013 browser_->OpenURLInCurrentTab(url, transition); | |
1014 } | |
1015 | |
939 void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) { | 1016 void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) { |
940 // If the preview is showing custom NTP content, don't hide it, commit it | 1017 // If the preview is showing custom NTP content, don't hide it, commit it |
941 // (no matter where the user clicked) or try to recreate it. | 1018 // (no matter where the user clicked) or try to recreate it. |
942 if (model_.mode().is_ntp()) | 1019 if (model_.mode().is_ntp()) |
943 return; | 1020 return; |
944 | 1021 |
945 // If the preview is not showing at all, recreate it if it's stale. | 1022 // If the preview is not showing at all, recreate it if it's stale. |
946 if (model_.mode().is_default()) { | 1023 if (model_.mode().is_default()) { |
947 OnStaleLoader(); | 1024 HandleStaleOverlay(); |
948 return; | 1025 return; |
949 } | 1026 } |
950 | 1027 |
951 // The preview is showing search suggestions. If GetPreviewContents() is NULL, | 1028 // The preview is showing search suggestions. If GetPreviewContents() is NULL, |
952 // we are in the commit path. Don't do anything. | 1029 // we are in the commit path. Don't do anything. |
953 if (!GetPreviewContents()) | 1030 if (!GetPreviewContents()) |
954 return; | 1031 return; |
955 | 1032 |
956 #if defined(OS_MACOSX) | 1033 #if defined(OS_MACOSX) |
957 // TODO(sreeram): See if Mac really needs this special treatment. | 1034 // TODO(sreeram): See if Mac really needs this special treatment. |
958 if (!loader_->is_pointer_down_from_activate()) | 1035 if (!overlay_->is_pointer_down_from_activate()) |
959 HideLoader(); | 1036 HideOverlay(); |
960 #else | 1037 #else |
961 if (IsViewInContents(GetViewGainingFocus(view_gaining_focus), | 1038 if (IsViewInContents(GetViewGainingFocus(view_gaining_focus), |
962 loader_->contents())) | 1039 overlay_->contents())) |
963 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); | 1040 CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); |
964 else | 1041 else |
965 HideLoader(); | 1042 HideOverlay(); |
966 #endif | 1043 #endif |
967 } | 1044 } |
968 | 1045 |
969 void InstantController::NavigateToURL(const GURL& url, | 1046 void InstantController::ResetNTP() { |
970 content::PageTransition transition) { | 1047 std::string instant_url; |
971 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 1048 if (!GetInstantURL(browser_->profile(), &instant_url)) |
972 "NavigateToURL: url='%s'", url.spec().c_str())); | 1049 return; |
973 | 1050 |
974 if (!extended_enabled_) | 1051 ntp_.reset(new InstantNTP(this, instant_url)); |
975 return; | 1052 ntp_->InitContents(browser_->profile(), browser_->GetActiveWebContents(), |
976 if (loader_) | 1053 base::Bind(&InstantController::ResetNTP, |
977 HideLoader(); | 1054 base::Unretained(this))); |
978 browser_->OpenURLInCurrentTab(url, transition); | 1055 |
1056 // Ensure the searchbox API has the correct initial state. | |
1057 if (extended_enabled_) { | |
1058 browser_->UpdateThemeInfoForPreview(); | |
1059 ntp_->SetDisplayInstantResults(instant_enabled_); | |
1060 ntp_->SetMarginSize(start_margin_, end_margin_); | |
1061 } | |
979 } | 1062 } |
980 | 1063 |
981 void InstantController::LogDebugEvent(const std::string& info) const { | 1064 bool InstantController::EnsureOverlayIsCurrent() { |
982 DVLOG(1) << info; | |
983 | |
984 debug_events_.push_front(std::make_pair( | |
985 base::Time::Now().ToInternalValue(), info)); | |
986 static const size_t kMaxDebugEventSize = 2000; | |
987 if (debug_events_.size() > kMaxDebugEventSize) | |
988 debug_events_.pop_back(); | |
989 } | |
990 | |
991 bool InstantController::EnsureLoaderIsCurrent() { | |
992 // If there's no active tab, the browser is closing. | 1065 // If there's no active tab, the browser is closing. |
993 const content::WebContents* active_tab = browser_->GetActiveWebContents(); | 1066 const content::WebContents* active_tab = browser_->GetActiveWebContents(); |
994 if (!active_tab) | 1067 if (!active_tab) |
995 return false; | 1068 return false; |
996 | 1069 |
1070 Profile* profile = Profile::FromBrowserContext( | |
1071 active_tab->GetBrowserContext()); | |
997 std::string instant_url; | 1072 std::string instant_url; |
998 if (!GetInstantURL(active_tab, &instant_url)) { | 1073 if (!GetInstantURL(profile, &instant_url)) { |
999 // If we are in extended mode, fallback to the local popup. | 1074 // If we are in extended mode, fallback to the local popup. |
1000 if (extended_enabled_) | 1075 if (extended_enabled_) |
1001 instant_url = kLocalOmniboxPopupURL; | 1076 instant_url = kLocalOmniboxPopupURL; |
1002 else | 1077 else |
1003 return false; | 1078 return false; |
1004 } | 1079 } |
1005 | 1080 |
1006 if (!loader_ || loader_->instant_url() != instant_url) | 1081 if (!overlay_ || overlay_->instant_url() != instant_url) |
1007 CreateLoader(instant_url, active_tab); | 1082 CreateOverlay(instant_url, active_tab); |
1008 | 1083 |
1009 return true; | 1084 return true; |
1010 } | 1085 } |
1011 | 1086 |
1012 void InstantController::CreateLoader(const std::string& instant_url, | 1087 void InstantController::CreateOverlay(const std::string& instant_url, |
1013 const content::WebContents* active_tab) { | 1088 const content::WebContents* active_tab) { |
1014 HideInternal(); | 1089 HideInternal(); |
1015 loader_.reset(new InstantLoader(this, instant_url)); | 1090 overlay_.reset(new InstantOverlay(this, instant_url)); |
1016 loader_->InitContents(active_tab); | 1091 overlay_->InitContents(browser_->profile(), active_tab); |
1017 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 1092 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
1018 "CreateLoader: instant_url='%s'", instant_url.c_str())); | 1093 "CreateOverlay: instant_url='%s'", instant_url.c_str())); |
1019 | 1094 |
1020 // Ensure the searchbox API has the correct initial state. | 1095 // Ensure the searchbox API has the correct initial state. |
1021 if (extended_enabled_) { | 1096 if (extended_enabled_) { |
1022 browser_->UpdateThemeInfoForPreview(); | 1097 browser_->UpdateThemeInfoForPreview(); |
1023 loader_->SetDisplayInstantResults(instant_enabled_); | 1098 overlay_->SetDisplayInstantResults(instant_enabled_); |
1024 loader_->SearchModeChanged(search_mode_); | 1099 overlay_->SearchModeChanged(search_mode_); |
1025 loader_->KeyCaptureChanged(omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); | 1100 overlay_->KeyCaptureChanged( |
1026 loader_->SetMarginSize(start_margin_, end_margin_); | 1101 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); |
1027 } | 1102 overlay_->SetMarginSize(start_margin_, end_margin_); |
1028 | |
1029 // Restart the stale loader timer. | |
1030 stale_loader_timer_.Start(FROM_HERE, | |
1031 base::TimeDelta::FromMilliseconds(kStaleLoaderTimeoutMS), this, | |
1032 &InstantController::OnStaleLoader); | |
1033 } | |
1034 | |
1035 void InstantController::OnStaleLoader() { | |
1036 // The local popup is never stale. | |
1037 if (loader_ && loader_->IsUsingLocalPreview()) | |
1038 return; | |
1039 | |
1040 // If the preview is showing or the omnibox has focus, don't delete the | |
1041 // loader. It will get refreshed the next time the preview is hidden or the | |
1042 // omnibox loses focus. | |
1043 if (!stale_loader_timer_.IsRunning() && | |
1044 omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && | |
1045 model_.mode().is_default()) { | |
1046 loader_.reset(); | |
1047 EnsureLoaderIsCurrent(); | |
1048 } | 1103 } |
1049 } | 1104 } |
1050 | 1105 |
1051 void InstantController::ResetInstantTab() { | 1106 void InstantController::ResetInstantTab() { |
1052 // Do not wire up the InstantTab if instant should only use local previews, to | 1107 // Do not wire up the InstantTab if instant should only use local previews, to |
1053 // prevent it from sending data to the page. | 1108 // prevent it from sending data to the page. |
1054 if (search_mode_.is_origin_search() && !use_local_preview_only_) { | 1109 if (!search_mode_.is_origin_default() && !use_local_preview_only_) { |
1055 content::WebContents* active_tab = browser_->GetActiveWebContents(); | 1110 content::WebContents* active_tab = browser_->GetActiveWebContents(); |
1056 if (!instant_tab_ || active_tab != instant_tab_->contents()) { | 1111 if (!instant_tab_ || active_tab != instant_tab_->contents()) { |
1057 instant_tab_.reset(new InstantTab(this, active_tab)); | 1112 instant_tab_.reset(new InstantTab(this)); |
1058 instant_tab_->Init(); | 1113 instant_tab_->Init(active_tab); |
1059 instant_tab_->SetDisplayInstantResults(instant_enabled_); | 1114 instant_tab_->SetDisplayInstantResults(instant_enabled_); |
1060 instant_tab_->SetMarginSize(start_margin_, end_margin_); | 1115 instant_tab_->SetMarginSize(start_margin_, end_margin_); |
1116 instant_tab_->KeyCaptureChanged( | |
1117 omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); | |
1061 } | 1118 } |
1062 | 1119 |
1063 // Hide the |loader_| since we are now using |instant_tab_| instead. | 1120 // Hide the |overlay_| since we are now using |instant_tab_| instead. |
1064 HideLoader(); | 1121 HideOverlay(); |
1065 } else { | 1122 } else { |
1066 instant_tab_.reset(); | 1123 instant_tab_.reset(); |
1067 } | 1124 } |
1068 } | 1125 } |
1069 | 1126 |
1070 void InstantController::HideLoader() { | 1127 void InstantController::HideOverlay() { |
1071 HideInternal(); | 1128 HideInternal(); |
1072 OnStaleLoader(); | 1129 HandleStaleOverlay(); |
1073 } | 1130 } |
1074 | 1131 |
1075 void InstantController::HideInternal() { | 1132 void InstantController::HideInternal() { |
1076 LOG_INSTANT_DEBUG_EVENT(this, "Hide"); | 1133 LOG_INSTANT_DEBUG_EVENT(this, "Hide"); |
1077 | 1134 |
1078 // If GetPreviewContents() returns NULL, either we're already in the desired | 1135 // If GetPreviewContents() returns NULL, either we're already in the desired |
1079 // MODE_DEFAULT state, or we're in the commit path. For the latter, don't | 1136 // MODE_DEFAULT state, or we're in the commit path. For the latter, don't |
1080 // change the state just yet; else we may hide the preview unnecessarily. | 1137 // change the state just yet; else we may hide the preview unnecessarily. |
1081 // Instead, the state will be set correctly after the commit is done. | 1138 // Instead, the state will be set correctly after the commit is done. |
1082 if (GetPreviewContents()) { | 1139 if (GetPreviewContents()) { |
1083 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); | 1140 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); |
1084 allow_preview_to_show_search_suggestions_ = false; | 1141 allow_preview_to_show_search_suggestions_ = false; |
1085 | 1142 |
1086 // Send a message asking the preview to clear out old results. | 1143 // Send a message asking the preview to clear out old results. |
1087 loader_->Update(string16(), 0, 0, true); | 1144 overlay_->Update(string16(), 0, 0, true); |
1088 } | 1145 } |
1089 | 1146 |
1090 // Clear the first interaction timestamp for later use. | 1147 // Clear the first interaction timestamp for later use. |
1091 first_interaction_time_ = base::Time(); | 1148 first_interaction_time_ = base::Time(); |
1092 } | 1149 } |
1093 | 1150 |
1094 void InstantController::ShowLoader(InstantShownReason reason, | 1151 void InstantController::ShowOverlay(InstantShownReason reason, |
1095 int height, | 1152 int height, |
1096 InstantSizeUnits units) { | 1153 InstantSizeUnits units) { |
1097 // If we are on a committed search results page, the |loader_| is not in use. | 1154 // If we are on a committed search results page, the |overlay_| is not in use. |
1098 if (instant_tab_) | 1155 if (instant_tab_) |
1099 return; | 1156 return; |
1100 | 1157 |
1101 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 1158 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
1102 "Show: reason=%d height=%d units=%d", reason, height, units)); | 1159 "Show: reason=%d height=%d units=%d", reason, height, units)); |
1103 | 1160 |
1104 // Must be on NTP to show NTP content. | 1161 // INSTANT_SHOWN_CUSTOM_NTP_CONTENT is no longer supported. |
1105 if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT && !search_mode_.is_ntp()) | 1162 // TODO(samarth): remove once the server has been updated. |
1163 if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT) | |
1106 return; | 1164 return; |
1107 | 1165 |
1108 // Must have updated omnibox after the last HideLoader() to show suggestions. | 1166 // Must have updated omnibox after the last HideOverlay() to show suggestions. |
1109 if ((reason == INSTANT_SHOWN_QUERY_SUGGESTIONS || | 1167 if ((reason == INSTANT_SHOWN_QUERY_SUGGESTIONS || |
1110 reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) && | 1168 reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) && |
1111 !allow_preview_to_show_search_suggestions_) | 1169 !allow_preview_to_show_search_suggestions_) |
1112 return; | 1170 return; |
1113 | 1171 |
1114 // The page is trying to hide itself. Hide explicitly (i.e., don't use | 1172 // The page is trying to hide itself. Hide explicitly (i.e., don't use |
1115 // HideLoader()) so that it can change its mind. | 1173 // HideOverlay()) so that it can change its mind. |
1116 if (height == 0) { | 1174 if (height == 0) { |
1117 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); | 1175 model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); |
1118 return; | 1176 return; |
1119 } | 1177 } |
1120 | 1178 |
1121 // If the preview is being shown for the first time since the user started | 1179 // If the preview is being shown for the first time since the user started |
1122 // typing, record a histogram value. | 1180 // typing, record a histogram value. |
1123 if (!first_interaction_time_.is_null() && model_.mode().is_default()) { | 1181 if (!first_interaction_time_.is_null() && model_.mode().is_default()) { |
1124 base::TimeDelta delta = base::Time::Now() - first_interaction_time_; | 1182 base::TimeDelta delta = base::Time::Now() - first_interaction_time_; |
1125 UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShow", delta); | 1183 UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShow", delta); |
1126 } | 1184 } |
1127 | 1185 |
1128 // Show at 100% height except in the following cases: | 1186 // Show at 100% height except in the following cases: |
1129 // - The local omnibox popup is being loaded. | 1187 // - The local omnibox popup is being loaded. |
1130 // - Instant is disabled. The page needs to be able to show only a dropdown. | 1188 // - Instant is disabled. The page needs to be able to show only a dropdown. |
1131 // - The page wants to show custom NTP content. | 1189 // - The page wants to show custom NTP content. |
1132 // - The page is over a website other than search or an NTP, and is not | 1190 // - The page is over a website other than search or an NTP, and is not |
1133 // already showing at 100% height. | 1191 // already showing at 100% height. |
1134 if (loader_->IsUsingLocalPreview() || !instant_enabled_ || | 1192 if (overlay_->IsUsingLocalPreview() || !instant_enabled_ || |
1135 reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT || | 1193 reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT || |
1136 (search_mode_.is_origin_default() && !IsFullHeight(model_))) | 1194 (search_mode_.is_origin_default() && !IsFullHeight(model_))) |
1137 model_.SetPreviewState(search_mode_, height, units); | 1195 model_.SetPreviewState(search_mode_, height, units); |
1138 else | 1196 else |
1139 model_.SetPreviewState(search_mode_, 100, INSTANT_SIZE_PERCENT); | 1197 model_.SetPreviewState(search_mode_, 100, INSTANT_SIZE_PERCENT); |
1140 | 1198 |
1141 // If the user clicked on a query suggestion, also go ahead and commit the | 1199 // If the user clicked on a query suggestion, also go ahead and commit the |
1142 // overlay. This is necessary because if the overlay was partially visible | 1200 // overlay. This is necessary because if the overlay was partially visible |
1143 // when the suggestion was clicked, the click itself would not commit the | 1201 // when the suggestion was clicked, the click itself would not commit the |
1144 // overlay (because we're not full height). | 1202 // overlay (because we're not full height). |
1145 if (reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) | 1203 if (reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) |
1146 CommitIfPossible(INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION); | 1204 CommitIfPossible(INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION); |
1147 } | 1205 } |
1148 | 1206 |
1149 void InstantController::SendPopupBoundsToPage() { | 1207 void InstantController::SendPopupBoundsToPage() { |
1150 if (last_popup_bounds_ == popup_bounds_ || !loader_ || | 1208 if (last_popup_bounds_ == popup_bounds_ || !overlay_ || |
1151 loader_->is_pointer_down_from_activate()) | 1209 overlay_->is_pointer_down_from_activate()) |
1152 return; | 1210 return; |
1153 | 1211 |
1154 last_popup_bounds_ = popup_bounds_; | 1212 last_popup_bounds_ = popup_bounds_; |
1155 gfx::Rect preview_bounds = browser_->GetInstantBounds(); | 1213 gfx::Rect preview_bounds = browser_->GetInstantBounds(); |
1156 gfx::Rect intersection = gfx::IntersectRects(popup_bounds_, preview_bounds); | 1214 gfx::Rect intersection = gfx::IntersectRects(popup_bounds_, preview_bounds); |
1157 | 1215 |
1158 // Translate into window coordinates. | 1216 // Translate into window coordinates. |
1159 if (!intersection.IsEmpty()) { | 1217 if (!intersection.IsEmpty()) { |
1160 intersection.Offset(-preview_bounds.origin().x(), | 1218 intersection.Offset(-preview_bounds.origin().x(), |
1161 -preview_bounds.origin().y()); | 1219 -preview_bounds.origin().y()); |
1162 } | 1220 } |
1163 | 1221 |
1164 // In the current Chrome UI, these must always be true so they sanity check | 1222 // In the current Chrome UI, these must always be true so they sanity check |
1165 // the above operations. In a future UI, these may be removed or adjusted. | 1223 // the above operations. In a future UI, these may be removed or adjusted. |
1166 // There is no point in sanity-checking |intersection.y()| because the omnibox | 1224 // There is no point in sanity-checking |intersection.y()| because the omnibox |
1167 // can be placed anywhere vertically relative to the preview (for example, in | 1225 // can be placed anywhere vertically relative to the preview (for example, in |
1168 // Mac fullscreen mode, the omnibox is fully enclosed by the preview bounds). | 1226 // Mac fullscreen mode, the omnibox is fully enclosed by the preview bounds). |
1169 DCHECK_LE(0, intersection.x()); | 1227 DCHECK_LE(0, intersection.x()); |
1170 DCHECK_LE(0, intersection.width()); | 1228 DCHECK_LE(0, intersection.width()); |
1171 DCHECK_LE(0, intersection.height()); | 1229 DCHECK_LE(0, intersection.height()); |
1172 | 1230 |
1173 loader_->SetPopupBounds(intersection); | 1231 overlay_->SetPopupBounds(intersection); |
1174 } | 1232 } |
1175 | 1233 |
1176 bool InstantController::GetInstantURL(const content::WebContents* active_tab, | 1234 bool InstantController::GetInstantURL(Profile* profile, |
1177 std::string* instant_url) const { | 1235 std::string* instant_url) const { |
1178 DCHECK(active_tab); | 1236 DCHECK(profile); |
1179 instant_url->clear(); | 1237 instant_url->clear(); |
1180 | 1238 |
1181 if (extended_enabled_ && use_local_preview_only_) { | 1239 if (extended_enabled_ && use_local_preview_only_) { |
1182 *instant_url = kLocalOmniboxPopupURL; | 1240 *instant_url = kLocalOmniboxPopupURL; |
1183 return true; | 1241 return true; |
1184 } | 1242 } |
1185 | 1243 |
1186 const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile( | 1244 const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile( |
1187 Profile::FromBrowserContext(active_tab->GetBrowserContext()))-> | 1245 profile)->GetDefaultSearchProvider(); |
1188 GetDefaultSearchProvider(); | |
1189 | 1246 |
1190 if (!template_url) { | 1247 if (!template_url) { |
1191 LOG_INSTANT_DEBUG_EVENT(this, "GetInstantURL: No template URL"); | 1248 LOG_INSTANT_DEBUG_EVENT(this, "GetInstantURL: No template URL"); |
1192 return false; | 1249 return false; |
1193 } | 1250 } |
1194 | 1251 |
1195 CommandLine* command_line = CommandLine::ForCurrentProcess(); | 1252 CommandLine* command_line = CommandLine::ForCurrentProcess(); |
1196 if (command_line->HasSwitch(switches::kInstantURL)) | 1253 if (command_line->HasSwitch(switches::kInstantURL)) |
1197 *instant_url = command_line->GetSwitchValueASCII(switches::kInstantURL); | 1254 *instant_url = command_line->GetSwitchValueASCII(switches::kInstantURL); |
1198 | 1255 |
(...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
1257 iter->second > kMaxInstantSupportFailures) { | 1314 iter->second > kMaxInstantSupportFailures) { |
1258 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST); | 1315 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_BLOCKED_BY_BLACKLIST); |
1259 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( | 1316 LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( |
1260 "GetInstantURL: Instant URL blacklisted: url=%s", | 1317 "GetInstantURL: Instant URL blacklisted: url=%s", |
1261 instant_url->c_str())); | 1318 instant_url->c_str())); |
1262 return false; | 1319 return false; |
1263 } | 1320 } |
1264 | 1321 |
1265 return true; | 1322 return true; |
1266 } | 1323 } |
1324 | |
1325 void InstantController::BlacklistAndResetNTP() { | |
1326 ++blacklisted_urls_[ntp_->instant_url()]; | |
1327 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST); | |
1328 ignore_result(ntp_->ReleaseContents()); | |
1329 MessageLoop::current()->DeleteSoon(FROM_HERE, ntp_.release()); | |
1330 ResetNTP(); | |
1331 } | |
1332 | |
1333 void InstantController::BlacklistAndResetOverlay() { | |
1334 ++blacklisted_urls_[overlay_->instant_url()]; | |
1335 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST); | |
1336 HideInternal(); | |
1337 ignore_result(overlay_->ReleaseContents()); | |
1338 MessageLoop::current()->DeleteSoon(FROM_HERE, overlay_.release()); | |
1339 EnsureOverlayIsCurrent(); | |
1340 } | |
1341 | |
1342 void InstantController::RemoveFromBlacklist(const std::string& url) { | |
1343 if (blacklisted_urls_.erase(url)) { | |
1344 RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST); | |
1345 } | |
1346 } | |
OLD | NEW |