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