| 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 |