Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(3970)

Unified Diff: chrome/browser/instant/instant_controller.cc

Issue 11421079: Persist the Instant API to committed search result pages. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 8 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/instant/instant_controller.cc
diff --git a/chrome/browser/instant/instant_controller.cc b/chrome/browser/instant/instant_controller.cc
index 0c0f54706186ed867be074c5b94ac6579ce32d6f..293fd04beef5aec6148193b75babb129acb58d3f 100644
--- a/chrome/browser/instant/instant_controller.cc
+++ b/chrome/browser/instant/instant_controller.cc
@@ -176,11 +176,12 @@ bool InstantController::Update(const AutocompleteMatch& match,
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 == full_text) << user_text << "|"
- << full_text;
+ DCHECK(omnibox_popup_is_open || user_text.empty() || user_text == full_text)
+ << user_text << "|" << full_text;
// If there's inline autocompletion, the query has to be verbatim.
- DCHECK(user_text == full_text || verbatim) << user_text << "|" << full_text;
+ DCHECK(user_text.empty() || user_text == full_text || verbatim)
+ << 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;
@@ -204,6 +205,21 @@ bool InstantController::Update(const AutocompleteMatch& match,
return false;
}
+ // Ensure we have a loader that can process this match. First, try to use the
+ // TemplateURL of the |match|. If that's invalid, in non-extended mode, stop.
+ // In extended mode, try using the default search engine, but only when the
+ // match is for a URL (i.e., not some other kind of non-Instant search).
+ // A completely blank query shows up as a search, and we do want to allow
+ // that, hence the "!user_text.empty()" clause.
+ Profile* const profile = active_tab->profile();
+ const bool match_is_search = AutocompleteMatch::IsSearchType(match.type);
+ if (!ResetLoader(match.GetTemplateURL(profile, false), active_tab) &&
Jered 2012/11/27 19:21:57 Why reset the loader here if client_ is set?
sreeram 2012/11/29 07:33:19 Done.
+ (!extended_enabled_ || (match_is_search && !user_text.empty()) ||
+ (!client_ && !CreateDefaultLoader()))) {
+ Hide(true);
+ return false;
+ }
+
// Legend: OPIO == |omnibox_popup_is_open|, UIIP = |user_input_in_progress|.
//
// # OPIO UIIP full_text Notes
@@ -226,40 +242,47 @@ bool InstantController::Update(const AutocompleteMatch& match,
//
// In extended mode, #2 and #4 call Hide(). #1 doesn't Hide() as the preview
// may be showing custom NTP content, but doesn't Update() either. #3 and #7
- // don't Hide(), but send a blank query to Update(). #8 calls Update().
+ // don't Hide(), and send a blank query to Update(). #8 calls Update().
if (extended_enabled_) {
if (!omnibox_popup_is_open) {
- if (!full_text.empty()) {
- Hide(true);
- return false;
+ if (!user_input_in_progress) {
+ if (!full_text.empty()) {
+ Hide(true); // #2
samarth 2012/11/27 18:09:43 Mostly for my understanding: Hide() will be a no-o
sreeram 2012/11/29 07:33:19 No, Hide() won't be a no-op. For one, it will actu
+ // If the user hit Escape when on a search results page, restore the
+ // original results by resending the query. If the user was not on a
+ // search results page, SearchModeChanged() would've caught it, and
+ // |client_| will be NULL, so we won't accidentally send non-query
+ // |full_text| to |client_|. Except if the user just switched tabs.
+ // Hence the comparison of WebContents, to catch that case as well.
+ if (client_ && client_->contents() == active_tab->web_contents())
+ client_->Update(full_text, true);
+ }
+ return false; // #1
+ } else {
+ if (!full_text.empty()) {
+ Hide(true); // #4
+ if (match_is_search) {
+ // The user just switched to a tab with a partial query already in
+ // the omnibox. This tab may or may not be a search results page
+ // (SearchModeChanged() hasn't been called yet). So, assume that it
+ // could be, and store |full_text| so that if the user then hits
+ // Enter, we'll send the correct query in client_->Submit().
+ last_full_text_ = full_text;
+ last_match_was_search_ = true;
+ }
+ return false;
+ }
}
- if (!user_input_in_progress && full_text.empty())
- return false;
}
} else if (!omnibox_popup_is_open || full_text.empty()) {
// Update() can be called if the user clicks the preview while composing
// text with an IME. If so, we should commit on mouse up, so don't Hide().
- if (!GetPreviewContents() || !loader_->IsPointerDownFromActivate())
+ if (!loader_ || !loader_->IsPointerDownFromActivate())
Hide(true);
return false;
}
- // Ensure we have a loader that can process this match. First, try to use the
- // TemplateURL of the |match|. If that's invalid, in non-extended mode, stop.
- // In extended mode, try using the default search engine, but only when the
- // match is for a URL (i.e., not some other kind of non-Instant search).
- // A completely blank query shows up as a search, and we do want to allow
- // that, hence the "!full_text.empty()" clause.
- Profile* const profile = active_tab->profile();
- const bool match_is_search = AutocompleteMatch::IsSearchType(match.type);
- if (!ResetLoader(match.GetTemplateURL(profile, false), active_tab) &&
- (!extended_enabled_ || (match_is_search && !full_text.empty()) ||
- !CreateDefaultLoader())) {
- Hide(true);
- return false;
- }
-
// 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;
@@ -288,7 +311,7 @@ bool InstantController::Update(const AutocompleteMatch& match,
url_for_history_ = match.destination_url;
// Store the first interaction time for use with latency histograms.
- if (first_interaction_time_.is_null())
+ if (loader_ == CurrentClient() && first_interaction_time_.is_null())
Jered 2012/11/27 19:21:57 Please extract a method like IsCommitted() for loa
sreeram 2012/11/29 07:33:19 I've gone with the simpler "if (instant_tab_)" idi
first_interaction_time_ = base::Time::Now();
// Allow search suggestions. In extended mode, SearchModeChanged() will set
@@ -296,7 +319,10 @@ bool InstantController::Update(const AutocompleteMatch& match,
if (!extended_enabled_)
search_mode_.mode = chrome::search::Mode::MODE_SEARCH_SUGGESTIONS;
- loader_->Update(extended_enabled_ ? user_text : full_text, verbatim);
+ CurrentClient()->Update(extended_enabled_ ? user_text : full_text, verbatim);
+
+ if (loader_ == CurrentClient())
+ loader_->DidNavigate(history::HistoryAddPageArgs());
content::NotificationService::current()->Notify(
chrome::NOTIFICATION_INSTANT_CONTROLLER_UPDATED,
@@ -338,9 +364,6 @@ void InstantController::HandleAutocompleteResults(
if (!extended_enabled_)
return;
sky 2012/11/27 01:07:51 Shouldn't we early out if no client?
sreeram 2012/11/29 07:33:19 Done.
- if (!GetPreviewContents())
- return;
-
DVLOG(1) << "AutocompleteResults:";
std::vector<InstantAutocompleteResult> results;
for (ACProviders::const_iterator provider = providers.begin();
@@ -360,18 +383,20 @@ void InstantController::HandleAutocompleteResults(
}
}
- loader_->SendAutocompleteResults(results);
+ if (InstantClient* client = CurrentClient())
samarth 2012/11/27 18:09:43 nit: does the Chrome style guide allow this? I hav
sreeram 2012/11/29 07:33:19 The style guide doesn't mention it. @sky hates it.
+ client->SendAutocompleteResults(results);
}
bool InstantController::OnUpOrDownKeyPressed(int count) {
if (!extended_enabled_)
return false;
- if (!GetPreviewContents())
- return false;
+ if (InstantClient* client = CurrentClient()) {
+ client->UpOrDownKeyPressed(count);
+ return true;
+ }
- loader_->OnUpOrDownKeyPressed(count);
- return true;
+ return false;
}
TabContents* InstantController::GetPreviewContents() const {
@@ -386,11 +411,24 @@ bool InstantController::CommitIfCurrent(InstantCommitType type) {
if (!extended_enabled_ && !instant_enabled_)
return false;
+ if (client_ == CurrentClient() && last_match_was_search_ &&
Jered 2012/11/27 19:21:57 I am very confused. Why doesn't this cancel someti
sreeram 2012/11/29 07:33:19 Cancel() isn't applicable in the case of a committ
+ type == INSTANT_COMMIT_PRESSED_ENTER) {
+ client_->Submit(last_full_text_);
+ return true;
+ }
+
if (!IsCurrent())
return false;
DVLOG(1) << "CommitIfCurrent";
- TabContents* preview = loader_->ReleasePreviewContents(type, last_full_text_);
+
+ if (type == INSTANT_COMMIT_FOCUS_LOST)
+ loader_->Cancel(last_full_text_);
+ else
+ loader_->Submit(last_full_text_);
+ loader_->CleanupPreviewContents();
+
+ TabContents* preview = loader_->release_preview_contents();
if (extended_enabled_) {
// Consider what's happening:
@@ -494,7 +532,7 @@ void InstantController::OmniboxLostFocus(gfx::NativeView view_gaining_focus) {
Hide(true);
#else
if (IsViewInContents(GetViewGainingFocus(view_gaining_focus),
- GetPreviewContents()->web_contents()))
+ loader_->contents()))
CommitIfCurrent(INSTANT_COMMIT_FOCUS_LOST);
else
Hide(true);
@@ -508,7 +546,7 @@ void InstantController::OmniboxGotFocus() {
if (!extended_enabled_ && !instant_enabled_)
return;
- if (!GetPreviewContents())
+ if (!client_ && !loader_)
CreateDefaultLoader();
}
@@ -531,8 +569,10 @@ void InstantController::SearchModeChanged(
Hide(true);
}
- if (GetPreviewContents())
+ if (loader_)
loader_->SearchModeChanged(new_mode);
+
+ ResetClient();
}
void InstantController::ActiveTabChanged() {
@@ -548,6 +588,9 @@ void InstantController::ActiveTabChanged() {
if (search_mode_.is_search_suggestions() &&
model_.mode().is_search_suggestions())
Hide(false);
+
+ if (extended_enabled_)
+ ResetClient();
}
void InstantController::SetInstantEnabled(bool instant_enabled) {
@@ -560,7 +603,7 @@ void InstantController::ThemeChanged(const ThemeBackgroundInfo& theme_info) {
if (!extended_enabled_)
return;
- if (GetPreviewContents())
+ if (loader_)
loader_->SendThemeBackgroundInfo(theme_info);
}
@@ -568,15 +611,15 @@ void InstantController::ThemeAreaHeightChanged(int height) {
if (!extended_enabled_)
return;
- if (GetPreviewContents())
+ if (loader_)
loader_->SendThemeAreaHeight(height);
}
void InstantController::SetSuggestions(
- InstantLoader* loader,
+ InstantClient* client,
const std::vector<InstantSuggestion>& suggestions) {
DVLOG(1) << "SetSuggestions";
- if (loader_ != loader || !search_mode_.is_search_suggestions())
+ if (client != CurrentClient() || !search_mode_.is_search_suggestions())
return;
InstantSuggestion suggestion;
@@ -659,8 +702,18 @@ void InstantController::ShowInstantPreview(InstantLoader* loader,
Show(reason, height, units);
}
-void InstantController::InstantSupportDetermined(InstantLoader* loader,
+void InstantController::InstantSupportDetermined(InstantClient* client,
bool supports_instant) {
+ if (client_ == client) {
+ if (!supports_instant) {
+ // TODO(sreeram): This should be scheduled for later deletion, but we need
+ // to disconnect the observer before doing so.
+ client_.reset();
+ }
+ return;
+ }
+
+ InstantLoader* loader = static_cast<InstantLoader*>(client);
if (supports_instant) {
blacklisted_urls_.erase(loader->instant_url());
} else {
@@ -689,16 +742,34 @@ void InstantController::InstantLoaderContentsFocused(InstantLoader* loader) {
#endif
}
+void InstantController::ResetClient() {
+ if (search_mode_.is_origin_search()) {
+ content::WebContents* contents =
+ browser_->GetActiveTabContents()->web_contents();
+ if (!client_ || contents != client_->contents()) {
+ client_.reset(new InstantClient(this, contents));
+ client_->DetermineIfPageSupportsInstant();
+ }
+ // We are now using |client_| instead of |loader_|, so Hide() the latter. We
+ // want to call Hide(true) to clear old query results on the |loader_|, but
+ // that would also clear |last_full_text_|, which is bad if the user then
+ // immediately tries to commit the query on |client_|.
+ Hide(!search_mode_.is_search_suggestions());
+ } else {
+ client_.reset();
+ }
+}
+
bool InstantController::ResetLoader(const TemplateURL* template_url,
const TabContents* active_tab) {
std::string instant_url;
if (!GetInstantURL(template_url, &instant_url))
return false;
- if (GetPreviewContents() && loader_->instant_url() != instant_url)
+ if (loader_ && loader_->instant_url() != instant_url)
DeleteLoader();
- if (!GetPreviewContents()) {
+ if (!loader_) {
loader_.reset(new InstantLoader(this, instant_url, active_tab));
loader_->Init();
@@ -735,7 +806,7 @@ void InstantController::OnStaleLoader() {
// 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() && !is_omnibox_focused_ &&
+ if (!stale_loader_timer_.IsRunning() && !is_omnibox_focused_ && !client_ &&
model_.mode().is_default()) {
DeleteLoader();
CreateDefaultLoader();
@@ -796,6 +867,9 @@ void InstantController::Hide(bool clear_query) {
void InstantController::Show(InstantShownReason reason,
int height,
InstantSizeUnits units) {
+ if (client_ == CurrentClient())
+ return;
+
DVLOG(1) << "Show: reason=" << reason << " height=" << height << " units="
<< units;
@@ -819,8 +893,8 @@ void InstantController::Show(InstantShownReason reason,
}
void InstantController::SendBoundsToPage() {
- if (last_omnibox_bounds_ == omnibox_bounds_ ||
- !GetPreviewContents() || loader_->IsPointerDownFromActivate())
+ if (last_omnibox_bounds_ == omnibox_bounds_ || !loader_ ||
+ loader_->IsPointerDownFromActivate())
return;
last_omnibox_bounds_ = omnibox_bounds_;
@@ -896,3 +970,7 @@ bool InstantController::GetInstantURL(const TemplateURL* template_url,
return true;
}
+
+InstantClient* InstantController::CurrentClient() const {
+ return client_ ? client_.get() : loader_.get();
+}

Powered by Google App Engine
This is Rietveld 408576698