summaryrefslogtreecommitdiffstats
path: root/chrome/browser/autocomplete/autocomplete_edit.cc
diff options
context:
space:
mode:
authorpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-01 16:59:11 +0000
committerpkasting@chromium.org <pkasting@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-09-01 16:59:11 +0000
commitdf772cbfe7a1b17dd7bb179c1e25780201d0b0ce (patch)
treebb2c277deb1b3ef07d04b5908e362c0ef7556478 /chrome/browser/autocomplete/autocomplete_edit.cc
parent8e0dca871966c15a08c23bfd890aad73ee3b8aa5 (diff)
downloadchromium_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.cc118
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;
}