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