diff options
Diffstat (limited to 'chrome/browser/ui/search/instant_controller.cc')
-rw-r--r-- | chrome/browser/ui/search/instant_controller.cc | 1297 |
1 files changed, 25 insertions, 1272 deletions
diff --git a/chrome/browser/ui/search/instant_controller.cc b/chrome/browser/ui/search/instant_controller.cc index f80fbf9..a3f465b 100644 --- a/chrome/browser/ui/search/instant_controller.cc +++ b/chrome/browser/ui/search/instant_controller.cc @@ -4,22 +4,13 @@ #include "chrome/browser/ui/search/instant_controller.h" -#include <iterator> - #include "base/metrics/histogram.h" #include "base/prefs/pref_service.h" -#include "base/strings/string_util.h" #include "base/strings/stringprintf.h" -#include "base/strings/utf_string_conversions.h" -#include "chrome/browser/autocomplete/autocomplete_provider.h" -#include "chrome/browser/autocomplete/autocomplete_result.h" -#include "chrome/browser/autocomplete/search_provider.h" #include "chrome/browser/content_settings/content_settings_provider.h" #include "chrome/browser/content_settings/host_content_settings_map.h" -#include "chrome/browser/history/history_service.h" -#include "chrome/browser/history/history_service_factory.h" -#include "chrome/browser/history/history_tab_helper.h" #include "chrome/browser/platform_util.h" +#include "chrome/browser/profiles/profile.h" #include "chrome/browser/search/instant_service.h" #include "chrome/browser/search/instant_service_factory.h" #include "chrome/browser/search/search.h" @@ -28,7 +19,6 @@ #include "chrome/browser/search_engines/template_url_service_factory.h" #include "chrome/browser/ui/browser_instant_controller.h" #include "chrome/browser/ui/search/instant_ntp.h" -#include "chrome/browser/ui/search/instant_overlay.h" #include "chrome/browser/ui/search/instant_tab.h" #include "chrome/browser/ui/search/search_tab_helper.h" #include "chrome/common/chrome_notification_types.h" @@ -46,7 +36,6 @@ #include "content/public/browser/web_contents_view.h" #include "net/base/escape.h" #include "net/base/network_change_notifier.h" -#include "third_party/icu/public/common/unicode/normalizer2.h" #if defined(TOOLKIT_VIEWS) #include "ui/views/widget/widget.h" @@ -54,11 +43,6 @@ namespace { -// An artificial delay (in milliseconds) we introduce before telling the Instant -// page about the new omnibox bounds, in cases where the bounds shrink. This is -// to avoid the page jumping up/down very fast in response to bounds changes. -const int kUpdateBoundsDelayMS = 1000; - // For reporting Instant navigations. enum InstantNavigation { INSTANT_NAVIGATION_LOCAL_CLICK = 0, @@ -85,128 +69,6 @@ void RecordNavigationHistogram(bool is_local, bool is_click, bool is_extended) { INSTANT_NAVIGATION_MAX); } -void RecordFallbackReasonHistogram( - const InstantController::InstantFallbackReason fallback_reason) { - UMA_HISTOGRAM_ENUMERATION("InstantExtended.FallbackToLocalOverlay", - fallback_reason, - InstantController::INSTANT_FALLBACK_MAX); -} - -InstantController::InstantFallbackReason DetermineFallbackReason( - const InstantPage* page, std::string instant_url) { - InstantController::InstantFallbackReason fallback_reason; - if (!page) { - fallback_reason = InstantController::INSTANT_FALLBACK_NO_OVERLAY; - } else if (instant_url.empty()) { - fallback_reason = InstantController::INSTANT_FALLBACK_INSTANT_URL_EMPTY; - } else if (!chrome::MatchesOriginAndPath(GURL(page->instant_url()), - GURL(instant_url))) { - fallback_reason = InstantController::INSTANT_FALLBACK_ORIGIN_PATH_MISMATCH; - } else if (!page->supports_instant()) { - fallback_reason = InstantController::INSTANT_FALLBACK_INSTANT_NOT_SUPPORTED; - } else { - fallback_reason = InstantController::INSTANT_FALLBACK_UNKNOWN; - } - return fallback_reason; -} - -void AddSessionStorageHistogram(bool extended_enabled, - const content::WebContents* tab1, - const content::WebContents* tab2) { - base::HistogramBase* histogram = base::BooleanHistogram::FactoryGet( - std::string("Instant.SessionStorageNamespace") + - (extended_enabled ? "_Extended" : "_Instant"), - base::HistogramBase::kUmaTargetedHistogramFlag); - const content::SessionStorageNamespaceMap& session_storage_map1 = - tab1->GetController().GetSessionStorageNamespaceMap(); - const content::SessionStorageNamespaceMap& session_storage_map2 = - tab2->GetController().GetSessionStorageNamespaceMap(); - bool is_session_storage_the_same = - session_storage_map1.size() == session_storage_map2.size(); - if (is_session_storage_the_same) { - // The size is the same, so let's check that all entries match. - for (content::SessionStorageNamespaceMap::const_iterator - it1 = session_storage_map1.begin(), - it2 = session_storage_map2.begin(); - it1 != session_storage_map1.end() && it2 != session_storage_map2.end(); - ++it1, ++it2) { - if (it1->first != it2->first || it1->second.get() != it2->second.get()) { - is_session_storage_the_same = false; - break; - } - } - } - histogram->AddBoolean(is_session_storage_the_same); -} - -string16 Normalize(const string16& str) { - UErrorCode status = U_ZERO_ERROR; - const icu::Normalizer2* normalizer = - icu::Normalizer2::getInstance(NULL, "nfkc_cf", UNORM2_COMPOSE, status); - if (normalizer == NULL || U_FAILURE(status)) - return str; - icu::UnicodeString norm_str(normalizer->normalize( - icu::UnicodeString(FALSE, str.c_str(), str.size()), status)); - if (U_FAILURE(status)) - return str; - return string16(norm_str.getBuffer(), norm_str.length()); -} - -bool NormalizeAndStripPrefix(string16* text, const string16& prefix) { - string16 norm_prefix = Normalize(prefix); - string16 norm_text = Normalize(*text); - if (norm_prefix.size() <= norm_text.size() && - norm_text.compare(0, norm_prefix.size(), norm_prefix) == 0) { - *text = norm_text.erase(0, norm_prefix.size()); - return true; - } - return false; -} - -// For TOOLKIT_VIEWS, the top level widget is always focused. If the focus -// change originated in views determine the child Widget from the view that is -// being focused. -gfx::NativeView GetViewGainingFocus(gfx::NativeView view_gaining_focus) { -#if defined(TOOLKIT_VIEWS) - views::Widget* widget = view_gaining_focus ? - views::Widget::GetWidgetForNativeView(view_gaining_focus) : NULL; - if (widget) { - views::FocusManager* focus_manager = widget->GetFocusManager(); - if (focus_manager && focus_manager->is_changing_focus() && - focus_manager->GetFocusedView() && - focus_manager->GetFocusedView()->GetWidget()) - return focus_manager->GetFocusedView()->GetWidget()->GetNativeView(); - } -#endif - return view_gaining_focus; -} - -// Returns true if |view| is the top-level contents view or a child view in the -// view hierarchy of |contents|. -bool IsViewInContents(gfx::NativeView view, content::WebContents* contents) { - content::RenderWidgetHostView* rwhv = contents->GetRenderWidgetHostView(); - if (!view || !rwhv) - return false; - - gfx::NativeView tab_view = contents->GetView()->GetNativeView(); - if (view == rwhv->GetNativeView() || view == tab_view) - return true; - - // Walk up the view hierarchy to determine if the view is a subview of the - // WebContents view (such as a windowed plugin or http auth dialog). - while (view) { - view = platform_util::GetParent(view); - if (view == tab_view) - return true; - } - - return false; -} - -bool IsFullHeight(const InstantOverlayModel& model) { - return model.height() == 100 && model.height_units() == INSTANT_SIZE_PERCENT; -} - bool IsContentsFrom(const InstantPage* page, const content::WebContents* contents) { return page && (page->contents() == contents); @@ -256,19 +118,9 @@ InstantController::InstantController(BrowserInstantController* browser, bool extended_enabled) : browser_(browser), extended_enabled_(extended_enabled), - instant_enabled_(false), - use_local_page_only_(true), - preload_ntp_(true), - model_(this), - use_tab_for_suggestions_(false), - last_omnibox_text_has_inline_autocompletion_(false), - last_verbatim_(false), - last_transition_type_(content::PAGE_TRANSITION_LINK), - last_match_was_search_(false), omnibox_focus_state_(OMNIBOX_FOCUS_NONE), omnibox_focus_change_reason_(OMNIBOX_FOCUS_CHANGE_EXPLICIT), - omnibox_bounds_(-1, -1, 0, 0), - allow_overlay_to_show_search_suggestions_(false) { + omnibox_bounds_(-1, -1, 0, 0) { // When the InstantController lives, the InstantService should live. // InstantService sets up profile-level facilities such as the ThemeSource for @@ -287,267 +139,6 @@ InstantController::~InstantController() { } } -void InstantController::OnAutocompleteStart() { - if (UseTabForSuggestions() && instant_tab_->supports_instant()) { - LOG_INSTANT_DEBUG_EVENT( - this, "OnAutocompleteStart: using InstantTab"); - return; - } - - // Not using |instant_tab_|. Check if overlay is OK to use. - InstantFallbackReason fallback_reason = ShouldSwitchToLocalOverlay(); - if (fallback_reason != INSTANT_FALLBACK_NONE) { - ResetOverlay(GetLocalInstantURL()); - RecordFallbackReasonHistogram(fallback_reason); - LOG_INSTANT_DEBUG_EVENT( - this, "OnAutocompleteStart: switching to local overlay"); - } else { - LOG_INSTANT_DEBUG_EVENT( - this, "OnAutocompleteStart: using existing overlay"); - } - use_tab_for_suggestions_ = false; -} - -bool InstantController::Update(const AutocompleteMatch& match, - const string16& user_text, - const string16& full_text, - size_t selection_start, - size_t selection_end, - bool verbatim, - bool user_input_in_progress, - bool omnibox_popup_is_open, - bool escape_pressed, - bool is_keyword_search) { - if (!extended_enabled() && !instant_enabled_) - return false; - - LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( - "Update: %s user_text='%s' full_text='%s' selection_start=%d " - "selection_end=%d verbatim=%d typing=%d popup=%d escape_pressed=%d " - "is_keyword_search=%d", - AutocompleteMatchType::ToString(match.type).c_str(), - UTF16ToUTF8(user_text).c_str(), UTF16ToUTF8(full_text).c_str(), - static_cast<int>(selection_start), static_cast<int>(selection_end), - verbatim, user_input_in_progress, omnibox_popup_is_open, escape_pressed, - is_keyword_search)); - - // Store the current |last_omnibox_text_| and update |last_omnibox_text_| - // upfront with the contents of |full_text|. Even if we do an early return, - // |last_omnibox_text_| will be updated. - string16 previous_omnibox_text = last_omnibox_text_; - last_omnibox_text_ = full_text; - last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && - !user_text.empty(); - - // TODO(dhollowa): Complete keyword match UI. For now just hide suggestions. - // http://crbug.com/153932. Note, this early escape is happens prior to the - // DCHECKs below because |user_text| and |full_text| have different semantics - // when keyword search is in effect. - if (is_keyword_search) { - if (UseTabForSuggestions()) - instant_tab_->sender()->Update(string16(), 0, 0, true); - else - HideOverlay(); - last_match_was_search_ = false; - last_suggestion_ = InstantSuggestion(); - return false; - } - - // Ignore spurious updates when the omnibox is blurred; otherwise click - // targets on the page may vanish before a click event arrives. - if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE) - return false; - - // If the popup is open, the user has to be typing. - DCHECK(!omnibox_popup_is_open || user_input_in_progress); - - // If the popup is closed, there should be no inline autocompletion. - DCHECK(omnibox_popup_is_open || user_text.empty() || user_text == full_text) - << user_text << "|" << full_text; - - // If there's no text in the omnibox, the user can't have typed any. - DCHECK(!full_text.empty() || user_text.empty()) << user_text; - - // If the user isn't typing, and the popup is closed, there can't be any - // user-typed text. - DCHECK(user_input_in_progress || omnibox_popup_is_open || user_text.empty()) - << user_text; - - // The overlay is being clicked and will commit soon. Don't change anything. - // TODO(sreeram): Add a browser test for this. - 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 overlay, the mode is set to "allow" further below. - if (!extended_enabled()) - search_mode_.mode = SearchMode::MODE_DEFAULT; - - // In non extended mode, Instant is disabled for URLs and keyword mode. - if (!extended_enabled() && - (!last_match_was_search_ || - match.type == AutocompleteMatchType::SEARCH_OTHER_ENGINE)) { - HideOverlay(); - return false; - } - - if (!UseTabForSuggestions() && !overlay_) { - HideOverlay(); - return false; - } - - if (extended_enabled()) { - if (!omnibox_popup_is_open) { - if (!user_input_in_progress) { - // If the user isn't typing and the omnibox popup is closed, it means a - // regular navigation, tab-switch or the user hitting Escape. - if (UseTabForSuggestions()) { - // The user is on a search results page. It may be showing results for - // a partial query the user typed before they hit Escape. Send the - // omnibox text to the page to restore the original results. - // - // In a tab switch, |instant_tab_| won't have updated yet, so it may - // be pointing to the previous tab (which was a search results page). - // Ensure we don't send the omnibox text to a random webpage (the new - // tab), by comparing the old and new WebContents. - if (escape_pressed && - instant_tab_->contents() == browser_->GetActiveWebContents()) { - // TODO(kmadhusu): If the |full_text| is not empty, send an - // onkeypress(esc) to the Instant page. Do not call - // onsubmit(full_text). Fix. - if (full_text.empty()) { - // Call onchange("") to clear the query for the page. - instant_tab_->sender()->Update(string16(), 0, 0, true); - instant_tab_->sender()->EscKeyPressed(); - } else { - instant_tab_->sender()->Submit(full_text); - } - } - } else if (!full_text.empty()) { - // If |full_text| is empty, the user is on the NTP. The overlay may - // be showing custom NTP content; hide only if that's not the case. - HideOverlay(); - } - } else if (full_text.empty()) { - // The user is typing, and backspaced away all omnibox text. Clear - // |last_omnibox_text_| so that we don't attempt to set suggestions. - last_omnibox_text_.clear(); - last_user_text_.clear(); - last_suggestion_ = InstantSuggestion(); - if (UseTabForSuggestions()) { - // On a search results page, tell it to clear old results. - instant_tab_->sender()->Update(string16(), 0, 0, true); - } else if (overlay_ && search_mode_.is_origin_ntp()) { - // On the NTP, tell the overlay to clear old results. Don't hide the - // overlay so it can show a blank page or logo if it wants. - overlay_->Update(string16(), 0, 0, true); - } else { - HideOverlay(); - } - } else { - // The user switched to a tab with partial text already in the omnibox. - 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 - // out to be, we should store |full_text| now, so that if the user hits - // Enter, we'll send the correct query to - // instant_tab_->sender()->Submit(). If the partial text is not a query - // (|last_match_was_search_| is false), we won't Submit(), so no need to - // worry about that. - last_user_text_ = user_text; - last_suggestion_ = InstantSuggestion(); - } - return false; - } else if (full_text.empty()) { - // The user typed a solitary "?". Same as the backspace case above. - last_omnibox_text_.clear(); - last_user_text_.clear(); - last_suggestion_ = InstantSuggestion(); - if (UseTabForSuggestions()) - instant_tab_->sender()->Update(string16(), 0, 0, true); - else if (overlay_ && search_mode_.is_origin_ntp()) - overlay_->Update(string16(), 0, 0, true); - else - HideOverlay(); - return false; - } - } else if (!omnibox_popup_is_open || full_text.empty()) { - // In the non-extended case, hide the overlay as long as the user isn't - // actively typing a non-empty query. - HideOverlay(); - return false; - } - - last_omnibox_text_has_inline_autocompletion_ = user_text != full_text; - - // If the user continues typing the same query as the suggested text is - // showing, reuse the suggestion (but only for INSTANT_COMPLETE_NEVER). - bool reused_suggestion = false; - if (last_suggestion_.behavior == INSTANT_COMPLETE_NEVER && - !last_omnibox_text_has_inline_autocompletion_) { - if (StartsWith(previous_omnibox_text, full_text, false)) { - // The user is backspacing away characters. - last_suggestion_.text.insert(0, previous_omnibox_text, full_text.size(), - previous_omnibox_text.size() - full_text.size()); - reused_suggestion = true; - } else if (StartsWith(full_text, previous_omnibox_text, false)) { - // The user is typing forward. Normalize any added characters. - reused_suggestion = NormalizeAndStripPrefix(&last_suggestion_.text, - string16(full_text, previous_omnibox_text.size())); - } - } - if (!reused_suggestion) - last_suggestion_ = InstantSuggestion(); - - // TODO(kmadhusu): Investigate whether it's possible to update - // |last_user_text_| at the beginning of this function. - last_user_text_ = user_text; - - if (!extended_enabled()) { - // In non-extended mode, the query is verbatim if there's any selection - // (including inline autocompletion) or if the cursor is not at the end. - verbatim = verbatim || selection_start != selection_end || - selection_start != full_text.size(); - } - last_verbatim_ = verbatim; - - last_transition_type_ = match.transition; - url_for_history_ = match.destination_url; - - // Allow search suggestions. In extended mode, SearchModeChanged() will set - // this, but it's not called in non-extended mode, so fake it. - if (!extended_enabled()) - search_mode_.mode = SearchMode::MODE_SEARCH_SUGGESTIONS; - - if (UseTabForSuggestions()) { - instant_tab_->sender()->Update(user_text, selection_start, - selection_end, verbatim); - } else if (overlay_) { - allow_overlay_to_show_search_suggestions_ = true; - - overlay_->Update(extended_enabled() ? user_text : full_text, - selection_start, selection_end, verbatim); - } - - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED, - content::Source<InstantController>(this), - content::NotificationService::NoDetails()); - - // We don't have new suggestions yet, but we can either reuse the existing - // suggestion or reset the existing "gray text". - browser_->SetInstantSuggestion(last_suggestion_); - - // Record the time of the first keypress for logging histograms. - if (!first_interaction_time_recorded_ && first_interaction_time_.is_null()) - first_interaction_time_ = base::Time::Now(); - - return true; -} - scoped_ptr<content::WebContents> InstantController::ReleaseNTPContents() { if (!extended_enabled() || !browser_->profile() || browser_->profile()->IsOffTheRecord() || @@ -562,180 +153,29 @@ scoped_ptr<content::WebContents> InstantController::ReleaseNTPContents() { scoped_ptr<content::WebContents> ntp_contents = ntp_->ReleaseContents(); // Preload a new Instant NTP. - if (preload_ntp_) - ResetNTP(GetInstantURL()); - else - ntp_.reset(); + ResetNTP(GetInstantURL()); return ntp_contents.Pass(); } -// TODO(tonyg): This method only fires when the omnibox bounds change. It also -// needs to fire when the overlay bounds change (e.g.: open/close info bar). -void InstantController::SetPopupBounds(const gfx::Rect& bounds) { - if (!extended_enabled() && !instant_enabled_) - return; - - if (popup_bounds_ == bounds) - return; - - popup_bounds_ = bounds; - if (popup_bounds_.height() > last_popup_bounds_.height()) { - update_bounds_timer_.Stop(); - SendPopupBoundsToPage(); - } else if (!update_bounds_timer_.IsRunning()) { - update_bounds_timer_.Start(FROM_HERE, - base::TimeDelta::FromMilliseconds(kUpdateBoundsDelayMS), this, - &InstantController::SendPopupBoundsToPage); - } -} - void InstantController::SetOmniboxBounds(const gfx::Rect& bounds) { if (!extended_enabled() || omnibox_bounds_ == bounds) return; omnibox_bounds_ = bounds; - if (overlay_) - overlay_->sender()->SetOmniboxBounds(omnibox_bounds_); if (ntp_) ntp_->sender()->SetOmniboxBounds(omnibox_bounds_); if (instant_tab_) instant_tab_->sender()->SetOmniboxBounds(omnibox_bounds_); } -void InstantController::HandleAutocompleteResults( - const std::vector<AutocompleteProvider*>& providers, - const AutocompleteResult& autocomplete_result) { - if (!extended_enabled()) - return; - - if (!UseTabForSuggestions() && !overlay_) - return; - - // The omnibox sends suggestions when its possibly imaginary popup closes - // as it stops autocomplete. Ignore these. - if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE) - return; - - DVLOG(1) << "AutocompleteResults:"; - std::vector<InstantAutocompleteResult> results; - if (UsingLocalPage()) { - for (AutocompleteResult::const_iterator match(autocomplete_result.begin()); - match != autocomplete_result.end(); ++match) { - InstantAutocompleteResult result; - PopulateInstantAutocompleteResultFromMatch( - *match, std::distance(autocomplete_result.begin(), match), &result); - results.push_back(result); - } - } else { - for (ACProviders::const_iterator provider = providers.begin(); - provider != providers.end(); ++provider) { - for (ACMatches::const_iterator match = (*provider)->matches().begin(); - match != (*provider)->matches().end(); ++match) { - // When the top match is an inline history URL, the page calls - // SetSuggestions(url) which calls FinalizeInstantQuery() in - // SearchProvider creating a NAVSUGGEST match for the URL. If we sent - // this NAVSUGGEST match back to the page, it would be deduped against - // the original history match and replace it. But since the page ignores - // SearchProvider suggestions, the match would then disappear. Yuck. - // TODO(jered): Remove this when FinalizeInstantQuery() is ripped out. - if ((*provider)->type() == AutocompleteProvider::TYPE_SEARCH && - match->type == AutocompleteMatchType::NAVSUGGEST) { - continue; - } - InstantAutocompleteResult result; - PopulateInstantAutocompleteResultFromMatch(*match, kNoMatchIndex, - &result); - results.push_back(result); - } - } - } - LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( - "HandleAutocompleteResults: total_results=%d", - static_cast<int>(results.size()))); - - if (UseTabForSuggestions()) - instant_tab_->sender()->SendAutocompleteResults(results); - else if (overlay_) - overlay_->sender()->SendAutocompleteResults(results); - - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_INSTANT_SENT_AUTOCOMPLETE_RESULTS, - content::Source<InstantController>(this), - content::NotificationService::NoDetails()); -} - void InstantController::OnDefaultSearchProviderChanged() { if (ntp_ && extended_enabled()) { ntp_.reset(); - if (preload_ntp_) - ResetNTP(GetInstantURL()); - } - - // Do not reload the overlay if it's actually the local overlay. - if (overlay_ && !overlay_->IsLocal()) { - overlay_.reset(); - if (extended_enabled() || instant_enabled_) { - // Try to create another overlay immediately so that it is ready for the - // next user interaction. - ResetOverlay(GetInstantURL()); - } - } -} - -bool InstantController::OnUpOrDownKeyPressed(int count) { - if (!extended_enabled()) - return false; - - if (!UseTabForSuggestions() && !overlay_) - return false; - - if (UseTabForSuggestions()) - instant_tab_->sender()->UpOrDownKeyPressed(count); - else if (overlay_) - overlay_->sender()->UpOrDownKeyPressed(count); - - return true; -} - -void InstantController::OnCancel(const AutocompleteMatch& match, - const string16& user_text, - const string16& full_text) { - if (!extended_enabled()) - return; - - if (!UseTabForSuggestions() && !overlay_) - return; - - // We manually reset the state here since the JS is not expected to do it. - // TODO(sreeram): Handle the case where user_text is now a URL - last_match_was_search_ = AutocompleteMatch::IsSearchType(match.type) && - !full_text.empty(); - last_omnibox_text_ = full_text; - last_user_text_ = user_text; - last_suggestion_ = InstantSuggestion(); - - // Say |full_text| is "amazon.com" and |user_text| is "ama". This means the - // inline autocompletion is "zon.com"; so the selection should span from - // user_text.size() to full_text.size(). The selection bounds are inverted - // because the caret is at the end of |user_text|, not |full_text|. - if (UseTabForSuggestions()) { - instant_tab_->sender()->CancelSelection(user_text, full_text.size(), - user_text.size(), last_verbatim_); - } else if (overlay_) { - overlay_->sender()->CancelSelection(user_text, full_text.size(), - user_text.size(), last_verbatim_); + ResetNTP(GetInstantURL()); } } -void InstantController::OmniboxNavigateToURL() { - RecordNavigationHistogram(UsingLocalPage(), false, extended_enabled()); - if (!extended_enabled()) - return; - if (UseTabForSuggestions()) - instant_tab_->sender()->Submit(string16()); -} - void InstantController::ToggleVoiceSearch() { if (instant_tab_) instant_tab_->sender()->ToggleVoiceSearch(); @@ -773,29 +213,15 @@ void InstantController::InstantPageLoadFailed(content::WebContents* contents) { DeletePageSoon(ntp_.Pass()); if (!is_local) ResetNTP(GetLocalInstantURL()); - } else if (IsContentsFrom(overlay(), contents)) { - LOG_INSTANT_DEBUG_EVENT(this, "InstantPageLoadFailed: overlay"); - bool is_local = overlay_->IsLocal(); - DeletePageSoon(overlay_.Pass()); - if (!is_local) - ResetOverlay(GetLocalInstantURL()); + } else { + NOTREACHED(); } } -content::WebContents* InstantController::GetOverlayContents() const { - return overlay_ ? overlay_->contents() : NULL; -} - content::WebContents* InstantController::GetNTPContents() const { return ntp_ ? ntp_->contents() : NULL; } -bool InstantController::IsOverlayingSearchResults() const { - return model_.mode().is_search_suggestions() && IsFullHeight(model_) && - (last_match_was_search_ || - last_suggestion_.behavior == INSTANT_COMPLETE_NEVER); -} - bool InstantController::SubmitQuery(const string16& search_terms) { if (extended_enabled() && instant_tab_ && instant_tab_->supports_instant() && search_mode_.is_origin_search()) { @@ -809,156 +235,6 @@ bool InstantController::SubmitQuery(const string16& search_terms) { return false; } -bool InstantController::CommitIfPossible(InstantCommitType type) { - if (!extended_enabled() && !instant_enabled_) - return false; - - LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( - "CommitIfPossible: type=%d last_omnibox_text_='%s' " - "last_match_was_search_=%d use_tab_for_suggestions=%d", type, - UTF16ToUTF8(last_omnibox_text_).c_str(), last_match_was_search_, - UseTabForSuggestions())); - - // If we are on an already committed search results page, send a submit event - // to the page, but otherwise, nothing else to do. - if (UseTabForSuggestions()) { - if (type == INSTANT_COMMIT_PRESSED_ENTER && - !instant_tab_->IsLocal() && - (last_match_was_search_ || - last_suggestion_.behavior == INSTANT_COMPLETE_NEVER)) { - last_suggestion_.text.clear(); - instant_tab_->sender()->Submit(last_omnibox_text_); - instant_tab_->contents()->GetView()->Focus(); - EnsureSearchTermsAreSet(instant_tab_->contents(), last_omnibox_text_); - return true; - } - return false; - } - - if (!overlay_) - return false; - - // If the overlay is not showing at all, don't commit it. - if (!model_.mode().is_search_suggestions()) - return false; - - // If the overlay is showing at full height (with results), commit it. - // If it's showing at parial height, commit if it's navigating. - if (!IsOverlayingSearchResults() && type != INSTANT_COMMIT_NAVIGATED) - return false; - - // 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, overlay_->ReleaseContents() was called already. - if (!GetOverlayContents()) - return false; - - // Never commit the local overlay. - if (overlay_->IsLocal()) - return false; - - if (type == INSTANT_COMMIT_FOCUS_LOST) { - // Extended mode doesn't need or use the Cancel message. - if (!extended_enabled()) - overlay_->sender()->Cancel(last_omnibox_text_); - } else if (type != INSTANT_COMMIT_NAVIGATED) { - overlay_->sender()->Submit(last_omnibox_text_); - } - - // We expect the WebContents to be in a valid state (i.e., has a last - // committed entry, no transient entry, and no existing pending entry). - scoped_ptr<content::WebContents> overlay = overlay_->ReleaseContents(); - CHECK(overlay->GetController().CanPruneAllButVisible()); - - // If the overlay page has navigated since the last Update(), we need to add - // 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 = - overlay_->last_navigation(); - if (!last_navigation.url.is_empty()) { - content::NavigationEntry* entry = overlay->GetController().GetActiveEntry(); - - // 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. - // TODO(shishir): Should we commit the last navigation for - // INSTANT_COMMIT_NAVIGATED. - DCHECK(type == INSTANT_COMMIT_NAVIGATED || - last_navigation.url == entry->GetURL()); - - // Add the page to history. - HistoryTabHelper* history_tab_helper = - HistoryTabHelper::FromWebContents(overlay.get()); - history_tab_helper->UpdateHistoryForNavigation(last_navigation); - - // Update the page title. - history_tab_helper->UpdateHistoryPageTitle(*entry); - } - - // Add a fake history entry with a non-Instant search URL, so that search - // terms extraction (for autocomplete history matches) works. - HistoryService* history = HistoryServiceFactory::GetForProfile( - Profile::FromBrowserContext(overlay->GetBrowserContext()), - Profile::EXPLICIT_ACCESS); - if (history) { - history->AddPage(url_for_history_, base::Time::Now(), NULL, 0, GURL(), - history::RedirectList(), last_transition_type_, - history::SOURCE_BROWSED, false); - } - - if (type == INSTANT_COMMIT_PRESSED_ALT_ENTER) { - overlay->GetController().PruneAllButVisible(); - } else { - content::WebContents* active_tab = browser_->GetActiveWebContents(); - AddSessionStorageHistogram(extended_enabled(), active_tab, overlay.get()); - overlay->GetController().CopyStateFromAndPrune( - &active_tab->GetController()); - } - - if (extended_enabled()) { - // Adjust the search terms shown in the omnibox for this query. Hitting - // ENTER searches for what the user typed, so use last_omnibox_text_. - // Clicking on the overlay commits what is currently showing, so add in the - // gray text in that case. - if (type == INSTANT_COMMIT_FOCUS_LOST && - last_suggestion_.behavior == INSTANT_COMPLETE_NEVER) { - // Update |last_omnibox_text_| so that the controller commits the proper - // query if the user focuses the omnibox and presses Enter. - last_omnibox_text_ += last_suggestion_.text; - } - - EnsureSearchTermsAreSet(overlay.get(), last_omnibox_text_); - } - - // Save notification source before we release the overlay. - content::Source<content::WebContents> notification_source(overlay.get()); - - browser_->CommitInstant(overlay.Pass(), - type == INSTANT_COMMIT_PRESSED_ALT_ENTER); - - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_INSTANT_COMMITTED, - notification_source, - content::NotificationService::NoDetails()); - - // Hide explicitly. See comments in HideOverlay() for why. - model_.SetOverlayState(SearchMode(), 0, INSTANT_SIZE_PERCENT); - - // Delay deletion as we could've gotten here from an InstantOverlay method. - DeletePageSoon(overlay_.Pass()); - - // Try to create another overlay immediately so that it is ready for the next - // user interaction. - ResetOverlay(GetInstantURL()); - - if (instant_tab_) - use_tab_for_suggestions_ = true; - - LOG_INSTANT_DEBUG_EVENT(this, "Committed"); - return true; -} - void InstantController::OmniboxFocusChanged( OmniboxFocusState state, OmniboxFocusChangeReason reason, @@ -967,9 +243,8 @@ void InstantController::OmniboxFocusChanged( "OmniboxFocusChanged: %d to %d for reason %d", omnibox_focus_state_, state, reason)); - OmniboxFocusState old_focus_state = omnibox_focus_state_; omnibox_focus_state_ = state; - if (!extended_enabled() && !instant_enabled_) + if (!extended_enabled() || !instant_tab_) return; content::NotificationService::current()->Notify( @@ -977,32 +252,12 @@ void InstantController::OmniboxFocusChanged( content::Source<InstantController>(this), content::NotificationService::NoDetails()); - if (extended_enabled()) { - if (overlay_) - overlay_->sender()->FocusChanged(omnibox_focus_state_, reason); - - if (instant_tab_) { - instant_tab_->sender()->FocusChanged(omnibox_focus_state_, reason); - // Don't send oninputstart/oninputend updates in response to focus changes - // if there's a navigation in progress. This prevents Chrome from sending - // a spurious oninputend when the user accepts a match in the omnibox. - if (instant_tab_->contents()->GetController().GetPendingEntry() == NULL) - instant_tab_->sender()->SetInputInProgress(IsInputInProgress()); - } - } - - if (state == OMNIBOX_FOCUS_VISIBLE && old_focus_state == OMNIBOX_FOCUS_NONE) { - // If the user explicitly focused the omnibox, then create the overlay if - // it doesn't exist. If we're using a fallback overlay, try loading the - // remote overlay again. - if (!overlay_ || (overlay_->IsLocal() && !use_local_page_only_)) - ResetOverlay(GetInstantURL()); - } else if (state == OMNIBOX_FOCUS_NONE && - old_focus_state != OMNIBOX_FOCUS_NONE) { - // If the focus went from the omnibox to outside the omnibox, commit or - // discard the overlay. - OmniboxLostFocus(view_gaining_focus); - } + instant_tab_->sender()->FocusChanged(omnibox_focus_state_, reason); + // Don't send oninputstart/oninputend updates in response to focus changes + // if there's a navigation in progress. This prevents Chrome from sending + // a spurious oninputend when the user accepts a match in the omnibox. + if (instant_tab_->contents()->GetController().GetPendingEntry() == NULL) + instant_tab_->sender()->SetInputInProgress(IsInputInProgress()); } void InstantController::SearchModeChanged(const SearchMode& old_mode, @@ -1015,9 +270,6 @@ void InstantController::SearchModeChanged(const SearchMode& old_mode, old_mode.mode, new_mode.origin, new_mode.mode)); search_mode_ = new_mode; - if (!new_mode.is_search_suggestions()) - HideOverlay(); - ResetInstantTab(); if (instant_tab_ && old_mode.is_ntp() != new_mode.is_ntp()) @@ -1025,57 +277,14 @@ void InstantController::SearchModeChanged(const SearchMode& old_mode, } void InstantController::ActiveTabChanged() { - if (!extended_enabled() && !instant_enabled_) + if (!extended_enabled()) return; LOG_INSTANT_DEBUG_EVENT(this, "ActiveTabChanged"); - - // When switching tabs, always hide the overlay. - HideOverlay(); - - if (extended_enabled()) - ResetInstantTab(); + ResetInstantTab(); } void InstantController::TabDeactivated(content::WebContents* contents) { - LOG_INSTANT_DEBUG_EVENT(this, "TabDeactivated"); - if (extended_enabled() && !contents->IsBeingDestroyed()) - CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); - - if (GetOverlayContents()) - HideOverlay(); -} - -void InstantController::SetInstantEnabled(bool instant_enabled, - bool use_local_page_only) { - LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( - "SetInstantEnabled: instant_enabled=%d, use_local_page_only=%d", - instant_enabled, use_local_page_only)); - - // Non extended mode does not care about |use_local_page_only|. - if (instant_enabled == instant_enabled_ && - (!extended_enabled() || - use_local_page_only == use_local_page_only_)) { - return; - } - - instant_enabled_ = instant_enabled; - use_local_page_only_ = use_local_page_only; - preload_ntp_ = !use_local_page_only_; - - // Preload the overlay. - HideInternal(); - overlay_.reset(); - if (extended_enabled() || instant_enabled_) - ResetOverlay(GetInstantURL()); - - // Preload the Instant NTP. - ntp_.reset(); - if (extended_enabled() && preload_ntp_) - ResetNTP(GetInstantURL()); - - if (instant_tab_) - instant_tab_->sender()->SetDisplayInstantResults(instant_enabled_); } void InstantController::ThemeInfoChanged( @@ -1083,52 +292,12 @@ void InstantController::ThemeInfoChanged( if (!extended_enabled()) return; - if (overlay_) - overlay_->sender()->SendThemeBackgroundInfo(theme_info); if (ntp_) ntp_->sender()->SendThemeBackgroundInfo(theme_info); if (instant_tab_) instant_tab_->sender()->SendThemeBackgroundInfo(theme_info); } -void InstantController::SwappedOverlayContents() { - model_.SetOverlayContents(GetOverlayContents()); -} - -void InstantController::FocusedOverlayContents() { -#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_->InstantOverlayFocused(); -#endif -} - -void InstantController::ReloadOverlayIfStale() { - // The local overlay is never stale. - if (overlay_ && (overlay_->IsLocal() || !overlay_->is_stale())) - return; - - // If the overlay is showing or the omnibox has focus, don't refresh the - // overlay. It will get refreshed the next time the overlay is hidden or the - // omnibox loses focus. - if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE && model_.mode().is_default()) - ResetOverlay(GetInstantURL()); -} - -void InstantController::OverlayLoadCompletedMainFrame() { - if (!overlay_ || overlay_->supports_instant()) - return; - InstantService* instant_service = GetInstantService(); - content::WebContents* contents = overlay_->contents(); - DCHECK(contents); - if (instant_service->IsInstantProcess( - contents->GetRenderProcessHost()->GetID())) { - return; - } - InstantSupportDetermined(contents, false); -} - void InstantController::LogDebugEvent(const std::string& info) const { DVLOG(1) << info; @@ -1145,12 +314,8 @@ void InstantController::ClearDebugEvents() { void InstantController::MostVisitedItemsChanged( const std::vector<InstantMostVisitedItem>& items) { - if (overlay_) - overlay_->sender()->SendMostVisitedItems(items); - if (ntp_) ntp_->sender()->SendMostVisitedItems(items); - if (instant_tab_) instant_tab_->sender()->SendMostVisitedItems(items); @@ -1190,10 +355,6 @@ Profile* InstantController::profile() const { return browser_->profile(); } -InstantOverlay* InstantController::overlay() const { - return overlay_.get(); -} - InstantTab* InstantController::instant_tab() const { return instant_tab_.get(); } @@ -1207,7 +368,7 @@ void InstantController::OnNetworkChanged( // Not interested in events conveying change to offline if (type == net::NetworkChangeNotifier::CONNECTION_NONE) return; - if (!extended_enabled_ || use_local_page_only_) + if (!extended_enabled_) return; if (!ntp_ || ntp_->IsLocal()) ResetNTP(GetInstantURL()); @@ -1228,14 +389,7 @@ void InstantController::InstantPageRenderViewCreated( } // Ensure the searchbox API has the correct initial state. - if (IsContentsFrom(overlay(), contents)) { - overlay_->sender()->SetDisplayInstantResults(instant_enabled_); - overlay_->sender()->FocusChanged(omnibox_focus_state_, - omnibox_focus_change_reason_); - overlay_->sender()->SetOmniboxBounds(omnibox_bounds_); - overlay_->InitializeFonts(); - } else if (IsContentsFrom(ntp(), contents)) { - ntp_->sender()->SetDisplayInstantResults(instant_enabled_); + if (IsContentsFrom(ntp(), contents)) { ntp_->sender()->SetOmniboxBounds(omnibox_bounds_); ntp_->InitializeFonts(); ntp_->InitializePromos(); @@ -1286,29 +440,14 @@ void InstantController::InstantSupportDetermined( content::Source<InstantController>(this), content::NotificationService::NoDetails()); - } else if (IsContentsFrom(overlay(), contents)) { - if (!supports_instant) { - HideInternal(); - bool is_local = overlay_->IsLocal(); - DeletePageSoon(overlay_.Pass()); - // Preload a local overlay in place of the broken online one. - if (!is_local && extended_enabled()) - ResetOverlay(GetLocalInstantURL()); - } - - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_INSTANT_OVERLAY_SUPPORT_DETERMINED, - content::Source<InstantController>(this), - content::NotificationService::NoDetails()); + } else { + NOTREACHED(); } } void InstantController::InstantPageRenderViewGone( const content::WebContents* contents) { - if (IsContentsFrom(overlay(), contents)) { - HideInternal(); - DeletePageSoon(overlay_.Pass()); - } else if (IsContentsFrom(ntp(), contents)) { + if (IsContentsFrom(ntp(), contents)) { DeletePageSoon(ntp_.Pass()); } else { NOTREACHED(); @@ -1318,31 +457,7 @@ void InstantController::InstantPageRenderViewGone( void InstantController::InstantPageAboutToNavigateMainFrame( const content::WebContents* contents, const GURL& url) { - if (IsContentsFrom(overlay(), contents)) { - // 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); - } - } else if (IsContentsFrom(instant_tab(), contents)) { + if (IsContentsFrom(instant_tab(), contents)) { // The Instant tab navigated. Send it the data it needs to display // properly. UpdateInfoForInstantTab(); @@ -1351,118 +466,6 @@ void InstantController::InstantPageAboutToNavigateMainFrame( } } -void InstantController::SetSuggestions( - const content::WebContents* contents, - const std::vector<InstantSuggestion>& suggestions) { - LOG_INSTANT_DEBUG_EVENT(this, "SetSuggestions"); - - // Ignore if the message is from an unexpected source. - if (IsContentsFrom(ntp(), contents)) - return; - if (UseTabForSuggestions() && !IsContentsFrom(instant_tab(), contents)) - return; - if (IsContentsFrom(overlay(), contents) && - !allow_overlay_to_show_search_suggestions_) - return; - - InstantSuggestion suggestion; - if (!suggestions.empty()) - suggestion = suggestions[0]; - - // TODO(samarth): allow InstantTabs to call SetSuggestions() from the NTP once - // that is better supported. - bool can_use_instant_tab = UseTabForSuggestions() && - search_mode_.is_search(); - bool can_use_overlay = search_mode_.is_search_suggestions() && - !last_omnibox_text_.empty(); - if (!can_use_instant_tab && !can_use_overlay) - return; - - if (suggestion.behavior == INSTANT_COMPLETE_REPLACE) { - if (omnibox_focus_state_ == OMNIBOX_FOCUS_NONE) { - // TODO(samarth,skanuj): setValue() needs to be handled differently when - // the omnibox doesn't have focus. Instead of setting temporary text, we - // should be setting search terms on the appropriate NavigationEntry. - // (Among other things, this ensures that URL-shaped values will get the - // additional security token.) - // - // Note that this also breaks clicking on a suggestion corresponding to - // gray-text completion: we can't distinguish between the user - // clicking on white space (where we don't accept the gray text) and the - // user clicking on the suggestion (when we do accept the gray text). - // This needs to be fixed before we can turn on Instant again. - return; - } - - // We don't get an Update() when changing the omnibox due to a REPLACE - // suggestion (so that we don't inadvertently cause the overlay to change - // what it's showing, as the user arrows up/down through the page-provided - // suggestions). So, update these state variables here. - last_omnibox_text_ = suggestion.text; - last_user_text_.clear(); - last_suggestion_ = InstantSuggestion(); - last_match_was_search_ = suggestion.type == INSTANT_SUGGESTION_SEARCH; - LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( - "ReplaceSuggestion text='%s' type=%d", - UTF16ToUTF8(suggestion.text).c_str(), suggestion.type)); - browser_->SetInstantSuggestion(suggestion); - } else { - if (FixSuggestion(&suggestion)) { - last_suggestion_ = suggestion; - if (suggestion.type == INSTANT_SUGGESTION_SEARCH && - suggestion.behavior == INSTANT_COMPLETE_NEVER) - last_omnibox_text_ = last_user_text_; - LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( - "SetInstantSuggestion: text='%s' behavior=%d", - UTF16ToUTF8(suggestion.text).c_str(), - suggestion.behavior)); - browser_->SetInstantSuggestion(suggestion); - content::NotificationService::current()->Notify( - chrome::NOTIFICATION_INSTANT_SET_SUGGESTION, - content::Source<InstantController>(this), - content::NotificationService::NoDetails()); - } else { - last_suggestion_ = InstantSuggestion(); - } - } - - // Extended mode pages will call ShowOverlay() when they are ready. - if (!extended_enabled()) - ShowOverlay(100, INSTANT_SIZE_PERCENT); -} - -void InstantController::ShowInstantOverlay(const content::WebContents* contents, - int height, - InstantSizeUnits units) { - if (extended_enabled() && IsContentsFrom(overlay(), contents)) - ShowOverlay(height, units); -} - -void InstantController::LogDropdownShown() { - // If suggestions are being shown for the first time since the user started - // typing, record a histogram value. - if (!first_interaction_time_.is_null() && !first_interaction_time_recorded_) { - base::TimeDelta delta = base::Time::Now() - first_interaction_time_; - first_interaction_time_recorded_ = true; - if (search_mode_.is_origin_ntp()) { - UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShowFromNTP", delta); - LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( - "LogShowInstantOverlay: TimeToFirstShowFromNTP=%d", - static_cast<int>(delta.InMilliseconds()))); - } else if (search_mode_.is_origin_search()) { - UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShowFromSERP", delta); - LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( - "LogShowInstantOverlay: TimeToFirstShowFromSERP=%d", - static_cast<int>(delta.InMilliseconds()))); - } else { - UMA_HISTOGRAM_TIMES("Instant.TimeToFirstShowFromWeb", delta); - LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( - "LogShowInstantOverlay: TimeToFirstShowFromWeb=%d", - static_cast<int>(delta.InMilliseconds()))); - } - } -} - void InstantController::FocusOmnibox(const content::WebContents* contents, OmniboxFocusState state) { if (!extended_enabled()) @@ -1505,9 +508,6 @@ void InstantController::NavigateToURL(const content::WebContents* contents, // has switched tabs). if (!extended_enabled()) return; - if (overlay_) { - HideOverlay(); - } if (transition == content::PAGE_TRANSITION_AUTO_BOOKMARK) { content::RecordAction( @@ -1520,43 +520,12 @@ void InstantController::NavigateToURL(const content::WebContents* contents, browser_->OpenURL(url, transition, disposition); } -void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) { - // If the overlay is showing custom NTP content, don't hide it, commit it - // (no matter where the user clicked) or try to recreate it. - if (model_.mode().is_ntp()) - return; - - if (model_.mode().is_default()) { - // If the overlay is not showing at all, recreate it if it's stale. - ReloadOverlayIfStale(); - return; - } - - // The overlay is showing search suggestions. If GetOverlayContents() is NULL, - // we are in the commit path. Don't do anything. - if (!GetOverlayContents()) - return; - -#if defined(OS_MACOSX) - // TODO(sreeram): See if Mac really needs this special treatment. - if (!overlay_->is_pointer_down_from_activate()) - HideOverlay(); -#else - if (IsFullHeight(model_)) - CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); - else if (!IsViewInContents(GetViewGainingFocus(view_gaining_focus), - overlay_->contents())) - HideOverlay(); -#endif -} - std::string InstantController::GetLocalInstantURL() const { return chrome::GetLocalInstantURL(profile()).spec(); } std::string InstantController::GetInstantURL() const { - if (extended_enabled() && - (use_local_page_only_ || net::NetworkChangeNotifier::IsOffline())) + if (extended_enabled() && net::NetworkChangeNotifier::IsOffline()) return GetLocalInstantURL(); const GURL instant_url = chrome::GetInstantURL(profile(), @@ -1601,7 +570,8 @@ void InstantController::ResetNTP(const std::string& instant_url) { } void InstantController::ReloadStaleNTP() { - ResetNTP(GetInstantURL()); + if (extended_enabled()) + ResetNTP(GetInstantURL()); } bool InstantController::ShouldSwitchToLocalNTP() const { @@ -1626,33 +596,6 @@ bool InstantController::ShouldSwitchToLocalNTP() const { return !(InStartup() && chrome::ShouldPreferRemoteNTPOnStartup()); } -void InstantController::ResetOverlay(const std::string& instant_url) { - HideInternal(); - overlay_.reset(); -} - -InstantController::InstantFallbackReason -InstantController::ShouldSwitchToLocalOverlay() const { - if (!extended_enabled()) - return INSTANT_FALLBACK_NONE; - - if (!overlay()) - return DetermineFallbackReason(NULL, std::string()); - - // Assume users with Javascript disabled do not want the online experience. - if (!IsJavascriptEnabled()) - return INSTANT_FALLBACK_JAVASCRIPT_DISABLED; - - if (overlay()->IsLocal()) - return INSTANT_FALLBACK_NONE; - - bool page_is_current = PageIsCurrent(overlay()); - if (!page_is_current) - return DetermineFallbackReason(overlay(), GetInstantURL()); - - return INSTANT_FALLBACK_NONE; -} - void InstantController::ResetInstantTab() { if (!search_mode_.is_origin_default()) { content::WebContents* active_tab = browser_->GetActiveWebContents(); @@ -1661,11 +604,7 @@ void InstantController::ResetInstantTab() { new InstantTab(this, browser_->profile()->IsOffTheRecord())); instant_tab_->Init(active_tab); UpdateInfoForInstantTab(); - use_tab_for_suggestions_ = true; } - - // Hide the |overlay_| since we are now using |instant_tab_| instead. - HideOverlay(); } else { instant_tab_.reset(); } @@ -1673,7 +612,6 @@ void InstantController::ResetInstantTab() { void InstantController::UpdateInfoForInstantTab() { if (instant_tab_) { - instant_tab_->sender()->SetDisplayInstantResults(instant_enabled_); instant_tab_->sender()->SetOmniboxBounds(omnibox_bounds_); // Update theme details. @@ -1696,168 +634,8 @@ bool InstantController::IsInputInProgress() const { omnibox_focus_state_ == OMNIBOX_FOCUS_VISIBLE; } -void InstantController::HideOverlay() { - HideInternal(); - ReloadOverlayIfStale(); -} - -void InstantController::HideInternal() { - LOG_INSTANT_DEBUG_EVENT(this, "Hide"); - - // If GetOverlayContents() returns NULL, either we're already in the desired - // MODE_DEFAULT state, or we're in the commit path. For the latter, don't - // change the state just yet; else we may hide the overlay unnecessarily. - // Instead, the state will be set correctly after the commit is done. - if (GetOverlayContents()) { - model_.SetOverlayState(SearchMode(), 0, INSTANT_SIZE_PERCENT); - allow_overlay_to_show_search_suggestions_ = false; - - // Send a message asking the overlay to clear out old results. - overlay_->Update(string16(), 0, 0, true); - } - - // Clear the first interaction timestamp for later use. - first_interaction_time_ = base::Time(); - first_interaction_time_recorded_ = false; - - if (instant_tab_) - use_tab_for_suggestions_ = true; -} - -void InstantController::ShowOverlay(int height, InstantSizeUnits units) { - // Nothing to see here. - if (!overlay_) - return; - - // If we are on a committed search results page, the |overlay_| is not in use. - if (UseTabForSuggestions()) - return; - - LOG_INSTANT_DEBUG_EVENT(this, base::StringPrintf( - "Show: height=%d units=%d", height, units)); - - // Must have updated omnibox after the last HideOverlay() to show suggestions. - if (!allow_overlay_to_show_search_suggestions_) - return; - - // The page is trying to hide itself. Hide explicitly (i.e., don't use - // HideOverlay()) so that it can change its mind. - if (height == 0) { - model_.SetOverlayState(SearchMode(), 0, INSTANT_SIZE_PERCENT); - if (instant_tab_) - use_tab_for_suggestions_ = true; - return; - } - - // Show at 100% height except in the following cases: - // - The local overlay (omnibox popup) is being loaded. - // - Instant is disabled. The page needs to be able to show only a dropdown. - // - The page is over a website other than search or an NTP, and is not - // already showing at 100% height. - if (overlay_->IsLocal() || !instant_enabled_ || - (search_mode_.is_origin_default() && !IsFullHeight(model_))) - model_.SetOverlayState(search_mode_, height, units); - else - model_.SetOverlayState(search_mode_, 100, INSTANT_SIZE_PERCENT); - - // If the overlay is being shown at full height and the omnibox is not - // focused, commit right away. - if (IsFullHeight(model_) && omnibox_focus_state_ == OMNIBOX_FOCUS_NONE) - CommitIfPossible(INSTANT_COMMIT_FOCUS_LOST); -} - -void InstantController::SendPopupBoundsToPage() { - if (last_popup_bounds_ == popup_bounds_ || !overlay_ || - overlay_->is_pointer_down_from_activate()) - return; - - last_popup_bounds_ = popup_bounds_; - gfx::Rect overlay_bounds = browser_->GetInstantBounds(); - gfx::Rect intersection = gfx::IntersectRects(popup_bounds_, overlay_bounds); - - // Translate into window coordinates. - if (!intersection.IsEmpty()) { - intersection.Offset(-overlay_bounds.origin().x(), - -overlay_bounds.origin().y()); - } - - // In the current Chrome UI, these must always be true so they sanity check - // the above operations. In a future UI, these may be removed or adjusted. - // There is no point in sanity-checking |intersection.y()| because the omnibox - // can be placed anywhere vertically relative to the overlay (for example, in - // Mac fullscreen mode, the omnibox is fully enclosed by the overlay bounds). - DCHECK_LE(0, intersection.x()); - DCHECK_LE(0, intersection.width()); - DCHECK_LE(0, intersection.height()); - - overlay_->sender()->SetPopupBounds(intersection); -} - - - -bool InstantController::FixSuggestion(InstantSuggestion* suggestion) const { - // We only accept suggestions if the user has typed text. If the user is - // arrowing up/down (|last_user_text_| is empty), we reject suggestions. - if (last_user_text_.empty()) - return false; - - // If the page is trying to set inline autocompletion in verbatim mode, - // instead try suggesting the exact omnibox text. This makes the omnibox - // interpret user text as an URL if possible while preventing unwanted - // autocompletion during backspacing. - if (suggestion->behavior == INSTANT_COMPLETE_NOW && last_verbatim_) - suggestion->text = last_omnibox_text_; - - // Suggestion text should be a full URL for URL suggestions, or the - // completion of a query for query suggestions. - if (suggestion->type == INSTANT_SUGGESTION_URL) { - // If the suggestion is not a valid URL, perhaps it's something like - // "foo.com". Try prefixing "http://". If it still isn't valid, drop it. - if (!GURL(suggestion->text).is_valid()) { - suggestion->text.insert(0, ASCIIToUTF16("http://")); - if (!GURL(suggestion->text).is_valid()) - return false; - } - - // URL suggestions are only accepted if the query for which the suggestion - // was generated is the same as |last_user_text_|. - // - // Any other URL suggestions--in particular suggestions for old user_text - // lagging behind a slow IPC--are ignored. See crbug.com/181589. - // - // TODO(samarth): Accept stale suggestions if they would be accepted by - // SearchProvider as an inlinable suggestion. http://crbug.com/191656. - return suggestion->query == last_user_text_; - } - - // We use |last_user_text_| because |last_omnibox_text| may contain text from - // a previous URL suggestion at this point. - if (suggestion->type == INSTANT_SUGGESTION_SEARCH) { - if (StartsWith(suggestion->text, last_user_text_, true)) { - // The user typed an exact prefix of the suggestion. - suggestion->text.erase(0, last_user_text_.size()); - return true; - } else if (NormalizeAndStripPrefix(&suggestion->text, last_user_text_)) { - // Unicode normalize and case-fold the user text and suggestion. If the - // user text is a prefix, suggest the normalized, case-folded completion - // for instance, if the user types 'i' and the suggestion is 'INSTANT', - // suggest 'nstant'. Otherwise, the user text really isn't a prefix, so - // suggest nothing. - // TODO(samarth|jered): revisit this logic. http://crbug.com/196572. - return true; - } - } - - return false; -} - bool InstantController::UsingLocalPage() const { - return (UseTabForSuggestions() && instant_tab_->IsLocal()) || - (!UseTabForSuggestions() && overlay_ && overlay_->IsLocal()); -} - -bool InstantController::UseTabForSuggestions() const { - return instant_tab_ && use_tab_for_suggestions_; + return instant_tab_ && instant_tab_->IsLocal(); } void InstantController::RedirectToLocalNTP(content::WebContents* contents) { @@ -1871,31 +649,6 @@ void InstantController::RedirectToLocalNTP(content::WebContents* contents) { // entry. } -void InstantController::PopulateInstantAutocompleteResultFromMatch( - const AutocompleteMatch& match, size_t autocomplete_match_index, - InstantAutocompleteResult* result) { - DCHECK(result); - result->provider = UTF8ToUTF16(match.provider->GetName()); - result->type = match.type; - result->description = match.description; - result->destination_url = UTF8ToUTF16(match.destination_url.spec()); - - // Setting the search_query field tells the Instant page to treat the - // suggestion as a query. - if (AutocompleteMatch::IsSearchType(match.type)) - result->search_query = match.contents; - - result->transition = match.transition; - result->relevance = match.relevance; - result->autocomplete_match_index = autocomplete_match_index; - - DVLOG(1) << " " << result->relevance << " " - << UTF8ToUTF16(AutocompleteMatchType::ToString(result->type)) << " " - << result->provider << " " << result->destination_url << " '" - << result->description << "' '" << result->search_query << "' " - << result->transition << " " << result->autocomplete_match_index; -} - bool InstantController::IsJavascriptEnabled() const { GURL instant_url(GetInstantURL()); GURL origin(instant_url.GetOrigin()); |