| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2009 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/keyword_provider.h" | 5 #include "chrome/browser/autocomplete/keyword_provider.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <vector> | 8 #include <vector> |
| 9 | 9 |
| 10 #include "base/string_util.h" | 10 #include "base/string_util.h" |
| 11 #include "chrome/browser/profile.h" | 11 #include "chrome/browser/profile.h" |
| (...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 54 // always put any exact matches first no matter what, since the code in | 54 // always put any exact matches first no matter what, since the code in |
| 55 // Start() assumes this (and it makes sense). | 55 // Start() assumes this (and it makes sense). |
| 56 bool operator()(const std::wstring& keyword1, | 56 bool operator()(const std::wstring& keyword1, |
| 57 const std::wstring& keyword2) const { | 57 const std::wstring& keyword2) const { |
| 58 return keyword1.length() < keyword2.length(); | 58 return keyword1.length() < keyword2.length(); |
| 59 } | 59 } |
| 60 }; | 60 }; |
| 61 | 61 |
| 62 } // namespace | 62 } // namespace |
| 63 | 63 |
| 64 // static |
| 65 const TemplateURL* KeywordProvider::GetSubstitutingTemplateURLForInput( |
| 66 Profile* profile, |
| 67 const AutocompleteInput& input, |
| 68 std::wstring* remaining_input) { |
| 69 std::wstring keyword; |
| 70 if (!ExtractKeywordFromInput(input, &keyword, remaining_input)) |
| 71 return NULL; |
| 72 |
| 73 // Make sure the model is loaded. This is cheap and quickly bails out if |
| 74 // the model is already loaded. |
| 75 TemplateURLModel* model = profile->GetTemplateURLModel(); |
| 76 DCHECK(model); |
| 77 model->Load(); |
| 78 |
| 79 const TemplateURL* template_url = model->GetTemplateURLForKeyword(keyword); |
| 80 return TemplateURL::SupportsReplacement(template_url) ? template_url : NULL; |
| 81 } |
| 82 |
| 64 void KeywordProvider::Start(const AutocompleteInput& input, | 83 void KeywordProvider::Start(const AutocompleteInput& input, |
| 65 bool minimal_changes) { | 84 bool minimal_changes) { |
| 66 matches_.clear(); | 85 matches_.clear(); |
| 67 | 86 |
| 68 if ((input.type() == AutocompleteInput::INVALID) || | |
| 69 (input.type() == AutocompleteInput::FORCED_QUERY)) | |
| 70 return; | |
| 71 | |
| 72 // Split user input into a keyword and some query input. | 87 // Split user input into a keyword and some query input. |
| 73 // | 88 // |
| 74 // We want to suggest keywords even when users have started typing URLs, on | 89 // We want to suggest keywords even when users have started typing URLs, on |
| 75 // the assumption that they might not realize they no longer need to go to a | 90 // the assumption that they might not realize they no longer need to go to a |
| 76 // site to be able to search it. So we call CleanUserInputKeyword() to strip | 91 // site to be able to search it. So we call CleanUserInputKeyword() to strip |
| 77 // any initial scheme and/or "www.". NOTE: Any heuristics or UI used to | 92 // any initial scheme and/or "www.". NOTE: Any heuristics or UI used to |
| 78 // automatically/manually create keywords will need to be in sync with | 93 // automatically/manually create keywords will need to be in sync with |
| 79 // whatever we do here! | 94 // whatever we do here! |
| 80 // | 95 // |
| 81 // TODO(pkasting): http://b/1112681 If someday we remember usage frequency for | 96 // TODO(pkasting): http://b/1112681 If someday we remember usage frequency for |
| 82 // keywords, we might suggest keywords that haven't even been partially typed, | 97 // keywords, we might suggest keywords that haven't even been partially typed, |
| 83 // if the user uses them enough and isn't obviously typing something else. In | 98 // if the user uses them enough and isn't obviously typing something else. In |
| 84 // this case we'd consider all input here to be query input. | 99 // this case we'd consider all input here to be query input. |
| 85 std::wstring remaining_input; | 100 std::wstring keyword, remaining_input; |
| 86 std::wstring keyword(TemplateURLModel::CleanUserInputKeyword( | 101 if (!ExtractKeywordFromInput(input, &keyword, &remaining_input)) |
| 87 SplitKeywordFromInput(input.text(), &remaining_input))); | |
| 88 if (keyword.empty()) | |
| 89 return; | 102 return; |
| 90 | 103 |
| 91 // Make sure the model is loaded. This is cheap and quickly bails out if | 104 // Make sure the model is loaded. This is cheap and quickly bails out if |
| 92 // the model is already loaded. | 105 // the model is already loaded. |
| 93 TemplateURLModel* model = profile_ ? profile_->GetTemplateURLModel() : model_; | 106 TemplateURLModel* model = profile_ ? profile_->GetTemplateURLModel() : model_; |
| 94 DCHECK(model); | 107 DCHECK(model); |
| 95 model->Load(); | 108 model->Load(); |
| 96 | 109 |
| 97 // Get the best matches for this keyword. | 110 // Get the best matches for this keyword. |
| 98 // | 111 // |
| (...skipping 28 matching lines...) Expand all Loading... |
| 127 for (std::vector<std::wstring>::const_iterator i(keyword_matches.begin()); | 140 for (std::vector<std::wstring>::const_iterator i(keyword_matches.begin()); |
| 128 i != keyword_matches.end(); ++i) { | 141 i != keyword_matches.end(); ++i) { |
| 129 matches_.push_back(CreateAutocompleteMatch(model, *i, input, | 142 matches_.push_back(CreateAutocompleteMatch(model, *i, input, |
| 130 keyword.length(), | 143 keyword.length(), |
| 131 remaining_input)); | 144 remaining_input)); |
| 132 } | 145 } |
| 133 } | 146 } |
| 134 } | 147 } |
| 135 | 148 |
| 136 // static | 149 // static |
| 150 bool KeywordProvider::ExtractKeywordFromInput(const AutocompleteInput& input, |
| 151 std::wstring* keyword, |
| 152 std::wstring* remaining_input) { |
| 153 if ((input.type() == AutocompleteInput::INVALID) || |
| 154 (input.type() == AutocompleteInput::FORCED_QUERY)) |
| 155 return false; |
| 156 |
| 157 *keyword = TemplateURLModel::CleanUserInputKeyword( |
| 158 SplitKeywordFromInput(input.text(), remaining_input)); |
| 159 return !keyword->empty(); |
| 160 } |
| 161 |
| 162 // static |
| 137 std::wstring KeywordProvider::SplitKeywordFromInput( | 163 std::wstring KeywordProvider::SplitKeywordFromInput( |
| 138 const std::wstring& input, | 164 const std::wstring& input, |
| 139 std::wstring* remaining_input) { | 165 std::wstring* remaining_input) { |
| 140 // Find end of first token. The AutocompleteController has trimmed leading | 166 // Find end of first token. The AutocompleteController has trimmed leading |
| 141 // whitespace, so we need not skip over that. | 167 // whitespace, so we need not skip over that. |
| 142 const size_t first_white(input.find_first_of(kWhitespaceWide)); | 168 const size_t first_white(input.find_first_of(kWhitespaceWide)); |
| 143 DCHECK(first_white != 0); | 169 DCHECK(first_white != 0); |
| 144 if (first_white == std::wstring::npos) | 170 if (first_white == std::wstring::npos) |
| 145 return input; // Only one token provided. | 171 return input; // Only one token provided. |
| 146 | 172 |
| (...skipping 128 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 275 prefix_length, | 301 prefix_length, |
| 276 result.description.length(), | 302 result.description.length(), |
| 277 ACMatchClassification::DIM, | 303 ACMatchClassification::DIM, |
| 278 &result.description_class); | 304 &result.description_class); |
| 279 | 305 |
| 280 // Keyword searches don't look like URLs. | 306 // Keyword searches don't look like URLs. |
| 281 result.transition = PageTransition::GENERATED; | 307 result.transition = PageTransition::GENERATED; |
| 282 | 308 |
| 283 return result; | 309 return result; |
| 284 } | 310 } |
| OLD | NEW |