Chromium Code Reviews| Index: chrome/browser/instant/instant_controller.cc |
| diff --git a/chrome/browser/instant/instant_controller.cc b/chrome/browser/instant/instant_controller.cc |
| index 175fef2ad24763f3f98c3bcb17ca4f063e2f7c9e..2989b95da485063e8f92564c812de1beedcd6c35 100644 |
| --- a/chrome/browser/instant/instant_controller.cc |
| +++ b/chrome/browser/instant/instant_controller.cc |
| @@ -13,7 +13,8 @@ |
| #include "chrome/browser/history/history.h" |
| #include "chrome/browser/history/history_service_factory.h" |
| #include "chrome/browser/history/history_tab_helper.h" |
| -#include "chrome/browser/instant/instant_loader.h" |
| +#include "chrome/browser/instant/instant_ntp.h" |
| +#include "chrome/browser/instant/instant_overlay.h" |
| #include "chrome/browser/instant/instant_tab.h" |
| #include "chrome/browser/platform_util.h" |
| #include "chrome/browser/search_engines/template_url_service.h" |
| @@ -46,7 +47,7 @@ const int kMaxInstantSupportFailures = 10; |
| // If an Instant page has not been used in these many milliseconds, it is |
| // reloaded so that the page does not become stale. |
| -const int kStaleLoaderTimeoutMS = 3 * 3600 * 1000; |
| +const int kStalePageTimeoutMS = 3 * 3600 * 1000; |
| // For reporting events of interest. |
| enum InstantControllerEvent { |
| @@ -159,6 +160,11 @@ bool IsFullHeight(const InstantModel& model) { |
| return model.height() == 100 && model.height_units() == INSTANT_SIZE_PERCENT; |
| } |
| +bool ContentsFrom(const InstantPage* page, |
| + const content::WebContents* contents) { |
| + return page && (page->contents() == contents); |
| +} |
| + |
| } // namespace |
| // static |
| @@ -213,9 +219,9 @@ bool InstantController::Update(const AutocompleteMatch& match, |
| // when keyword search is in effect. |
| if (is_keyword_search) { |
| if (instant_tab_) |
| - instant_tab_->Update(string16(), 0, 0, true); |
| + instant_tab_->api()->Update(string16(), 0, 0, true); |
| else |
| - HideLoader(); |
| + HideOverlay(); |
| last_match_was_search_ = false; |
| return false; |
| } |
| @@ -237,21 +243,21 @@ bool InstantController::Update(const AutocompleteMatch& match, |
| // The preview is being clicked and will commit soon. Don't change anything. |
| // TODO(sreeram): Add a browser test for this. |
| - if (loader_ && loader_->is_pointer_down_from_activate()) |
| + if (overlay_ && overlay_->is_pointer_down_from_activate()) |
| return false; |
| // In non-extended mode, SearchModeChanged() is never called, so fake it. The |
| // mode is set to "disallow suggestions" here, so that if one of the early |
| // "return false" conditions is hit, suggestions will be disallowed. If the |
| - // query is sent to the loader, the mode is set to "allow" further below. |
| + // query is sent to the overlay, the mode is set to "allow" further below. |
| if (!extended_enabled_) |
| search_mode_.mode = chrome::search::Mode::MODE_DEFAULT; |
| last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && |
| !user_text.empty(); |
| - if (!ResetLoaderForMatch(match)) { |
| - HideLoader(); |
| + if (!ResetOverlayForMatch(match)) { |
| + HideOverlay(); |
| return false; |
| } |
| @@ -271,12 +277,12 @@ bool InstantController::Update(const AutocompleteMatch& match, |
| // tab), by comparing the old and new WebContents. |
| if (escape_pressed && |
| instant_tab_->contents() == browser_->GetActiveWebContents()) { |
| - instant_tab_->Submit(full_text); |
| + instant_tab_->api()->Submit(full_text); |
| } |
| } else if (!full_text.empty()) { |
| // If |full_text| is empty, the user is on the NTP. The preview may |
| // be showing custom NTP content; hide only if that's not the case. |
| - HideLoader(); |
| + HideOverlay(); |
| } |
| } else if (full_text.empty()) { |
| // The user is typing, and backspaced away all omnibox text. Clear |
| @@ -285,17 +291,17 @@ bool InstantController::Update(const AutocompleteMatch& match, |
| last_suggestion_ = InstantSuggestion(); |
| if (instant_tab_) { |
| // On a search results page, tell it to clear old results. |
| - instant_tab_->Update(string16(), 0, 0, true); |
| + instant_tab_->api()->Update(string16(), 0, 0, true); |
| } else if (search_mode_.is_origin_ntp()) { |
| // On the NTP, tell the preview to clear old results. Don't hide the |
| // preview so it can show a blank page or logo if it wants. |
| - loader_->Update(string16(), 0, 0, true); |
| + overlay_->api()->Update(string16(), 0, 0, true); |
| } else { |
| - HideLoader(); |
| + HideOverlay(); |
| } |
| } else { |
| // The user switched to a tab with partial text already in the omnibox. |
| - HideLoader(); |
| + HideOverlay(); |
| // The new tab may or may not be a search results page; we don't know |
| // since SearchModeChanged() hasn't been called yet. If it later turns |
| @@ -312,17 +318,17 @@ bool InstantController::Update(const AutocompleteMatch& match, |
| last_omnibox_text_.clear(); |
| last_suggestion_ = InstantSuggestion(); |
| if (instant_tab_) |
| - instant_tab_->Update(string16(), 0, 0, true); |
| + instant_tab_->api()->Update(string16(), 0, 0, true); |
| else if (search_mode_.is_origin_ntp()) |
| - loader_->Update(string16(), 0, 0, true); |
| + overlay_->api()->Update(string16(), 0, 0, true); |
| else |
| - HideLoader(); |
| + HideOverlay(); |
| return false; |
| } |
| } else if (!omnibox_popup_is_open || full_text.empty()) { |
| // In the non-extended case, hide the preview as long as the user isn't |
| // actively typing a non-empty query. |
| - HideLoader(); |
| + HideOverlay(); |
| return false; |
| } |
| @@ -366,13 +372,14 @@ bool InstantController::Update(const AutocompleteMatch& match, |
| search_mode_.mode = chrome::search::Mode::MODE_SEARCH_SUGGESTIONS; |
| if (instant_tab_) { |
| - instant_tab_->Update(user_text, selection_start, selection_end, verbatim); |
| + instant_tab_->api()->Update(user_text, selection_start, |
| + selection_end, verbatim); |
| } else { |
| if (first_interaction_time_.is_null()) |
| first_interaction_time_ = base::Time::Now(); |
| allow_preview_to_show_search_suggestions_ = true; |
| - loader_->Update(extended_enabled_ ? user_text : full_text, |
| - selection_start, selection_end, verbatim); |
| + overlay_->api()->Update(extended_enabled_ ? user_text : full_text, |
| + selection_start, selection_end, verbatim); |
| } |
| content::NotificationService::current()->Notify( |
| @@ -390,6 +397,16 @@ bool InstantController::Update(const AutocompleteMatch& match, |
| return last_match_was_search_; |
| } |
| +content::WebContents* InstantController::ReleaseNTPContents() { |
| + if (!extended_enabled_ || !ntp_) |
| + return NULL; |
| + |
| + content::WebContents* ntp_contents = ntp_->ReleaseContents(); |
| + ntp_.reset(); |
| + ResetNTP(); |
| + return ntp_contents; |
| +} |
| + |
| // TODO(tonyg): This method only fires when the omnibox bounds change. It also |
| // needs to fire when the preview bounds change (e.g.: open/close info bar). |
| void InstantController::SetPopupBounds(const gfx::Rect& bounds) { |
| @@ -416,10 +433,12 @@ void InstantController::SetMarginSize(int start, int end) { |
| start_margin_ = start; |
| end_margin_ = end; |
| - if (loader_) |
| - loader_->SetMarginSize(start_margin_, end_margin_); |
| + if (overlay_) |
| + overlay_->api()->SetMarginSize(start_margin_, end_margin_); |
| + if (ntp_) |
| + ntp_->api()->SetMarginSize(start_margin_, end_margin_); |
| if (instant_tab_) |
| - instant_tab_->SetMarginSize(start_margin_, end_margin_); |
| + instant_tab_->api()->SetMarginSize(start_margin_, end_margin_); |
| } |
| void InstantController::HandleAutocompleteResults( |
| @@ -427,7 +446,7 @@ void InstantController::HandleAutocompleteResults( |
| if (!extended_enabled_) |
| return; |
| - if (!instant_tab_ && !loader_) |
| + if (!instant_tab_ && !overlay_) |
| return; |
| DVLOG(1) << "AutocompleteResults:"; |
| @@ -451,28 +470,28 @@ void InstantController::HandleAutocompleteResults( |
| } |
| if (instant_tab_) |
| - instant_tab_->SendAutocompleteResults(results); |
| + instant_tab_->api()->SendAutocompleteResults(results); |
| else |
| - loader_->SendAutocompleteResults(results); |
| + overlay_->api()->SendAutocompleteResults(results); |
| } |
| bool InstantController::OnUpOrDownKeyPressed(int count) { |
| if (!extended_enabled_) |
| return false; |
| - if (!instant_tab_ && !loader_) |
| + if (!instant_tab_ && !overlay_) |
| return false; |
| if (instant_tab_) |
| - instant_tab_->UpOrDownKeyPressed(count); |
| + instant_tab_->api()->UpOrDownKeyPressed(count); |
| else |
| - loader_->UpOrDownKeyPressed(count); |
| + overlay_->api()->UpOrDownKeyPressed(count); |
| return true; |
| } |
| content::WebContents* InstantController::GetPreviewContents() const { |
| - return loader_ ? loader_->contents() : NULL; |
| + return overlay_ ? overlay_->contents() : NULL; |
| } |
| bool InstantController::IsPreviewingSearchResults() const { |
| @@ -492,7 +511,7 @@ bool InstantController::CommitIfPossible(InstantCommitType type) { |
| // to the page, but otherwise, nothing else to do. |
| if (instant_tab_) { |
| if (last_match_was_search_ && type == INSTANT_COMMIT_PRESSED_ENTER) { |
| - instant_tab_->Submit(last_omnibox_text_); |
| + instant_tab_->api()->Submit(last_omnibox_text_); |
| instant_tab_->contents()->Focus(); |
| return true; |
| } |
| @@ -504,21 +523,21 @@ bool InstantController::CommitIfPossible(InstantCommitType type) { |
| // There may re-entrance here, from the call to browser_->CommitInstant below, |
| // which can cause a TabDeactivated notification which gets back here. |
| - // In this case, loader_->ReleaseContents() was called already. |
| + // In this case, overlay_->ReleaseContents() was called already. |
| if (!GetPreviewContents()) |
| return false; |
| // Never commit the local omnibox. |
| - if (loader_->IsUsingLocalPreview()) |
| + if (overlay_->IsUsingLocalPreview()) |
| return false; |
| if (type == INSTANT_COMMIT_FOCUS_LOST) |
| - loader_->Cancel(last_omnibox_text_); |
| + overlay_->api()->Cancel(last_omnibox_text_); |
| else if (type != INSTANT_COMMIT_NAVIGATED && |
| type != INSTANT_COMMIT_CLICKED_QUERY_SUGGESTION) |
| - loader_->Submit(last_omnibox_text_); |
| + overlay_->api()->Submit(last_omnibox_text_); |
| - content::WebContents* preview = loader_->ReleaseContents(); |
| + content::WebContents* preview = overlay_->ReleaseContents(); |
| if (extended_enabled_) { |
| // Consider what's happening: |
| @@ -556,11 +575,11 @@ bool InstantController::CommitIfPossible(InstantCommitType type) { |
| // the navigation to history ourselves. Else, the page will navigate after |
| // commit, and it will be added to history in the usual manner. |
| const history::HistoryAddPageArgs& last_navigation = |
| - loader_->last_navigation(); |
| + overlay_->last_navigation(); |
| if (!last_navigation.url.is_empty()) { |
| content::NavigationEntry* entry = preview->GetController().GetActiveEntry(); |
| - // The last navigation should be the same as the active entry if the loader |
| + // The last navigation should be the same as the active entry if the overlay |
| // is in search mode. During navigation, the active entry could have |
| // changed since DidCommitProvisionalLoadForFrame is called after the entry |
| // is changed. |
| @@ -606,15 +625,15 @@ bool InstantController::CommitIfPossible(InstantCommitType type) { |
| content::Source<content::WebContents>(preview), |
| content::NotificationService::NoDetails()); |
| - // Hide explicitly. See comments in HideLoader() for why. |
| + // Hide explicitly. See comments in HideOverlay() for why. |
| model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); |
| - // Delay deletion as we could've gotten here from an InstantLoader method. |
| - MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); |
| + // Delay deletion as we could've gotten here from an InstantOverlay method. |
| + MessageLoop::current()->DeleteSoon(FROM_HERE, overlay_.release()); |
| - // Try to create another loader immediately so that it is ready for the next |
| + // Try to create another overlay immediately so that it is ready for the next |
| // user interaction. |
| - CreateDefaultLoader(); |
| + CreateDefaultOverlay(); |
| return true; |
| } |
| @@ -640,14 +659,20 @@ void InstantController::OmniboxFocusChanged( |
| // have no way of telling whether the keycapturechange happened because of |
| // some actual user action or just because they started typing.) |
| if (extended_enabled_ && GetPreviewContents() && |
| - reason != OMNIBOX_FOCUS_CHANGE_TYPING) |
| - loader_->KeyCaptureChanged(omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); |
| + reason != OMNIBOX_FOCUS_CHANGE_TYPING) { |
| + const bool is_key_capture_enabled = |
| + omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE; |
| + if (overlay_) |
| + overlay_->api()->KeyCaptureChanged(is_key_capture_enabled); |
| + if (instant_tab_) |
| + instant_tab_->api()->KeyCaptureChanged(is_key_capture_enabled); |
| + } |
| // If focus went from outside the omnibox to the omnibox, preload the default |
| // search engine, in anticipation of the user typing a query. If the reverse |
| // happened, commit or discard the preview. |
| if (state != OMNIBOX_FOCUS_NONE && old_focus_state == OMNIBOX_FOCUS_NONE) |
| - CreateDefaultLoader(); |
| + CreateDefaultOverlay(); |
| else if (state == OMNIBOX_FOCUS_NONE && old_focus_state != OMNIBOX_FOCUS_NONE) |
| OmniboxLostFocus(view_gaining_focus); |
| } |
| @@ -664,10 +689,10 @@ void InstantController::SearchModeChanged( |
| search_mode_ = new_mode; |
| if (!new_mode.is_search_suggestions()) |
| - HideLoader(); |
| + HideOverlay(); |
| - if (loader_) |
| - loader_->SearchModeChanged(new_mode); |
| + if (overlay_) |
| + overlay_->api()->SearchModeChanged(new_mode); |
| ResetInstantTab(); |
| } |
| @@ -678,10 +703,8 @@ void InstantController::ActiveTabChanged() { |
| DVLOG(1) << "ActiveTabChanged"; |
| - // When switching tabs, always hide the preview, except if it's showing NTP |
| - // content, and the new tab is also an NTP. |
| - if (!search_mode_.is_ntp() || !model_.mode().is_ntp()) |
| - HideLoader(); |
| + // When switching tabs, always hide the preview. |
| + HideOverlay(); |
| if (extended_enabled_) |
| ResetInstantTab(); |
| @@ -697,27 +720,147 @@ void InstantController::SetInstantEnabled(bool instant_enabled) { |
| DVLOG(1) << "SetInstantEnabled: " << instant_enabled; |
| instant_enabled_ = instant_enabled; |
| HideInternal(); |
| - loader_.reset(); |
| + overlay_.reset(); |
| if (extended_enabled_ || instant_enabled_) |
| - CreateDefaultLoader(); |
| + CreateDefaultOverlay(); |
| + if (extended_enabled_) |
| + ResetNTP(); |
| if (instant_tab_) |
| - instant_tab_->SetDisplayInstantResults(instant_enabled_); |
| + instant_tab_->api()->SetDisplayInstantResults(instant_enabled_); |
| } |
| void InstantController::ThemeChanged(const ThemeBackgroundInfo& theme_info) { |
| if (!extended_enabled_) |
| return; |
| - if (loader_) |
| - loader_->SendThemeBackgroundInfo(theme_info); |
| + if (overlay_) |
| + overlay_->api()->SendThemeBackgroundInfo(theme_info); |
| + if (ntp_) |
| + ntp_->api()->SendThemeBackgroundInfo(theme_info); |
| } |
| void InstantController::ThemeAreaHeightChanged(int height) { |
| if (!extended_enabled_) |
| return; |
| - if (loader_) |
| - loader_->SendThemeAreaHeight(height); |
| + if (overlay_) |
| + overlay_->api()->SendThemeAreaHeight(height); |
| + if (ntp_) |
| + ntp_->api()->SendThemeAreaHeight(height); |
| +} |
| + |
| +void InstantController::SwappedOverlayWebContents() { |
| + model_.SetPreviewContents(GetPreviewContents()); |
| +} |
| + |
| +void InstantController::InstantOverlayContentsFocused() { |
| +#if defined(USE_AURA) |
| + // On aura the omnibox only receives a focus lost if we initiate the focus |
| + // change. This does that. |
| + if (!model_.mode().is_default()) |
| + browser_->InstantPreviewFocused(); |
| +#endif |
| +} |
| + |
| +void InstantController::OnStaleNTP() { |
| + if (ntp_->is_stale()) { |
| + ntp_.reset(); |
| + ResetNTP(); |
| + } |
| +} |
| + |
| +void InstantController::OnStaleOverlay() { |
| + // The local popup is never stale. |
| + if (overlay_ && overlay_->IsUsingLocalPreview()) |
| + return; |
| + |
| + // If the preview is showing or the omnibox has focus, don't delete the |
| + // overlay. It will get refreshed the next time the preview is hidden or the |
| + // omnibox loses focus. |
| + if ((!overlay_ || overlay_->is_stale()) && |
| + omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && |
| + model_.mode().is_default()) { |
| + overlay_.reset(); |
| + CreateDefaultOverlay(); |
| + } |
| +} |
| + |
| +void InstantController::InstantSupportDetermined( |
| + const content::WebContents* contents, |
| + bool supports_instant) { |
| + if (ContentsFrom(instant_tab_.get(), contents)) { |
| + if (!supports_instant) |
| + MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release()); |
| + } else if (ContentsFrom(ntp_.get(), contents)) { |
|
Jered
2013/01/14 18:22:34
The body of this else if block and the following e
samarth
2013/01/22 15:59:06
They're different enough that I don't think it wou
|
| + if (supports_instant) { |
| + RemoveFromBlacklist(ntp_->instant_url()); |
| + } else { |
| + AddToBlacklist(ntp_->instant_url()); |
| + delete ntp_->ReleaseContents(); |
| + ntp_.reset(); |
| + ResetNTP(); |
| + } |
| + } else if (ContentsFrom(overlay_.get(), contents)) { |
| + if (supports_instant) { |
| + RemoveFromBlacklist(overlay_->instant_url()); |
| + } else { |
| + AddToBlacklist(overlay_->instant_url()); |
| + HideInternal(); |
| + delete overlay_->ReleaseContents(); |
| + overlay_.reset(); |
| + CreateDefaultOverlay(); |
| + } |
| + content::NotificationService::current()->Notify( |
| + chrome::NOTIFICATION_INSTANT_SUPPORT_DETERMINED, |
| + content::Source<InstantController>(this), |
| + content::NotificationService::NoDetails()); |
| + } |
| +} |
| + |
| +void InstantController::InstantPageRenderViewGone( |
| + const content::WebContents* contents) { |
| + if (ContentsFrom(overlay_.get(), contents)) { |
| + AddToBlacklist(overlay_->instant_url()); |
| + HideInternal(); |
| + delete overlay_->ReleaseContents(); |
| + overlay_.reset(); |
| + CreateDefaultOverlay(); |
| + } else if (ContentsFrom(ntp_.get(), contents)) { |
| + AddToBlacklist(ntp_->instant_url()); |
| + delete ntp_->ReleaseContents(); |
| + ntp_.reset(); |
| + ResetNTP(); |
| + } |
| +} |
| + |
| +void InstantController::InstantPageAboutToNavigateMainFrame( |
| + const content::WebContents* contents, |
| + const GURL& url) { |
| + if (!ContentsFrom(overlay_.get(), contents)) |
| + return; |
| + |
| + // If the page does not yet support instant, we allow redirects and other |
| + // navigations to go through since the instant URL can redirect - e.g. to |
| + // country specific pages. |
| + if (!overlay_->supports_instant()) |
| + return; |
| + |
| + GURL instant_url(overlay_->instant_url()); |
| + |
| + // If we are navigating to the instant URL, do nothing. |
| + if (url == instant_url) |
| + return; |
| + |
| + // Commit the navigation if either: |
| + // - The page is in NTP mode (so it could only navigate on a user click) or |
| + // - The page is not in NTP mode and we are navigating to a URL with a |
| + // different host or path than the instant URL. This enables the instant |
| + // page when it is showing search results to change the query parameters |
| + // and fragments of the URL without it navigating. |
| + if (model_.mode().is_ntp() || |
| + (url.host() != instant_url.host() || url.path() != instant_url.path())) { |
| + CommitIfPossible(INSTANT_COMMIT_NAVIGATED); |
| + } |
| } |
| void InstantController::SetSuggestions( |
| @@ -726,13 +869,11 @@ void InstantController::SetSuggestions( |
| DVLOG(1) << "SetSuggestions"; |
| // Ignore if the message is from an unexpected source. |
| - if (instant_tab_) { |
| - if (instant_tab_->contents() != contents) |
| - return; |
| - } else if (!loader_ || loader_->contents() != contents || |
| - !allow_preview_to_show_search_suggestions_) { |
| + if (instant_tab_ && !ContentsFrom(instant_tab_.get(), contents)) |
| + return; |
| + if (ContentsFrom(overlay_.get(), contents) && |
| + !allow_preview_to_show_search_suggestions_) |
| return; |
| - } |
| InstantSuggestion suggestion; |
| if (!suggestions.empty()) |
| @@ -809,107 +950,56 @@ void InstantController::SetSuggestions( |
| } |
| } |
| - // Extended mode pages will call ShowLoader() when they are ready. |
| + // Extended mode pages will call ShowOverlay() when they are ready. |
| if (!extended_enabled_) |
| - ShowLoader(INSTANT_SHOWN_QUERY_SUGGESTIONS, 100, INSTANT_SIZE_PERCENT); |
| -} |
| - |
| -void InstantController::InstantSupportDetermined( |
| - const content::WebContents* contents, |
| - bool supports_instant) { |
| - if (instant_tab_ && instant_tab_->contents() == contents) { |
| - if (!supports_instant) |
| - MessageLoop::current()->DeleteSoon(FROM_HERE, instant_tab_.release()); |
| - return; |
| - } |
| - |
| - if (loader_ && loader_->contents() == contents) { |
| - if (supports_instant) { |
| - if (blacklisted_urls_.erase(loader_->instant_url())) { |
| - RecordEventHistogram( |
| - INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST); |
| - } |
| - } else { |
| - ++blacklisted_urls_[loader_->instant_url()]; |
| - RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST); |
| - HideInternal(); |
| - delete loader_->ReleaseContents(); |
| - MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); |
| - CreateDefaultLoader(); |
| - } |
| - content::NotificationService::current()->Notify( |
| - chrome::NOTIFICATION_INSTANT_SUPPORT_DETERMINED, |
| - content::Source<InstantController>(this), |
| - content::NotificationService::NoDetails()); |
| - } |
| + ShowOverlay(INSTANT_SHOWN_QUERY_SUGGESTIONS, 100, INSTANT_SIZE_PERCENT); |
| } |
| -void InstantController::ShowInstantPreview(InstantShownReason reason, |
| +void InstantController::ShowInstantPreview(const content::WebContents* contents, |
| + InstantShownReason reason, |
| int height, |
| InstantSizeUnits units) { |
| - if (extended_enabled_) |
| - ShowLoader(reason, height, units); |
| -} |
| - |
| -void InstantController::StartCapturingKeyStrokes() { |
| - // Ignore unless the loader is active and on the NTP. |
| - if (extended_enabled_ && !instant_tab_ && model_.mode().is_ntp()) |
| - browser_->FocusOmniboxInvisibly(); |
| -} |
| - |
| -void InstantController::StopCapturingKeyStrokes() { |
| - // Ignore unless the loader is active and on the NTP, and the omnibox has |
| - // invisible focus. |
| - if (extended_enabled_ && !instant_tab_ && model_.mode().is_ntp() && |
| - omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE) |
| - loader_->contents()->Focus(); |
| + if (extended_enabled_ && ContentsFrom(overlay_.get(), contents)) |
| + ShowOverlay(reason, height, units); |
| } |
| -void InstantController::SwappedWebContents() { |
| - model_.SetPreviewContents(GetPreviewContents()); |
| -} |
| - |
| -void InstantController::InstantLoaderContentsFocused() { |
| -#if defined(USE_AURA) |
| - // On aura the omnibox only receives a focus lost if we initiate the focus |
| - // change. This does that. |
| - if (!model_.mode().is_default()) |
| - browser_->InstantPreviewFocused(); |
| -#endif |
| -} |
| +void InstantController::StartCapturingKeyStrokes( |
| + const content::WebContents* contents) { |
| + if (!extended_enabled_) |
| + return; |
| -void InstantController::InstantLoaderRenderViewGone() { |
| - ++blacklisted_urls_[loader_->instant_url()]; |
| - HideInternal(); |
| - delete loader_->ReleaseContents(); |
| - // Delay deletion as we have gotten here from an InstantLoader method. |
| - MessageLoop::current()->DeleteSoon(FROM_HERE, loader_.release()); |
| - CreateDefaultLoader(); |
| + // Only honor the call if it comes from an active InstantTab or from an |
| + // InstantOverlay that is being shown. |
| + if (ContentsFrom(instant_tab_.get(), contents) || |
| + (ContentsFrom(overlay_.get(), contents) && !model_.mode().is_default())) { |
| + browser_->FocusOmniboxInvisibly(); |
| + } |
| } |
| -void InstantController::InstantLoaderAboutToNavigateMainFrame(const GURL& url) { |
| - // If the page does not yet support instant, we allow redirects and other |
| - // navigations to go through since the instant URL can redirect - e.g. to |
| - // country specific pages. |
| - if (!loader_->supports_instant()) |
| +void InstantController::StopCapturingKeyStrokes( |
| + content::WebContents* contents) { |
| + // Nothing to do if omnibox doesn't have invisible focus. |
| + if (!extended_enabled_ || omnibox_focus_state_ != OMNIBOX_FOCUS_INVISIBLE) |
| return; |
| - GURL instant_url(loader_->instant_url()); |
| + // Only honor the call if it comes from an active InstantTab or from an |
| + // InstantOverlay that is being shown. |
| + if (ContentsFrom(instant_tab_.get(), contents) || |
| + (ContentsFrom(overlay_.get(), contents) && !model_.mode().is_default())) { |
| + contents->Focus(); |
| + } |
| +} |
| - // If we are navigating to the instant URL, do nothing. |
| - if (url == instant_url) |
| +void InstantController::NavigateToURL(const content::WebContents* contents, |
| + const GURL& url, |
| + content::PageTransition transition) { |
| + // TODO(samarth): handle case where contents are no longer "active" (e.g. user |
| + // has switched tabs). |
| + if (!extended_enabled_) |
| return; |
| - |
| - // Commit the navigation if either: |
| - // - The page is in NTP mode (so it could only navigate on a user click) or |
| - // - The page is not in NTP mode and we are navigating to a URL with a |
| - // different host or path than the instant URL. This enables the instant |
| - // page when it is showing search results to change the query parameters |
| - // and fragments of the URL without it navigating. |
| - if (model_.mode().is_ntp() || |
| - (url.host() != instant_url.host() || url.path() != instant_url.path())) { |
| - CommitIfPossible(INSTANT_COMMIT_NAVIGATED); |
| - } |
| + if (overlay_) |
| + HideOverlay(); |
| + browser_->OpenURLInCurrentTab(url, transition); |
| } |
| void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) { |
| @@ -920,7 +1010,7 @@ void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) { |
| // If the preview is not showing at all, recreate it if it's stale. |
| if (model_.mode().is_default()) { |
| - OnStaleLoader(); |
| + OnStaleOverlay(); |
| return; |
| } |
| @@ -931,29 +1021,39 @@ void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) { |
| #if defined(OS_MACOSX) |
| // TODO(sreeram): See if Mac really needs this special treatment. |
| - if (!loader_->is_pointer_down_from_activate()) |
| - HideLoader(); |
| + if (!overlay_->is_pointer_down_from_activate()) |
| + HideOverlay(); |
| #else |
| if (IsViewInContents(GetViewGainingFocus(view_gaining_focus), |
| - loader_->contents())) |
| + overlay_->contents())) |
| CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); |
| else |
| - HideLoader(); |
| + HideOverlay(); |
| #endif |
| } |
| -void InstantController::NavigateToURL(const GURL& url, |
| - content::PageTransition transition) { |
| - if (!extended_enabled_) |
| - return; |
| - if (loader_) |
| - HideLoader(); |
| - browser_->OpenURLInCurrentTab(url, transition); |
| +bool InstantController::ResetNTP() { |
| + const TemplateURL* template_url = TemplateURLServiceFactory::GetForProfile( |
| + browser_->profile())->GetDefaultSearchProvider(); |
| + std::string instant_url; |
| + if (!GetInstantURL(template_url, &instant_url)) |
| + return false; |
| + |
| + ntp_.reset(new InstantNTP(this, instant_url)); |
| + ntp_->InitContents(browser_->profile(), browser_->GetActiveWebContents()); |
| + |
| + // Ensure the searchbox API has the correct initial state. |
| + if (extended_enabled_) { |
| + browser_->UpdateThemeInfoForPreview(); |
| + ntp_->api()->SetDisplayInstantResults(instant_enabled_); |
| + ntp_->api()->SetMarginSize(start_margin_, end_margin_); |
| + } |
| + return true; |
| } |
| -bool InstantController::ResetLoader(const TemplateURL* template_url, |
| - const content::WebContents* active_tab, |
| - bool fallback_to_local) { |
| +bool InstantController::ResetOverlay(const TemplateURL* template_url, |
| + const content::WebContents* active_tab, |
| + bool fallback_to_local) { |
| std::string instant_url; |
| if (!GetInstantURL(template_url, &instant_url)) { |
| if (!fallback_to_local || !extended_enabled_) |
| @@ -963,32 +1063,28 @@ bool InstantController::ResetLoader(const TemplateURL* template_url, |
| instant_url = kLocalOmniboxPopupURL; |
| } |
| - if (loader_ && loader_->instant_url() == instant_url) |
| + if (overlay_ && overlay_->instant_url() == instant_url) |
| return true; |
| HideInternal(); |
| - loader_.reset(new InstantLoader(this, instant_url)); |
| - loader_->InitContents(active_tab); |
| + overlay_.reset(new InstantOverlay(this, instant_url)); |
| + overlay_->InitContents(browser_->profile(), active_tab); |
| // Ensure the searchbox API has the correct initial state. |
| if (extended_enabled_) { |
| browser_->UpdateThemeInfoForPreview(); |
| - loader_->SetDisplayInstantResults(instant_enabled_); |
| - loader_->SearchModeChanged(search_mode_); |
| - loader_->KeyCaptureChanged(omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); |
| - loader_->SetMarginSize(start_margin_, end_margin_); |
| + overlay_->api()->SetDisplayInstantResults(instant_enabled_); |
| + overlay_->api()->SearchModeChanged(search_mode_); |
| + overlay_->api()->KeyCaptureChanged( |
| + omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); |
| + overlay_->api()->SetMarginSize(start_margin_, end_margin_); |
| } |
| - // Restart the stale loader timer. |
| - stale_loader_timer_.Start(FROM_HERE, |
| - base::TimeDelta::FromMilliseconds(kStaleLoaderTimeoutMS), this, |
| - &InstantController::OnStaleLoader); |
| - |
| return true; |
| } |
| -bool InstantController::CreateDefaultLoader() { |
| - // If there's no active tab, the browser is closing. |
| +bool InstantController::CreateDefaultOverlay() { |
| + // If there's no active tab, the browser is opening or closing. |
| const content::WebContents* active_tab = browser_->GetActiveWebContents(); |
| if (!active_tab) |
| return false; |
| @@ -997,46 +1093,11 @@ bool InstantController::CreateDefaultLoader() { |
| Profile::FromBrowserContext(active_tab->GetBrowserContext()))-> |
| GetDefaultSearchProvider(); |
| - return ResetLoader(template_url, active_tab, true); |
| -} |
| - |
| -void InstantController::OnStaleLoader() { |
| - // The local popup is never stale. |
| - if (loader_ && loader_->IsUsingLocalPreview()) |
| - return; |
| - |
| - // If the preview is showing or the omnibox has focus, don't delete the |
| - // loader. It will get refreshed the next time the preview is hidden or the |
| - // omnibox loses focus. |
| - if (!stale_loader_timer_.IsRunning() && |
| - omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && |
| - model_.mode().is_default()) { |
| - loader_.reset(); |
| - CreateDefaultLoader(); |
| - } |
| + return ResetOverlay(template_url, active_tab, true); |
| } |
| -void InstantController::ResetInstantTab() { |
| - // Do not wire up the InstantTab if instant should only use local previews, to |
| - // prevent it from sending data to the page. |
| - if (search_mode_.is_origin_search() && !use_local_preview_only_) { |
| - content::WebContents* active_tab = browser_->GetActiveWebContents(); |
| - if (!instant_tab_ || active_tab != instant_tab_->contents()) { |
| - instant_tab_.reset(new InstantTab(this, active_tab)); |
| - instant_tab_->Init(); |
| - instant_tab_->SetDisplayInstantResults(instant_enabled_); |
| - instant_tab_->SetMarginSize(start_margin_, end_margin_); |
| - } |
| - |
| - // Hide the |loader_| since we are now using |instant_tab_| instead. |
| - HideLoader(); |
| - } else { |
| - instant_tab_.reset(); |
| - } |
| -} |
| - |
| -bool InstantController::ResetLoaderForMatch(const AutocompleteMatch& match) { |
| - // If we are on a search results page, we'll use that instead of a loader. |
| +bool InstantController::ResetOverlayForMatch(const AutocompleteMatch& match) { |
| + // If we are on a search results page, we'll use that instead of a overlay. |
| // TODO(sreeram): If |instant_tab_|'s URL is not the same as the instant_url |
| // of |match|, we shouldn't use the committed tab. |
| if (instant_tab_) |
| @@ -1047,16 +1108,16 @@ bool InstantController::ResetLoaderForMatch(const AutocompleteMatch& match) { |
| if (!active_tab) |
| return false; |
| - // Try to create a loader for the instant_url in the TemplateURL of |match|. |
| + // Try to create a overlay for the instant_url in the TemplateURL of |match|. |
| // Do not fallback to the local preview because if the keyword specific |
| // instant URL fails, we want to first try the default instant URL which |
| - // happens in the CreateDefaultLoader call below. |
| + // happens in the CreateDefaultOverlay call below. |
| const TemplateURL* template_url = match.GetTemplateURL( |
| Profile::FromBrowserContext(active_tab->GetBrowserContext()), false); |
| - if (ResetLoader(template_url, active_tab, false)) |
| + if (ResetOverlay(template_url, active_tab, false)) |
| return true; |
| - // In non-extended mode, stop if we couldn't get a loader for the |match|. |
| + // In non-extended mode, stop if we couldn't get a overlay for the |match|. |
| if (!extended_enabled_) |
| return false; |
| @@ -1065,12 +1126,33 @@ bool InstantController::ResetLoaderForMatch(const AutocompleteMatch& match) { |
| return false; |
| // The match is a URL, or a blank query. Try the default search engine. |
| - return CreateDefaultLoader(); |
| + return CreateDefaultOverlay(); |
| } |
| -void InstantController::HideLoader() { |
| +void InstantController::ResetInstantTab() { |
| + // Do not wire up the InstantTab if instant should only use local previews, to |
| + // prevent it from sending data to the page. |
| + if (!search_mode_.is_origin_default() && !use_local_preview_only_) { |
| + content::WebContents* active_tab = browser_->GetActiveWebContents(); |
| + if (!instant_tab_ || active_tab != instant_tab_->contents()) { |
| + instant_tab_.reset(new InstantTab(this, active_tab)); |
| + instant_tab_->Init(); |
| + instant_tab_->api()->SetDisplayInstantResults(instant_enabled_); |
| + instant_tab_->api()->SetMarginSize(start_margin_, end_margin_); |
| + instant_tab_->api()->KeyCaptureChanged( |
| + omnibox_focus_state_ == OMNIBOX_FOCUS_INVISIBLE); |
| + } |
| + |
| + // Hide the |overlay_| since we are now using |instant_tab_| instead. |
| + HideOverlay(); |
| + } else { |
| + instant_tab_.reset(); |
| + } |
| +} |
| + |
| +void InstantController::HideOverlay() { |
| HideInternal(); |
| - OnStaleLoader(); |
| + OnStaleOverlay(); |
| } |
| void InstantController::HideInternal() { |
| @@ -1085,35 +1167,36 @@ void InstantController::HideInternal() { |
| allow_preview_to_show_search_suggestions_ = false; |
| // Send a message asking the preview to clear out old results. |
| - loader_->Update(string16(), 0, 0, true); |
| + overlay_->api()->Update(string16(), 0, 0, true); |
| } |
| // Clear the first interaction timestamp for later use. |
| first_interaction_time_ = base::Time(); |
| } |
| -void InstantController::ShowLoader(InstantShownReason reason, |
| - int height, |
| - InstantSizeUnits units) { |
| - // If we are on a committed search results page, the |loader_| is not in use. |
| +void InstantController::ShowOverlay(InstantShownReason reason, |
| + int height, |
| + InstantSizeUnits units) { |
| + // If we are on a committed search results page, the |overlay_| is not in use. |
| if (instant_tab_) |
| return; |
| DVLOG(1) << "Show: reason=" << reason << " height=" << height << " units=" |
| << units; |
| - // Must be on NTP to show NTP content. |
| - if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT && !search_mode_.is_ntp()) |
| + // INSTANT_SHOWN_CUSTOM_NTP_CONTENT is no longer supported. |
| + // TODO(samarth): remove once the server has been updated. |
| + if (reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT) |
| return; |
| - // Must have updated omnibox after the last HideLoader() to show suggestions. |
| + // Must have updated omnibox after the last HideOverlay() to show suggestions. |
| if ((reason == INSTANT_SHOWN_QUERY_SUGGESTIONS || |
| reason == INSTANT_SHOWN_CLICKED_QUERY_SUGGESTION) && |
| !allow_preview_to_show_search_suggestions_) |
| return; |
| // The page is trying to hide itself. Hide explicitly (i.e., don't use |
| - // HideLoader()) so that it can change its mind. |
| + // HideOverlay()) so that it can change its mind. |
| if (height == 0) { |
| model_.SetPreviewState(chrome::search::Mode(), 0, INSTANT_SIZE_PERCENT); |
| return; |
| @@ -1132,7 +1215,7 @@ void InstantController::ShowLoader(InstantShownReason reason, |
| // - The page wants to show custom NTP content. |
| // - The page is over a website other than search or an NTP, and is not |
| // already showing at 100% height. |
| - if (loader_->IsUsingLocalPreview() || !instant_enabled_ || |
| + if (overlay_->IsUsingLocalPreview() || !instant_enabled_ || |
| reason == INSTANT_SHOWN_CUSTOM_NTP_CONTENT || |
| (search_mode_.is_origin_default() && !IsFullHeight(model_))) |
| model_.SetPreviewState(search_mode_, height, units); |
| @@ -1148,8 +1231,8 @@ void InstantController::ShowLoader(InstantShownReason reason, |
| } |
| void InstantController::SendPopupBoundsToPage() { |
| - if (last_popup_bounds_ == popup_bounds_ || !loader_ || |
| - loader_->is_pointer_down_from_activate()) |
| + if (last_popup_bounds_ == popup_bounds_ || !overlay_ || |
| + overlay_->is_pointer_down_from_activate()) |
| return; |
| last_popup_bounds_ = popup_bounds_; |
| @@ -1171,7 +1254,7 @@ void InstantController::SendPopupBoundsToPage() { |
| DCHECK_LE(0, intersection.width()); |
| DCHECK_LE(0, intersection.height()); |
| - loader_->SetPopupBounds(intersection); |
| + overlay_->api()->SetPopupBounds(intersection); |
| } |
| bool InstantController::GetInstantURL(const TemplateURL* template_url, |
| @@ -1232,3 +1315,14 @@ bool InstantController::GetInstantURL(const TemplateURL* template_url, |
| return true; |
| } |
| + |
| +void InstantController::AddToBlacklist(const std::string& url) { |
| + ++blacklisted_urls_[url]; |
| + RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_ADDED_TO_BLACKLIST); |
| +} |
| + |
| +void InstantController::RemoveFromBlacklist(const std::string& url) { |
| + if (blacklisted_urls_.erase(url)) { |
| + RecordEventHistogram(INSTANT_CONTROLLER_EVENT_URL_REMOVED_FROM_BLACKLIST); |
| + } |
| +} |