diff options
author | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-01 16:59:11 +0000 |
---|---|---|
committer | pkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-09-01 16:59:11 +0000 |
commit | df772cbfe7a1b17dd7bb179c1e25780201d0b0ce (patch) | |
tree | bb2c277deb1b3ef07d04b5908e362c0ef7556478 /chrome/browser/autocomplete/autocomplete_edit.cc | |
parent | 8e0dca871966c15a08c23bfd890aad73ee3b8aa5 (diff) | |
download | chromium_src-df772cbfe7a1b17dd7bb179c1e25780201d0b0ce.zip chromium_src-df772cbfe7a1b17dd7bb179c1e25780201d0b0ce.tar.gz chromium_src-df772cbfe7a1b17dd7bb179c1e25780201d0b0ce.tar.bz2 |
More work fixing miscellaneous issues in the autocomplete code, probably none of which will help my crasher :(
* Force the query to stop if the user deletes a match. This makes more sense from a UI perspective and allows some code to be simpler.
* Prevent us from potentially doing a "minimal changes" match in a different profile (hard to trigger, likely no practical effects)
* Remove unneeded Reset() call on a repeating timer (which will auto-reset itself)
* Rename one of the notifications and move its listener to the edit, since that's who really cares about it anyway.
* Make the controller's Stop(true) notify the popup via the normal observer pipeline rather than coding something special into the popup's StopAutocomplete().
* Rename |paste_and_go_controller| |synchronous_controller| and use it instead of using the main popup controller to do the synchronous query when calling URLsForDefaultMatch(). This makes things both simpler and safer.
BUG=none
TEST=Using the omnibox still works fine
Review URL: http://codereview.chromium.org/178049
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@25044 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/autocomplete/autocomplete_edit.cc')
-rw-r--r-- | chrome/browser/autocomplete/autocomplete_edit.cc | 118 |
1 files changed, 96 insertions, 22 deletions
diff --git a/chrome/browser/autocomplete/autocomplete_edit.cc b/chrome/browser/autocomplete/autocomplete_edit.cc index ce78f0f..174f23c 100644 --- a/chrome/browser/autocomplete/autocomplete_edit.cc +++ b/chrome/browser/autocomplete/autocomplete_edit.cc @@ -10,6 +10,7 @@ #include "chrome/browser/autocomplete/autocomplete_popup_model.h" #include "chrome/browser/autocomplete/keyword_provider.h" #include "chrome/browser/metrics/user_metrics.h" +#include "chrome/browser/net/dns_global.h" #include "chrome/browser/net/url_fixer_upper.h" #include "chrome/browser/profile.h" #include "chrome/browser/search_engines/template_url.h" @@ -22,15 +23,13 @@ /////////////////////////////////////////////////////////////////////////////// // AutocompleteEditModel -// A single AutocompleteController used solely for making synchronous calls to -// determine how to deal with the clipboard contents for Paste And Go -// functionality. We avoid using the popup's controller here because we don't -// want to interrupt in-progress queries or modify the popup state just -// because the user right-clicked the edit. We don't need a controller for -// every edit because this will always be accessed on the main thread, so we +// A single AutocompleteController used solely for making synchronous calls. We +// avoid using the popup's controller here because we don't want to interrupt +// in-progress queries or modify the popup state. We don't need a controller +// for every edit because this will always be accessed on the main thread, so we // won't have thread-safety problems. -static AutocompleteController* paste_and_go_controller = NULL; -static int paste_and_go_controller_refcount = 0; +static AutocompleteController* synchronous_controller = NULL; +static int synchronous_controller_refcount = 0; AutocompleteEditModel::AutocompleteEditModel( AutocompleteEditView* view, @@ -48,16 +47,32 @@ AutocompleteEditModel::AutocompleteEditModel( keyword_ui_state_(NORMAL), show_search_hint_(true), profile_(profile) { - if (++paste_and_go_controller_refcount == 1) { + if (++synchronous_controller_refcount == 1) { // We don't have a controller yet, so create one. No profile is set since // we'll set this before each call to the controller. - paste_and_go_controller = new AutocompleteController(NULL); + synchronous_controller = new AutocompleteController(NULL); } } AutocompleteEditModel::~AutocompleteEditModel() { - if (--paste_and_go_controller_refcount == 0) - delete paste_and_go_controller; + if (--synchronous_controller_refcount == 0) { + delete synchronous_controller; + } else { + // This isn't really necessary, but it ensures safety if someday any + // provider does some kind of cleanup on the old profile when it gets a + // SetProfile() call. The current profile could be deleted after we return, + // so if we don't do this, the providers will be referencing a deleted + // object, and if they accessed it on the next SetProfile() call, bad things + // would happen. + synchronous_controller->SetProfile(NULL); + } +} + +void AutocompleteEditModel::SetPopupModel(AutocompletePopupModel* popup_model) { + popup_ = popup_model; + registrar_.Add(this, + NotificationType::AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED, + Source<AutocompleteController>(popup_->autocomplete_controller())); } void AutocompleteEditModel::SetProfile(Profile* profile) { @@ -198,13 +213,13 @@ bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const { paste_and_go_alternate_nav_url_ = GURL(); // Ask the controller what do do with this input. - // Setting the profile is cheap, and since there's one paste_and_go_controller + // Setting the profile is cheap, and since there's one synchronous_controller // for many tabs which may all have different profiles, it ensures we're // always using the right one. - paste_and_go_controller->SetProfile(profile_); - paste_and_go_controller->Start(text, std::wstring(), true, false, true); - DCHECK(paste_and_go_controller->done()); - const AutocompleteResult& result = paste_and_go_controller->result(); + synchronous_controller->SetProfile(profile_); + synchronous_controller->Start(text, std::wstring(), true, false, true); + DCHECK(synchronous_controller->done()); + const AutocompleteResult& result = synchronous_controller->result(); if (result.empty()) return false; @@ -527,6 +542,39 @@ bool AutocompleteEditModel::OnAfterPossibleChange(const std::wstring& new_text, return true; } +void AutocompleteEditModel::Observe(NotificationType type, + const NotificationSource& source, + const NotificationDetails& details) { + DCHECK_EQ(NotificationType::AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED, + type.value); + + std::wstring inline_autocomplete_text; + std::wstring keyword; + bool is_keyword_hint = false; + AutocompleteMatch::Type match_type = AutocompleteMatch::SEARCH_WHAT_YOU_TYPED; + const AutocompleteResult* result = + Details<const AutocompleteResult>(details).ptr(); + const AutocompleteResult::const_iterator match(result->default_match()); + if (match != result->end()) { + if ((match->inline_autocomplete_offset != std::wstring::npos) && + (match->inline_autocomplete_offset < match->fill_into_edit.length())) { + inline_autocomplete_text = + match->fill_into_edit.substr(match->inline_autocomplete_offset); + } + // Warm up DNS Prefetch Cache. + chrome_browser_net::DnsPrefetchUrl(match->destination_url); + // We could prefetch the alternate nav URL, if any, but because there + // can be many of these as a user types an initial series of characters, + // the OS DNS cache could suffer eviction problems for minimal gain. + + is_keyword_hint = popup_->GetKeywordForMatch(*match, &keyword); + match_type = match->type; + } + + OnPopupDataChanged(inline_autocomplete_text, false, keyword, is_keyword_hint, + match_type); +} + void AutocompleteEditModel::InternalSetUserText(const std::wstring& text) { user_text_ = text; just_deleted_text_ = false; @@ -550,13 +598,39 @@ std::wstring AutocompleteEditModel::UserTextFromDisplayText( GURL AutocompleteEditModel::GetURLForCurrentText( PageTransition::Type* transition, bool* is_history_what_you_typed_match, - GURL* alternate_nav_url) { + GURL* alternate_nav_url) const { return (popup_->IsOpen() || query_in_progress()) ? popup_->URLsForCurrentSelection(transition, is_history_what_you_typed_match, alternate_nav_url) : - popup_->URLsForDefaultMatch(UserTextFromDisplayText(view_->GetText()), - GetDesiredTLD(), transition, - is_history_what_you_typed_match, - alternate_nav_url); + URLsForDefaultMatch(transition, is_history_what_you_typed_match, + alternate_nav_url); +} + +GURL AutocompleteEditModel::URLsForDefaultMatch( + PageTransition::Type* transition, + bool* is_history_what_you_typed_match, + GURL* alternate_nav_url) const { + // Ask the controller what do do with this input. + // Setting the profile is cheap, and since there's one synchronous_controller + // for many tabs which may all have different profiles, it ensures we're + // always using the right one. + synchronous_controller->SetProfile(profile_); + synchronous_controller->Start(UserTextFromDisplayText(view_->GetText()), + GetDesiredTLD(), true, false, true); + CHECK(synchronous_controller->done()); + + const AutocompleteResult& result = synchronous_controller->result(); + if (result.empty()) + return GURL(); + + // Get the URLs for the default match. + const AutocompleteResult::const_iterator match = result.default_match(); + if (transition) + *transition = match->transition; + if (is_history_what_you_typed_match) + *is_history_what_you_typed_match = match->is_history_what_you_typed_match; + if (alternate_nav_url) + *alternate_nav_url = result.alternate_nav_url(); + return match->destination_url; } |