OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "chrome/browser/autocomplete/autocomplete_edit.h" | 5 #include "chrome/browser/autocomplete/autocomplete_edit.h" |
6 | 6 |
7 #include <string> | 7 #include <string> |
8 | 8 |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
11 #include "chrome/browser/autocomplete/autocomplete_edit_view.h" | 11 #include "chrome/browser/autocomplete/autocomplete_edit_view.h" |
12 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" | 12 #include "chrome/browser/autocomplete/autocomplete_popup_model.h" |
13 #include "chrome/browser/autocomplete/keyword_provider.h" | 13 #include "chrome/browser/autocomplete/keyword_provider.h" |
14 #include "chrome/browser/metrics/user_metrics.h" | 14 #include "chrome/browser/metrics/user_metrics.h" |
15 #include "chrome/browser/net/dns_global.h" | 15 #include "chrome/browser/net/dns_global.h" |
16 #include "chrome/browser/net/url_fixer_upper.h" | 16 #include "chrome/browser/net/url_fixer_upper.h" |
17 #include "chrome/browser/profile.h" | 17 #include "chrome/browser/profile.h" |
18 #include "chrome/browser/search_engines/template_url.h" | 18 #include "chrome/browser/search_engines/template_url.h" |
19 #include "chrome/browser/search_engines/template_url_model.h" | 19 #include "chrome/browser/search_engines/template_url_model.h" |
| 20 #include "chrome/browser/search_versus_navigate_classifier.h" |
20 #include "chrome/common/notification_service.h" | 21 #include "chrome/common/notification_service.h" |
21 #include "googleurl/src/gurl.h" | 22 #include "googleurl/src/gurl.h" |
22 #include "googleurl/src/url_util.h" | 23 #include "googleurl/src/url_util.h" |
23 #include "third_party/skia/include/core/SkBitmap.h" | 24 #include "third_party/skia/include/core/SkBitmap.h" |
24 | 25 |
25 /////////////////////////////////////////////////////////////////////////////// | 26 /////////////////////////////////////////////////////////////////////////////// |
26 // AutocompleteEditModel | 27 // AutocompleteEditModel |
27 | 28 |
28 // A single AutocompleteController used solely for making synchronous calls. We | |
29 // avoid using the popup's controller here because we don't want to interrupt | |
30 // in-progress queries or modify the popup state. We don't need a controller | |
31 // for every edit because this will always be accessed on the main thread, so we | |
32 // won't have thread-safety problems. | |
33 static AutocompleteController* synchronous_controller = NULL; | |
34 static int synchronous_controller_refcount = 0; | |
35 | |
36 AutocompleteEditModel::AutocompleteEditModel( | 29 AutocompleteEditModel::AutocompleteEditModel( |
37 AutocompleteEditView* view, | 30 AutocompleteEditView* view, |
38 AutocompleteEditController* controller, | 31 AutocompleteEditController* controller, |
39 Profile* profile) | 32 Profile* profile) |
40 : view_(view), | 33 : view_(view), |
41 popup_(NULL), | 34 popup_(NULL), |
42 controller_(controller), | 35 controller_(controller), |
43 has_focus_(false), | 36 has_focus_(false), |
44 user_input_in_progress_(false), | 37 user_input_in_progress_(false), |
45 just_deleted_text_(false), | 38 just_deleted_text_(false), |
46 has_temporary_text_(false), | 39 has_temporary_text_(false), |
47 original_keyword_ui_state_(NORMAL), | 40 original_keyword_ui_state_(NORMAL), |
48 paste_state_(NONE), | 41 paste_state_(NONE), |
49 control_key_state_(UP), | 42 control_key_state_(UP), |
50 is_keyword_hint_(false), | 43 is_keyword_hint_(false), |
51 keyword_ui_state_(NORMAL), | 44 keyword_ui_state_(NORMAL), |
52 show_search_hint_(true), | 45 show_search_hint_(true), |
53 paste_and_go_transition_(PageTransition::TYPED), | 46 paste_and_go_transition_(PageTransition::TYPED), |
54 profile_(profile) { | 47 profile_(profile) { |
55 if (++synchronous_controller_refcount == 1) { | |
56 // We don't have a controller yet, so create one. No profile is set since | |
57 // we'll set this before each call to the controller. | |
58 synchronous_controller = new AutocompleteController(NULL); | |
59 } | |
60 } | |
61 | |
62 AutocompleteEditModel::~AutocompleteEditModel() { | |
63 if (--synchronous_controller_refcount == 0) | |
64 delete synchronous_controller; | |
65 } | 48 } |
66 | 49 |
67 void AutocompleteEditModel::SetPopupModel(AutocompletePopupModel* popup_model) { | 50 void AutocompleteEditModel::SetPopupModel(AutocompletePopupModel* popup_model) { |
68 popup_ = popup_model; | 51 popup_ = popup_model; |
69 registrar_.Add(this, | 52 registrar_.Add(this, |
70 NotificationType::AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED, | 53 NotificationType::AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED, |
71 Source<AutocompleteController>(popup_->autocomplete_controller())); | 54 Source<AutocompleteController>(popup_->autocomplete_controller())); |
72 } | 55 } |
73 | 56 |
74 void AutocompleteEditModel::SetProfile(Profile* profile) { | 57 void AutocompleteEditModel::SetProfile(Profile* profile) { |
(...skipping 121 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
196 } | 179 } |
197 | 180 |
198 void AutocompleteEditModel::StartAutocomplete( | 181 void AutocompleteEditModel::StartAutocomplete( |
199 bool prevent_inline_autocomplete) const { | 182 bool prevent_inline_autocomplete) const { |
200 popup_->StartAutocomplete(user_text_, GetDesiredTLD(), | 183 popup_->StartAutocomplete(user_text_, GetDesiredTLD(), |
201 prevent_inline_autocomplete || just_deleted_text_ || | 184 prevent_inline_autocomplete || just_deleted_text_ || |
202 (paste_state_ != NONE), keyword_ui_state_ == KEYWORD); | 185 (paste_state_ != NONE), keyword_ui_state_ == KEYWORD); |
203 } | 186 } |
204 | 187 |
205 bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const { | 188 bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const { |
206 // Reset local state. | |
207 paste_and_go_url_ = GURL(); | 189 paste_and_go_url_ = GURL(); |
208 paste_and_go_transition_ = PageTransition::TYPED; | 190 paste_and_go_transition_ = PageTransition::TYPED; |
209 paste_and_go_alternate_nav_url_ = GURL(); | 191 paste_and_go_alternate_nav_url_ = GURL(); |
210 | 192 |
211 // Ask the controller what do do with this input. | 193 profile_->GetSearchVersusNavigateClassifier()->Classify(text, std::wstring(), |
212 // Setting the profile is cheap, and since there's one synchronous_controller | 194 NULL, &paste_and_go_url_, &paste_and_go_transition_, NULL, |
213 // for many tabs which may all have different profiles, it ensures we're | 195 &paste_and_go_alternate_nav_url_); |
214 // always using the right one. | |
215 synchronous_controller->SetProfile(profile_); | |
216 synchronous_controller->Start(text, std::wstring(), true, false, true); | |
217 DCHECK(synchronous_controller->done()); | |
218 const AutocompleteResult& result = synchronous_controller->result(); | |
219 if (result.empty()) | |
220 return false; | |
221 | |
222 // Set local state based on the default action for this input. | |
223 const AutocompleteResult::const_iterator match(result.default_match()); | |
224 DCHECK(match != result.end()); | |
225 paste_and_go_url_ = match->destination_url; | |
226 paste_and_go_transition_ = match->transition; | |
227 paste_and_go_alternate_nav_url_ = result.alternate_nav_url(); | |
228 | 196 |
229 return paste_and_go_url_.is_valid(); | 197 return paste_and_go_url_.is_valid(); |
230 } | 198 } |
231 | 199 |
232 void AutocompleteEditModel::PasteAndGo() { | 200 void AutocompleteEditModel::PasteAndGo() { |
233 // The final parameter to OpenURL, keyword, is not quite correct here: it's | 201 // The final parameter to OpenURL, keyword, is not quite correct here: it's |
234 // possible to "paste and go" a string that contains a keyword. This is | 202 // possible to "paste and go" a string that contains a keyword. This is |
235 // enough of an edge case that we ignore this possibility. | 203 // enough of an edge case that we ignore this possibility. |
236 view_->RevertAll(); | 204 view_->RevertAll(); |
237 view_->OpenURL(paste_and_go_url_, CURRENT_TAB, paste_and_go_transition_, | 205 view_->OpenURL(paste_and_go_url_, CURRENT_TAB, paste_and_go_transition_, |
(...skipping 355 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
593 const std::wstring& text) const { | 561 const std::wstring& text) const { |
594 return ((keyword_ui_state_ == NO_KEYWORD) || is_keyword_hint_ || | 562 return ((keyword_ui_state_ == NO_KEYWORD) || is_keyword_hint_ || |
595 keyword_.empty()) ? | 563 keyword_.empty()) ? |
596 text : (keyword_ + L" " + text); | 564 text : (keyword_ + L" " + text); |
597 } | 565 } |
598 | 566 |
599 GURL AutocompleteEditModel::GetURLForCurrentText( | 567 GURL AutocompleteEditModel::GetURLForCurrentText( |
600 PageTransition::Type* transition, | 568 PageTransition::Type* transition, |
601 bool* is_history_what_you_typed_match, | 569 bool* is_history_what_you_typed_match, |
602 GURL* alternate_nav_url) const { | 570 GURL* alternate_nav_url) const { |
603 return (popup_->IsOpen() || query_in_progress()) ? | 571 if (popup_->IsOpen() || query_in_progress()) { |
604 popup_->URLsForCurrentSelection(transition, | 572 return popup_->URLsForCurrentSelection(transition, |
605 is_history_what_you_typed_match, | 573 is_history_what_you_typed_match, |
606 alternate_nav_url) : | 574 alternate_nav_url); |
607 URLsForDefaultMatch(transition, is_history_what_you_typed_match, | 575 } |
608 alternate_nav_url); | 576 |
| 577 GURL destination_url; |
| 578 profile_->GetSearchVersusNavigateClassifier()->Classify( |
| 579 UserTextFromDisplayText(view_->GetText()), GetDesiredTLD(), NULL, |
| 580 &destination_url, transition, is_history_what_you_typed_match, |
| 581 alternate_nav_url); |
| 582 return destination_url; |
609 } | 583 } |
610 | |
611 GURL AutocompleteEditModel::URLsForDefaultMatch( | |
612 PageTransition::Type* transition, | |
613 bool* is_history_what_you_typed_match, | |
614 GURL* alternate_nav_url) const { | |
615 // Ask the controller what do do with this input. | |
616 // Setting the profile is cheap, and since there's one synchronous_controller | |
617 // for many tabs which may all have different profiles, it ensures we're | |
618 // always using the right one. | |
619 synchronous_controller->SetProfile(profile_); | |
620 synchronous_controller->Start(UserTextFromDisplayText(view_->GetText()), | |
621 GetDesiredTLD(), true, false, true); | |
622 CHECK(synchronous_controller->done()); | |
623 | |
624 const AutocompleteResult& result = synchronous_controller->result(); | |
625 if (result.empty()) | |
626 return GURL(); | |
627 | |
628 // Get the URLs for the default match. | |
629 const AutocompleteResult::const_iterator match = result.default_match(); | |
630 if (transition) | |
631 *transition = match->transition; | |
632 if (is_history_what_you_typed_match) | |
633 *is_history_what_you_typed_match = match->is_history_what_you_typed_match; | |
634 if (alternate_nav_url) | |
635 *alternate_nav_url = result.alternate_nav_url(); | |
636 return match->destination_url; | |
637 } | |
OLD | NEW |