| OLD | NEW |
| 1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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/metrics/histogram.h" | 10 #include "base/metrics/histogram.h" |
| (...skipping 25 matching lines...) Expand all Loading... |
| 36 /////////////////////////////////////////////////////////////////////////////// | 36 /////////////////////////////////////////////////////////////////////////////// |
| 37 // AutocompleteEditController | 37 // AutocompleteEditController |
| 38 | 38 |
| 39 AutocompleteEditController::~AutocompleteEditController() { | 39 AutocompleteEditController::~AutocompleteEditController() { |
| 40 } | 40 } |
| 41 | 41 |
| 42 /////////////////////////////////////////////////////////////////////////////// | 42 /////////////////////////////////////////////////////////////////////////////// |
| 43 // AutocompleteEditModel::State | 43 // AutocompleteEditModel::State |
| 44 | 44 |
| 45 AutocompleteEditModel::State::State(bool user_input_in_progress, | 45 AutocompleteEditModel::State::State(bool user_input_in_progress, |
| 46 const string16& user_text, | 46 const std::wstring& user_text, |
| 47 const string16& keyword, | 47 const std::wstring& keyword, |
| 48 bool is_keyword_hint) | 48 bool is_keyword_hint) |
| 49 : user_input_in_progress(user_input_in_progress), | 49 : user_input_in_progress(user_input_in_progress), |
| 50 user_text(user_text), | 50 user_text(user_text), |
| 51 keyword(keyword), | 51 keyword(keyword), |
| 52 is_keyword_hint(is_keyword_hint) { | 52 is_keyword_hint(is_keyword_hint) { |
| 53 } | 53 } |
| 54 | 54 |
| 55 AutocompleteEditModel::State::~State() { | 55 AutocompleteEditModel::State::~State() { |
| 56 } | 56 } |
| 57 | 57 |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 94 | 94 |
| 95 const AutocompleteEditModel::State | 95 const AutocompleteEditModel::State |
| 96 AutocompleteEditModel::GetStateForTabSwitch() { | 96 AutocompleteEditModel::GetStateForTabSwitch() { |
| 97 // Like typing, switching tabs "accepts" the temporary text as the user | 97 // Like typing, switching tabs "accepts" the temporary text as the user |
| 98 // text, because it makes little sense to have temporary text when the | 98 // text, because it makes little sense to have temporary text when the |
| 99 // popup is closed. | 99 // popup is closed. |
| 100 if (user_input_in_progress_) { | 100 if (user_input_in_progress_) { |
| 101 // Weird edge case to match other browsers: if the edit is empty, revert to | 101 // Weird edge case to match other browsers: if the edit is empty, revert to |
| 102 // the permanent text (so the user can get it back easily) but select it (so | 102 // the permanent text (so the user can get it back easily) but select it (so |
| 103 // on switching back, typing will "just work"). | 103 // on switching back, typing will "just work"). |
| 104 const string16 user_text(UserTextFromDisplayText(view_->GetText())); | 104 const std::wstring user_text(UserTextFromDisplayText(view_->GetText())); |
| 105 if (user_text.empty()) { | 105 if (user_text.empty()) { |
| 106 view_->RevertAll(); | 106 view_->RevertAll(); |
| 107 view_->SelectAll(true); | 107 view_->SelectAll(true); |
| 108 } else { | 108 } else { |
| 109 InternalSetUserText(user_text); | 109 InternalSetUserText(user_text); |
| 110 } | 110 } |
| 111 } | 111 } |
| 112 | 112 |
| 113 return State(user_input_in_progress_, user_text_, keyword_, is_keyword_hint_); | 113 return State(user_input_in_progress_, user_text_, keyword_, is_keyword_hint_); |
| 114 } | 114 } |
| (...skipping 10 matching lines...) Expand all Loading... |
| 125 } | 125 } |
| 126 } | 126 } |
| 127 | 127 |
| 128 AutocompleteMatch AutocompleteEditModel::CurrentMatch() { | 128 AutocompleteMatch AutocompleteEditModel::CurrentMatch() { |
| 129 AutocompleteMatch match; | 129 AutocompleteMatch match; |
| 130 GetInfoForCurrentText(&match, NULL); | 130 GetInfoForCurrentText(&match, NULL); |
| 131 return match; | 131 return match; |
| 132 } | 132 } |
| 133 | 133 |
| 134 bool AutocompleteEditModel::UpdatePermanentText( | 134 bool AutocompleteEditModel::UpdatePermanentText( |
| 135 const string16& new_permanent_text) { | 135 const std::wstring& new_permanent_text) { |
| 136 // When there's a new URL, and the user is not editing anything or the edit | 136 // When there's a new URL, and the user is not editing anything or the edit |
| 137 // doesn't have focus, we want to revert the edit to show the new URL. (The | 137 // doesn't have focus, we want to revert the edit to show the new URL. (The |
| 138 // common case where the edit doesn't have focus is when the user has started | 138 // common case where the edit doesn't have focus is when the user has started |
| 139 // an edit and then abandoned it and clicked a link on the page.) | 139 // an edit and then abandoned it and clicked a link on the page.) |
| 140 const bool visibly_changed_permanent_text = | 140 const bool visibly_changed_permanent_text = |
| 141 (permanent_text_ != new_permanent_text) && | 141 (permanent_text_ != new_permanent_text) && |
| 142 (!user_input_in_progress_ || !has_focus_); | 142 (!user_input_in_progress_ || !has_focus_); |
| 143 | 143 |
| 144 permanent_text_ = new_permanent_text; | 144 permanent_text_ = new_permanent_text; |
| 145 return visibly_changed_permanent_text; | 145 return visibly_changed_permanent_text; |
| 146 } | 146 } |
| 147 | 147 |
| 148 void AutocompleteEditModel::SetUserText(const string16& text) { | 148 void AutocompleteEditModel::SetUserText(const std::wstring& text) { |
| 149 SetInputInProgress(true); | 149 SetInputInProgress(true); |
| 150 InternalSetUserText(text); | 150 InternalSetUserText(text); |
| 151 paste_state_ = NONE; | 151 paste_state_ = NONE; |
| 152 has_temporary_text_ = false; | 152 has_temporary_text_ = false; |
| 153 } | 153 } |
| 154 | 154 |
| 155 void AutocompleteEditModel::FinalizeInstantQuery( | 155 void AutocompleteEditModel::FinalizeInstantQuery( |
| 156 const string16& input_text, | 156 const std::wstring& input_text, |
| 157 const string16& suggest_text) { | 157 const std::wstring& suggest_text) { |
| 158 popup_->FinalizeInstantQuery(input_text, suggest_text); | 158 popup_->FinalizeInstantQuery(input_text, suggest_text); |
| 159 } | 159 } |
| 160 | 160 |
| 161 void AutocompleteEditModel::GetDataForURLExport(GURL* url, | 161 void AutocompleteEditModel::GetDataForURLExport(GURL* url, |
| 162 string16* title, | 162 std::wstring* title, |
| 163 SkBitmap* favicon) { | 163 SkBitmap* favicon) { |
| 164 AutocompleteMatch match; | 164 AutocompleteMatch match; |
| 165 GetInfoForCurrentText(&match, NULL); | 165 GetInfoForCurrentText(&match, NULL); |
| 166 *url = match.destination_url; | 166 *url = match.destination_url; |
| 167 if (*url == URLFixerUpper::FixupURL(UTF16ToUTF8(permanent_text_), | 167 if (*url == URLFixerUpper::FixupURL(WideToUTF8(permanent_text_), |
| 168 std::string())) { | 168 std::string())) { |
| 169 *title = controller_->GetTitle(); | 169 *title = controller_->GetTitle(); |
| 170 *favicon = controller_->GetFavIcon(); | 170 *favicon = controller_->GetFavIcon(); |
| 171 } | 171 } |
| 172 } | 172 } |
| 173 | 173 |
| 174 bool AutocompleteEditModel::UseVerbatimInstant() { | 174 bool AutocompleteEditModel::UseVerbatimInstant() { |
| 175 #if defined(OS_MACOSX) | 175 #if defined(OS_MACOSX) |
| 176 // TODO(suzhe): Fix Mac port to display Instant suggest in a separated NSView, | 176 // TODO(suzhe): Fix Mac port to display Instant suggest in a separated NSView, |
| 177 // so that we can display instant suggest along with composition text. | 177 // so that we can display instant suggest along with composition text. |
| 178 const AutocompleteInput& input = popup_->autocomplete_controller()->input(); | 178 const AutocompleteInput& input = popup_->autocomplete_controller()->input(); |
| 179 if (input.initial_prevent_inline_autocomplete()) | 179 if (input.initial_prevent_inline_autocomplete()) |
| 180 return true; | 180 return true; |
| 181 #endif | 181 #endif |
| 182 | 182 |
| 183 // The value of input.initial_prevent_inline_autocomplete() is determined by | 183 // The value of input.initial_prevent_inline_autocomplete() is determined by |
| 184 // following conditions: | 184 // following conditions: |
| 185 // 1. If the caret is at the end of the text (checked below). | 185 // 1. If the caret is at the end of the text (checked below). |
| 186 // 2. If it's in IME composition mode. | 186 // 2. If it's in IME composition mode. |
| 187 // As we use a separated widget for displaying the instant suggest, it won't | 187 // As we use a separated widget for displaying the instant suggest, it won't |
| 188 // interfere with IME composition, so we don't need to care about the value of | 188 // interfere with IME composition, so we don't need to care about the value of |
| 189 // input.initial_prevent_inline_autocomplete() here. | 189 // input.initial_prevent_inline_autocomplete() here. |
| 190 if (view_->DeleteAtEndPressed() || (popup_->selected_line() != 0) || | 190 if (view_->DeleteAtEndPressed() || (popup_->selected_line() != 0) || |
| 191 just_deleted_text_) | 191 just_deleted_text_) |
| 192 return true; | 192 return true; |
| 193 | 193 |
| 194 string16::size_type start, end; | 194 std::wstring::size_type start, end; |
| 195 view_->GetSelectionBounds(&start, &end); | 195 view_->GetSelectionBounds(&start, &end); |
| 196 return (start != end) || (start != view_->GetText().size()); | 196 return (start != end) || (start != view_->GetText().size()); |
| 197 } | 197 } |
| 198 | 198 |
| 199 string16 AutocompleteEditModel::GetDesiredTLD() const { | 199 std::wstring AutocompleteEditModel::GetDesiredTLD() const { |
| 200 // Tricky corner case: The user has typed "foo" and currently sees an inline | 200 // Tricky corner case: The user has typed "foo" and currently sees an inline |
| 201 // autocomplete suggestion of "foo.net". He now presses ctrl-a (e.g. to | 201 // autocomplete suggestion of "foo.net". He now presses ctrl-a (e.g. to |
| 202 // select all, on Windows). If we treat the ctrl press as potentially for the | 202 // select all, on Windows). If we treat the ctrl press as potentially for the |
| 203 // sake of ctrl-enter, then we risk "www.foo.com" being promoted as the best | 203 // sake of ctrl-enter, then we risk "www.foo.com" being promoted as the best |
| 204 // match. This would make the autocompleted text disappear, leaving our user | 204 // match. This would make the autocompleted text disappear, leaving our user |
| 205 // feeling very confused when the wrong text gets highlighted. | 205 // feeling very confused when the wrong text gets highlighted. |
| 206 // | 206 // |
| 207 // Thus, we only treat the user as pressing ctrl-enter when the user presses | 207 // Thus, we only treat the user as pressing ctrl-enter when the user presses |
| 208 // ctrl without any fragile state built up in the omnibox: | 208 // ctrl without any fragile state built up in the omnibox: |
| 209 // * the contents of the omnibox have not changed since the keypress, | 209 // * the contents of the omnibox have not changed since the keypress, |
| 210 // * there is no autocompleted text visible, and | 210 // * there is no autocompleted text visible, and |
| 211 // * the user is not typing a keyword query. | 211 // * the user is not typing a keyword query. |
| 212 return (control_key_state_ == DOWN_WITHOUT_CHANGE && | 212 return (control_key_state_ == DOWN_WITHOUT_CHANGE && |
| 213 inline_autocomplete_text_.empty() && !KeywordIsSelected())? | 213 inline_autocomplete_text_.empty() && !KeywordIsSelected())? |
| 214 ASCIIToUTF16("com") : string16(); | 214 std::wstring(L"com") : std::wstring(); |
| 215 } | 215 } |
| 216 | 216 |
| 217 bool AutocompleteEditModel::CurrentTextIsURL() const { | 217 bool AutocompleteEditModel::CurrentTextIsURL() const { |
| 218 // If !user_input_in_progress_, the permanent text is showing, which should | 218 // If !user_input_in_progress_, the permanent text is showing, which should |
| 219 // always be a URL, so no further checking is needed. By avoiding checking in | 219 // always be a URL, so no further checking is needed. By avoiding checking in |
| 220 // this case, we avoid calling into the autocomplete providers, and thus | 220 // this case, we avoid calling into the autocomplete providers, and thus |
| 221 // initializing the history system, as long as possible, which speeds startup. | 221 // initializing the history system, as long as possible, which speeds startup. |
| 222 if (!user_input_in_progress_) | 222 if (!user_input_in_progress_) |
| 223 return true; | 223 return true; |
| 224 | 224 |
| 225 AutocompleteMatch match; | 225 AutocompleteMatch match; |
| 226 GetInfoForCurrentText(&match, NULL); | 226 GetInfoForCurrentText(&match, NULL); |
| 227 return match.transition == PageTransition::TYPED; | 227 return match.transition == PageTransition::TYPED; |
| 228 } | 228 } |
| 229 | 229 |
| 230 AutocompleteMatch::Type AutocompleteEditModel::CurrentTextType() const { | 230 AutocompleteMatch::Type AutocompleteEditModel::CurrentTextType() const { |
| 231 AutocompleteMatch match; | 231 AutocompleteMatch match; |
| 232 GetInfoForCurrentText(&match, NULL); | 232 GetInfoForCurrentText(&match, NULL); |
| 233 return match.type; | 233 return match.type; |
| 234 } | 234 } |
| 235 | 235 |
| 236 void AutocompleteEditModel::AdjustTextForCopy(int sel_min, | 236 void AutocompleteEditModel::AdjustTextForCopy(int sel_min, |
| 237 bool is_all_selected, | 237 bool is_all_selected, |
| 238 string16* text, | 238 std::wstring* text, |
| 239 GURL* url, | 239 GURL* url, |
| 240 bool* write_url) { | 240 bool* write_url) { |
| 241 *write_url = false; | 241 *write_url = false; |
| 242 | 242 |
| 243 if (sel_min != 0) | 243 if (sel_min != 0) |
| 244 return; | 244 return; |
| 245 | 245 |
| 246 // We can't use CurrentTextIsURL() or GetDataForURLExport() because right now | 246 // We can't use CurrentTextIsURL() or GetDataForURLExport() because right now |
| 247 // the user is probably holding down control to cause the copy, which will | 247 // the user is probably holding down control to cause the copy, which will |
| 248 // screw up our calculation of the desired_tld. | 248 // screw up our calculation of the desired_tld. |
| 249 if (!GetURLForText(*text, url)) | 249 if (!GetURLForText(*text, url)) |
| 250 return; // Can't be parsed as a url, no need to adjust text. | 250 return; // Can't be parsed as a url, no need to adjust text. |
| 251 | 251 |
| 252 if (!user_input_in_progress() && is_all_selected) { | 252 if (!user_input_in_progress() && is_all_selected) { |
| 253 // The user selected all the text and has not edited it. Use the url as the | 253 // The user selected all the text and has not edited it. Use the url as the |
| 254 // text so that if the scheme was stripped it's added back, and the url | 254 // text so that if the scheme was stripped it's added back, and the url |
| 255 // is unescaped (we escape parts of the url for display). | 255 // is unescaped (we escape parts of the url for display). |
| 256 *text = UTF8ToUTF16(url->spec()); | 256 *text = UTF8ToWide(url->spec()); |
| 257 *write_url = true; | 257 *write_url = true; |
| 258 return; | 258 return; |
| 259 } | 259 } |
| 260 | 260 |
| 261 // Prefix the text with 'http://' if the text doesn't start with 'http://', | 261 // Prefix the text with 'http://' if the text doesn't start with 'http://', |
| 262 // the text parses as a url with a scheme of http, the user selected the | 262 // the text parses as a url with a scheme of http, the user selected the |
| 263 // entire host, and the user hasn't edited the host or manually removed the | 263 // entire host, and the user hasn't edited the host or manually removed the |
| 264 // scheme. | 264 // scheme. |
| 265 GURL perm_url; | 265 GURL perm_url; |
| 266 if (GetURLForText(permanent_text_, &perm_url) && | 266 if (GetURLForText(permanent_text_, &perm_url) && |
| 267 perm_url.SchemeIs(chrome::kHttpScheme) && | 267 perm_url.SchemeIs(chrome::kHttpScheme) && |
| 268 url->SchemeIs(chrome::kHttpScheme) && | 268 url->SchemeIs(chrome::kHttpScheme) && |
| 269 perm_url.host() == url->host()) { | 269 perm_url.host() == url->host()) { |
| 270 *write_url = true; | 270 *write_url = true; |
| 271 | 271 |
| 272 string16 http = ASCIIToUTF16(chrome::kHttpScheme) + | 272 std::wstring http = ASCIIToWide(chrome::kHttpScheme) + |
| 273 ASCIIToUTF16(chrome::kStandardSchemeSeparator); | 273 ASCIIToWide(chrome::kStandardSchemeSeparator); |
| 274 if (text->compare(0, http.length(), http) != 0) | 274 if (text->compare(0, http.length(), http) != 0) |
| 275 *text = http + *text; | 275 *text = http + *text; |
| 276 } | 276 } |
| 277 } | 277 } |
| 278 | 278 |
| 279 void AutocompleteEditModel::SetInputInProgress(bool in_progress) { | 279 void AutocompleteEditModel::SetInputInProgress(bool in_progress) { |
| 280 if (user_input_in_progress_ == in_progress) | 280 if (user_input_in_progress_ == in_progress) |
| 281 return; | 281 return; |
| 282 | 282 |
| 283 user_input_in_progress_ = in_progress; | 283 user_input_in_progress_ = in_progress; |
| 284 controller_->OnInputInProgress(in_progress); | 284 controller_->OnInputInProgress(in_progress); |
| 285 } | 285 } |
| 286 | 286 |
| 287 void AutocompleteEditModel::Revert() { | 287 void AutocompleteEditModel::Revert() { |
| 288 SetInputInProgress(false); | 288 SetInputInProgress(false); |
| 289 paste_state_ = NONE; | 289 paste_state_ = NONE; |
| 290 InternalSetUserText(string16()); | 290 InternalSetUserText(std::wstring()); |
| 291 keyword_.clear(); | 291 keyword_.clear(); |
| 292 is_keyword_hint_ = false; | 292 is_keyword_hint_ = false; |
| 293 has_temporary_text_ = false; | 293 has_temporary_text_ = false; |
| 294 view_->SetWindowTextAndCaretPos(permanent_text_, | 294 view_->SetWindowTextAndCaretPos(permanent_text_, |
| 295 has_focus_ ? permanent_text_.length() : 0); | 295 has_focus_ ? permanent_text_.length() : 0); |
| 296 } | 296 } |
| 297 | 297 |
| 298 void AutocompleteEditModel::StartAutocomplete( | 298 void AutocompleteEditModel::StartAutocomplete( |
| 299 bool has_selected_text, | 299 bool has_selected_text, |
| 300 bool prevent_inline_autocomplete) const { | 300 bool prevent_inline_autocomplete) const { |
| 301 bool keyword_is_selected = KeywordIsSelected(); | 301 bool keyword_is_selected = KeywordIsSelected(); |
| 302 popup_->StartAutocomplete(user_text_, GetDesiredTLD(), | 302 popup_->StartAutocomplete(user_text_, GetDesiredTLD(), |
| 303 prevent_inline_autocomplete || just_deleted_text_ || | 303 prevent_inline_autocomplete || just_deleted_text_ || |
| 304 (has_selected_text && inline_autocomplete_text_.empty()) || | 304 (has_selected_text && inline_autocomplete_text_.empty()) || |
| 305 (paste_state_ != NONE), keyword_is_selected, keyword_is_selected); | 305 (paste_state_ != NONE), keyword_is_selected, keyword_is_selected); |
| 306 } | 306 } |
| 307 | 307 |
| 308 bool AutocompleteEditModel::CanPasteAndGo(const string16& text) const { | 308 bool AutocompleteEditModel::CanPasteAndGo(const std::wstring& text) const { |
| 309 if (!view_->GetCommandUpdater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) | 309 if (!view_->GetCommandUpdater()->IsCommandEnabled(IDC_OPEN_CURRENT_URL)) |
| 310 return false; | 310 return false; |
| 311 | 311 |
| 312 AutocompleteMatch match; | 312 AutocompleteMatch match; |
| 313 profile_->GetAutocompleteClassifier()->Classify(text, string16(), false, | 313 profile_->GetAutocompleteClassifier()->Classify(text, std::wstring(), false, |
| 314 &match, &paste_and_go_alternate_nav_url_); | 314 &match, &paste_and_go_alternate_nav_url_); |
| 315 paste_and_go_url_ = match.destination_url; | 315 paste_and_go_url_ = match.destination_url; |
| 316 paste_and_go_transition_ = match.transition; | 316 paste_and_go_transition_ = match.transition; |
| 317 return paste_and_go_url_.is_valid(); | 317 return paste_and_go_url_.is_valid(); |
| 318 } | 318 } |
| 319 | 319 |
| 320 void AutocompleteEditModel::PasteAndGo() { | 320 void AutocompleteEditModel::PasteAndGo() { |
| 321 // The final parameter to OpenURL, keyword, is not quite correct here: it's | 321 // The final parameter to OpenURL, keyword, is not quite correct here: it's |
| 322 // possible to "paste and go" a string that contains a keyword. This is | 322 // possible to "paste and go" a string that contains a keyword. This is |
| 323 // enough of an edge case that we ignore this possibility. | 323 // enough of an edge case that we ignore this possibility. |
| 324 view_->RevertAll(); | 324 view_->RevertAll(); |
| 325 view_->OpenURL(paste_and_go_url_, CURRENT_TAB, paste_and_go_transition_, | 325 view_->OpenURL(paste_and_go_url_, CURRENT_TAB, paste_and_go_transition_, |
| 326 paste_and_go_alternate_nav_url_, AutocompletePopupModel::kNoMatch, | 326 paste_and_go_alternate_nav_url_, AutocompletePopupModel::kNoMatch, |
| 327 string16()); | 327 std::wstring()); |
| 328 } | 328 } |
| 329 | 329 |
| 330 void AutocompleteEditModel::AcceptInput(WindowOpenDisposition disposition, | 330 void AutocompleteEditModel::AcceptInput(WindowOpenDisposition disposition, |
| 331 bool for_drop) { | 331 bool for_drop) { |
| 332 // Get the URL and transition type for the selected entry. | 332 // Get the URL and transition type for the selected entry. |
| 333 AutocompleteMatch match; | 333 AutocompleteMatch match; |
| 334 GURL alternate_nav_url; | 334 GURL alternate_nav_url; |
| 335 GetInfoForCurrentText(&match, &alternate_nav_url); | 335 GetInfoForCurrentText(&match, &alternate_nav_url); |
| 336 | 336 |
| 337 if (!match.destination_url.is_valid()) | 337 if (!match.destination_url.is_valid()) |
| 338 return; | 338 return; |
| 339 | 339 |
| 340 if ((match.transition == PageTransition::TYPED) && (match.destination_url == | 340 if ((match.transition == PageTransition::TYPED) && (match.destination_url == |
| 341 URLFixerUpper::FixupURL(UTF16ToUTF8(permanent_text_), std::string()))) { | 341 URLFixerUpper::FixupURL(WideToUTF8(permanent_text_), std::string()))) { |
| 342 // When the user hit enter on the existing permanent URL, treat it like a | 342 // When the user hit enter on the existing permanent URL, treat it like a |
| 343 // reload for scoring purposes. We could detect this by just checking | 343 // reload for scoring purposes. We could detect this by just checking |
| 344 // user_input_in_progress_, but it seems better to treat "edits" that end | 344 // user_input_in_progress_, but it seems better to treat "edits" that end |
| 345 // up leaving the URL unchanged (e.g. deleting the last character and then | 345 // up leaving the URL unchanged (e.g. deleting the last character and then |
| 346 // retyping it) as reloads too. We exclude non-TYPED transitions because if | 346 // retyping it) as reloads too. We exclude non-TYPED transitions because if |
| 347 // the transition is GENERATED, the user input something that looked | 347 // the transition is GENERATED, the user input something that looked |
| 348 // different from the current URL, even if it wound up at the same place | 348 // different from the current URL, even if it wound up at the same place |
| 349 // (e.g. manually retyping the same search query), and it seems wrong to | 349 // (e.g. manually retyping the same search query), and it seems wrong to |
| 350 // treat this as a reload. | 350 // treat this as a reload. |
| 351 match.transition = PageTransition::RELOAD; | 351 match.transition = PageTransition::RELOAD; |
| 352 } else if (for_drop || ((paste_state_ != NONE) && | 352 } else if (for_drop || ((paste_state_ != NONE) && |
| 353 match.is_history_what_you_typed_match)) { | 353 match.is_history_what_you_typed_match)) { |
| 354 // When the user pasted in a URL and hit enter, score it like a link click | 354 // When the user pasted in a URL and hit enter, score it like a link click |
| 355 // rather than a normal typed URL, so it doesn't get inline autocompleted | 355 // rather than a normal typed URL, so it doesn't get inline autocompleted |
| 356 // as aggressively later. | 356 // as aggressively later. |
| 357 match.transition = PageTransition::LINK; | 357 match.transition = PageTransition::LINK; |
| 358 } | 358 } |
| 359 | 359 |
| 360 if (match.type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED || | 360 if (match.type == AutocompleteMatch::SEARCH_WHAT_YOU_TYPED || |
| 361 match.type == AutocompleteMatch::SEARCH_HISTORY || | 361 match.type == AutocompleteMatch::SEARCH_HISTORY || |
| 362 match.type == AutocompleteMatch::SEARCH_SUGGEST) { | 362 match.type == AutocompleteMatch::SEARCH_SUGGEST) { |
| 363 const TemplateURL* default_provider = | 363 const TemplateURL* default_provider = |
| 364 profile_->GetTemplateURLModel()->GetDefaultSearchProvider(); | 364 profile_->GetTemplateURLModel()->GetDefaultSearchProvider(); |
| 365 if (default_provider && default_provider->url() && | 365 if (default_provider && default_provider->url() && |
| 366 default_provider->url()->HasGoogleBaseURLs()) | 366 default_provider->url()->HasGoogleBaseURLs()) |
| 367 GoogleURLTracker::GoogleURLSearchCommitted(); | 367 GoogleURLTracker::GoogleURLSearchCommitted(); |
| 368 } | 368 } |
| 369 view_->OpenURL(match.destination_url, disposition, match.transition, | 369 view_->OpenURL(match.destination_url, disposition, match.transition, |
| 370 alternate_nav_url, AutocompletePopupModel::kNoMatch, | 370 alternate_nav_url, AutocompletePopupModel::kNoMatch, |
| 371 is_keyword_hint_ ? string16() : keyword_); | 371 is_keyword_hint_ ? std::wstring() : keyword_); |
| 372 } | 372 } |
| 373 | 373 |
| 374 void AutocompleteEditModel::OpenURL(const GURL& url, | 374 void AutocompleteEditModel::OpenURL(const GURL& url, |
| 375 WindowOpenDisposition disposition, | 375 WindowOpenDisposition disposition, |
| 376 PageTransition::Type transition, | 376 PageTransition::Type transition, |
| 377 const GURL& alternate_nav_url, | 377 const GURL& alternate_nav_url, |
| 378 size_t index, | 378 size_t index, |
| 379 const string16& keyword) { | 379 const std::wstring& keyword) { |
| 380 // We only care about cases where there is a selection (i.e. the popup is | 380 // We only care about cases where there is a selection (i.e. the popup is |
| 381 // open). | 381 // open). |
| 382 if (popup_->IsOpen()) { | 382 if (popup_->IsOpen()) { |
| 383 scoped_ptr<AutocompleteLog> log(popup_->GetAutocompleteLog()); | 383 scoped_ptr<AutocompleteLog> log(popup_->GetAutocompleteLog()); |
| 384 if (index != AutocompletePopupModel::kNoMatch) | 384 if (index != AutocompletePopupModel::kNoMatch) |
| 385 log->selected_index = index; | 385 log->selected_index = index; |
| 386 else if (!has_temporary_text_) | 386 else if (!has_temporary_text_) |
| 387 log->inline_autocompleted_length = inline_autocomplete_text_.length(); | 387 log->inline_autocompleted_length = inline_autocomplete_text_.length(); |
| 388 NotificationService::current()->Notify( | 388 NotificationService::current()->Notify( |
| 389 NotificationType::OMNIBOX_OPENED_URL, Source<Profile>(profile_), | 389 NotificationType::OMNIBOX_OPENED_URL, Source<Profile>(profile_), |
| 390 Details<AutocompleteLog>(log.get())); | 390 Details<AutocompleteLog>(log.get())); |
| 391 } | 391 } |
| 392 | 392 |
| 393 TemplateURLModel* template_url_model = profile_->GetTemplateURLModel(); | 393 TemplateURLModel* template_url_model = profile_->GetTemplateURLModel(); |
| 394 if (template_url_model && !keyword.empty()) { | 394 if (template_url_model && !keyword.empty()) { |
| 395 const TemplateURL* const template_url = | 395 const TemplateURL* const template_url = |
| 396 template_url_model->GetTemplateURLForKeyword(keyword); | 396 template_url_model->GetTemplateURLForKeyword(WideToUTF16Hack(keyword)); |
| 397 | 397 |
| 398 // Special case for extension keywords. Don't increment usage count for | 398 // Special case for extension keywords. Don't increment usage count for |
| 399 // these. | 399 // these. |
| 400 if (template_url && template_url->IsExtensionKeyword()) { | 400 if (template_url && template_url->IsExtensionKeyword()) { |
| 401 AutocompleteMatch current_match; | 401 AutocompleteMatch current_match; |
| 402 GetInfoForCurrentText(¤t_match, NULL); | 402 GetInfoForCurrentText(¤t_match, NULL); |
| 403 | 403 |
| 404 const AutocompleteMatch& match = | 404 const AutocompleteMatch& match = |
| 405 index == AutocompletePopupModel::kNoMatch ? | 405 index == AutocompletePopupModel::kNoMatch ? |
| 406 current_match : result().match_at(index); | 406 current_match : result().match_at(index); |
| 407 | 407 |
| 408 // Strip the keyword + leading space off the input. | 408 // Strip the keyword + leading space off the input. |
| 409 size_t prefix_length = match.template_url->keyword().size() + 1; | 409 size_t prefix_length = match.template_url->keyword().size() + 1; |
| 410 ExtensionOmniboxEventRouter::OnInputEntered( | 410 ExtensionOmniboxEventRouter::OnInputEntered( |
| 411 profile_, match.template_url->GetExtensionId(), | 411 profile_, match.template_url->GetExtensionId(), |
| 412 UTF16ToUTF8(match.fill_into_edit.substr(prefix_length))); | 412 WideToUTF8(match.fill_into_edit.substr(prefix_length))); |
| 413 view_->RevertAll(); | 413 view_->RevertAll(); |
| 414 return; | 414 return; |
| 415 } | 415 } |
| 416 | 416 |
| 417 if (template_url) { | 417 if (template_url) { |
| 418 UserMetrics::RecordAction(UserMetricsAction("AcceptedKeyword"), profile_); | 418 UserMetrics::RecordAction(UserMetricsAction("AcceptedKeyword"), profile_); |
| 419 template_url_model->IncrementUsageCount(template_url); | 419 template_url_model->IncrementUsageCount(template_url); |
| 420 } | 420 } |
| 421 | 421 |
| 422 // NOTE: We purposefully don't increment the usage count of the default | 422 // NOTE: We purposefully don't increment the usage count of the default |
| 423 // search engine, if applicable; see comments in template_url.h. | 423 // search engine, if applicable; see comments in template_url.h. |
| 424 } | 424 } |
| 425 | 425 |
| 426 if (disposition != NEW_BACKGROUND_TAB) { | 426 if (disposition != NEW_BACKGROUND_TAB) { |
| 427 controller_->OnAutocompleteWillAccept(); | 427 controller_->OnAutocompleteWillAccept(); |
| 428 view_->RevertAll(); // Revert the box to its unedited state | 428 view_->RevertAll(); // Revert the box to its unedited state |
| 429 } | 429 } |
| 430 controller_->OnAutocompleteAccept(url, disposition, transition, | 430 controller_->OnAutocompleteAccept(url, disposition, transition, |
| 431 alternate_nav_url); | 431 alternate_nav_url); |
| 432 } | 432 } |
| 433 | 433 |
| 434 bool AutocompleteEditModel::AcceptKeyword() { | 434 bool AutocompleteEditModel::AcceptKeyword() { |
| 435 DCHECK(is_keyword_hint_ && !keyword_.empty()); | 435 DCHECK(is_keyword_hint_ && !keyword_.empty()); |
| 436 | 436 |
| 437 view_->OnBeforePossibleChange(); | 437 view_->OnBeforePossibleChange(); |
| 438 view_->SetWindowTextAndCaretPos(string16(), 0); | 438 view_->SetWindowTextAndCaretPos(std::wstring(), 0); |
| 439 is_keyword_hint_ = false; | 439 is_keyword_hint_ = false; |
| 440 view_->OnAfterPossibleChange(); | 440 view_->OnAfterPossibleChange(); |
| 441 just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets this | 441 just_deleted_text_ = false; // OnAfterPossibleChange() erroneously sets this |
| 442 // since the edit contents have disappeared. It | 442 // since the edit contents have disappeared. It |
| 443 // doesn't really matter, but we clear it to be | 443 // doesn't really matter, but we clear it to be |
| 444 // consistent. | 444 // consistent. |
| 445 UserMetrics::RecordAction(UserMetricsAction("AcceptedKeywordHint"), profile_); | 445 UserMetrics::RecordAction(UserMetricsAction("AcceptedKeywordHint"), profile_); |
| 446 return true; | 446 return true; |
| 447 } | 447 } |
| 448 | 448 |
| 449 void AutocompleteEditModel::ClearKeyword(const string16& visible_text) { | 449 void AutocompleteEditModel::ClearKeyword(const std::wstring& visible_text) { |
| 450 view_->OnBeforePossibleChange(); | 450 view_->OnBeforePossibleChange(); |
| 451 const string16 window_text(keyword_ + visible_text); | 451 const std::wstring window_text(keyword_ + visible_text); |
| 452 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length()); | 452 view_->SetWindowTextAndCaretPos(window_text.c_str(), keyword_.length()); |
| 453 keyword_.clear(); | 453 keyword_.clear(); |
| 454 is_keyword_hint_ = false; | 454 is_keyword_hint_ = false; |
| 455 view_->OnAfterPossibleChange(); | 455 view_->OnAfterPossibleChange(); |
| 456 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this | 456 just_deleted_text_ = true; // OnAfterPossibleChange() fails to clear this |
| 457 // since the edit contents have actually grown | 457 // since the edit contents have actually grown |
| 458 // longer. | 458 // longer. |
| 459 } | 459 } |
| 460 | 460 |
| 461 bool AutocompleteEditModel::query_in_progress() const { | 461 bool AutocompleteEditModel::query_in_progress() const { |
| (...skipping 97 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 559 // should force it to open immediately. | 559 // should force it to open immediately. |
| 560 } | 560 } |
| 561 } else { | 561 } else { |
| 562 // The popup is open, so the user should be able to interact with it | 562 // The popup is open, so the user should be able to interact with it |
| 563 // normally. | 563 // normally. |
| 564 popup_->Move(count); | 564 popup_->Move(count); |
| 565 } | 565 } |
| 566 } | 566 } |
| 567 | 567 |
| 568 void AutocompleteEditModel::OnPopupDataChanged( | 568 void AutocompleteEditModel::OnPopupDataChanged( |
| 569 const string16& text, | 569 const std::wstring& text, |
| 570 GURL* destination_for_temporary_text_change, | 570 GURL* destination_for_temporary_text_change, |
| 571 const string16& keyword, | 571 const std::wstring& keyword, |
| 572 bool is_keyword_hint) { | 572 bool is_keyword_hint) { |
| 573 // Update keyword/hint-related local state. | 573 // Update keyword/hint-related local state. |
| 574 bool keyword_state_changed = (keyword_ != keyword) || | 574 bool keyword_state_changed = (keyword_ != keyword) || |
| 575 ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()); | 575 ((is_keyword_hint_ != is_keyword_hint) && !keyword.empty()); |
| 576 if (keyword_state_changed) { | 576 if (keyword_state_changed) { |
| 577 keyword_ = keyword; | 577 keyword_ = keyword; |
| 578 is_keyword_hint_ = is_keyword_hint; | 578 is_keyword_hint_ = is_keyword_hint; |
| 579 | 579 |
| 580 // |is_keyword_hint_| should always be false if |keyword_| is empty. | 580 // |is_keyword_hint_| should always be false if |keyword_| is empty. |
| 581 DCHECK(!keyword_.empty() || !is_keyword_hint_); | 581 DCHECK(!keyword_.empty() || !is_keyword_hint_); |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 615 DisplayTextFromUserText(user_text_).length())) | 615 DisplayTextFromUserText(user_text_).length())) |
| 616 return; | 616 return; |
| 617 | 617 |
| 618 // All other code paths that return invoke OnChanged. We need to invoke | 618 // All other code paths that return invoke OnChanged. We need to invoke |
| 619 // OnChanged in case the destination url changed (as could happen when control | 619 // OnChanged in case the destination url changed (as could happen when control |
| 620 // is toggled). | 620 // is toggled). |
| 621 controller_->OnChanged(); | 621 controller_->OnChanged(); |
| 622 } | 622 } |
| 623 | 623 |
| 624 bool AutocompleteEditModel::OnAfterPossibleChange( | 624 bool AutocompleteEditModel::OnAfterPossibleChange( |
| 625 const string16& new_text, | 625 const std::wstring& new_text, |
| 626 bool selection_differs, | 626 bool selection_differs, |
| 627 bool text_differs, | 627 bool text_differs, |
| 628 bool just_deleted_text, | 628 bool just_deleted_text, |
| 629 bool allow_keyword_ui_change) { | 629 bool allow_keyword_ui_change) { |
| 630 // Update the paste state as appropriate: if we're just finishing a paste | 630 // Update the paste state as appropriate: if we're just finishing a paste |
| 631 // that replaced all the text, preserve that information; otherwise, if we've | 631 // that replaced all the text, preserve that information; otherwise, if we've |
| 632 // made some other edit, clear paste tracking. | 632 // made some other edit, clear paste tracking. |
| 633 if (paste_state_ == PASTING) | 633 if (paste_state_ == PASTING) |
| 634 paste_state_ = PASTED; | 634 paste_state_ = PASTED; |
| 635 else if (text_differs) | 635 else if (text_differs) |
| (...skipping 12 matching lines...) Expand all Loading... |
| 648 if (!text_differs && !popup_->IsOpen()) | 648 if (!text_differs && !popup_->IsOpen()) |
| 649 return false; // Don't open the popup for no reason. | 649 return false; // Don't open the popup for no reason. |
| 650 } else if (!user_text_changed) { | 650 } else if (!user_text_changed) { |
| 651 return false; | 651 return false; |
| 652 } | 652 } |
| 653 | 653 |
| 654 // If the user text has not changed, we do not want to change the model's | 654 // If the user text has not changed, we do not want to change the model's |
| 655 // state associated with the text. Otherwise, we can get surprising behavior | 655 // state associated with the text. Otherwise, we can get surprising behavior |
| 656 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 | 656 // where the autocompleted text unexpectedly reappears, e.g. crbug.com/55983 |
| 657 if (user_text_changed) { | 657 if (user_text_changed) { |
| 658 const string16 new_user_text = UserTextFromDisplayText(new_text); | 658 const std::wstring new_user_text = UserTextFromDisplayText(new_text); |
| 659 | 659 |
| 660 // Try to accept the current keyword if the user only typed a space at the | 660 // Try to accept the current keyword if the user only typed a space at the |
| 661 // end of content. Model's state and popup will be updated when the keyword | 661 // end of content. Model's state and popup will be updated when the keyword |
| 662 // is accepted. So we just need to return false here. | 662 // is accepted. So we just need to return false here. |
| 663 if (allow_keyword_ui_change && !selection_differs && | 663 if (allow_keyword_ui_change && !selection_differs && |
| 664 MaybeAcceptKeywordBySpace(new_user_text)) | 664 MaybeAcceptKeywordBySpace(new_user_text)) |
| 665 return false; | 665 return false; |
| 666 | 666 |
| 667 InternalSetUserText(new_user_text); | 667 InternalSetUserText(new_user_text); |
| 668 has_temporary_text_ = false; | 668 has_temporary_text_ = false; |
| (...skipping 29 matching lines...) Expand all Loading... |
| 698 return false; | 698 return false; |
| 699 } | 699 } |
| 700 } | 700 } |
| 701 | 701 |
| 702 void AutocompleteEditModel::Observe(NotificationType type, | 702 void AutocompleteEditModel::Observe(NotificationType type, |
| 703 const NotificationSource& source, | 703 const NotificationSource& source, |
| 704 const NotificationDetails& details) { | 704 const NotificationDetails& details) { |
| 705 DCHECK_EQ(NotificationType::AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED, | 705 DCHECK_EQ(NotificationType::AUTOCOMPLETE_CONTROLLER_DEFAULT_MATCH_UPDATED, |
| 706 type.value); | 706 type.value); |
| 707 | 707 |
| 708 string16 inline_autocomplete_text; | 708 std::wstring inline_autocomplete_text; |
| 709 string16 keyword; | 709 std::wstring keyword; |
| 710 bool is_keyword_hint = false; | 710 bool is_keyword_hint = false; |
| 711 const AutocompleteResult* result = | 711 const AutocompleteResult* result = |
| 712 Details<const AutocompleteResult>(details).ptr(); | 712 Details<const AutocompleteResult>(details).ptr(); |
| 713 const AutocompleteResult::const_iterator match(result->default_match()); | 713 const AutocompleteResult::const_iterator match(result->default_match()); |
| 714 if (match != result->end()) { | 714 if (match != result->end()) { |
| 715 if ((match->inline_autocomplete_offset != string16::npos) && | 715 if ((match->inline_autocomplete_offset != std::wstring::npos) && |
| 716 (match->inline_autocomplete_offset < match->fill_into_edit.length())) { | 716 (match->inline_autocomplete_offset < match->fill_into_edit.length())) { |
| 717 inline_autocomplete_text = | 717 inline_autocomplete_text = |
| 718 match->fill_into_edit.substr(match->inline_autocomplete_offset); | 718 match->fill_into_edit.substr(match->inline_autocomplete_offset); |
| 719 } | 719 } |
| 720 | 720 |
| 721 if (!match->destination_url.SchemeIs(chrome::kExtensionScheme)) { | 721 if (!match->destination_url.SchemeIs(chrome::kExtensionScheme)) { |
| 722 // Warm up DNS Prefetch cache, or preconnect to a search service. | 722 // Warm up DNS Prefetch cache, or preconnect to a search service. |
| 723 chrome_browser_net::AnticipateOmniboxUrl(match->destination_url, | 723 chrome_browser_net::AnticipateOmniboxUrl(match->destination_url, |
| 724 IsPreconnectable(match->type)); | 724 IsPreconnectable(match->type)); |
| 725 } | 725 } |
| 726 | 726 |
| 727 // We could prefetch the alternate nav URL, if any, but because there | 727 // We could prefetch the alternate nav URL, if any, but because there |
| 728 // can be many of these as a user types an initial series of characters, | 728 // can be many of these as a user types an initial series of characters, |
| 729 // the OS DNS cache could suffer eviction problems for minimal gain. | 729 // the OS DNS cache could suffer eviction problems for minimal gain. |
| 730 | 730 |
| 731 is_keyword_hint = popup_->GetKeywordForMatch(*match, &keyword); | 731 is_keyword_hint = popup_->GetKeywordForMatch(*match, &keyword); |
| 732 } | 732 } |
| 733 | 733 |
| 734 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, is_keyword_hint); | 734 OnPopupDataChanged(inline_autocomplete_text, NULL, keyword, is_keyword_hint); |
| 735 } | 735 } |
| 736 | 736 |
| 737 void AutocompleteEditModel::InternalSetUserText(const string16& text) { | 737 void AutocompleteEditModel::InternalSetUserText(const std::wstring& text) { |
| 738 user_text_ = text; | 738 user_text_ = text; |
| 739 just_deleted_text_ = false; | 739 just_deleted_text_ = false; |
| 740 inline_autocomplete_text_.clear(); | 740 inline_autocomplete_text_.clear(); |
| 741 } | 741 } |
| 742 | 742 |
| 743 bool AutocompleteEditModel::KeywordIsSelected() const { | 743 bool AutocompleteEditModel::KeywordIsSelected() const { |
| 744 return !is_keyword_hint_ && !keyword_.empty(); | 744 return !is_keyword_hint_ && !keyword_.empty(); |
| 745 } | 745 } |
| 746 | 746 |
| 747 string16 AutocompleteEditModel::DisplayTextFromUserText( | 747 std::wstring AutocompleteEditModel::DisplayTextFromUserText( |
| 748 const string16& text) const { | 748 const std::wstring& text) const { |
| 749 return KeywordIsSelected() ? | 749 return KeywordIsSelected() ? |
| 750 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; | 750 KeywordProvider::SplitReplacementStringFromInput(text, false) : text; |
| 751 } | 751 } |
| 752 | 752 |
| 753 string16 AutocompleteEditModel::UserTextFromDisplayText( | 753 std::wstring AutocompleteEditModel::UserTextFromDisplayText( |
| 754 const string16& text) const { | 754 const std::wstring& text) const { |
| 755 return KeywordIsSelected() ? (keyword_ + char16(' ') + text) : text; | 755 return KeywordIsSelected() ? (keyword_ + L" " + text) : text; |
| 756 } | 756 } |
| 757 | 757 |
| 758 void AutocompleteEditModel::GetInfoForCurrentText( | 758 void AutocompleteEditModel::GetInfoForCurrentText( |
| 759 AutocompleteMatch* match, | 759 AutocompleteMatch* match, |
| 760 GURL* alternate_nav_url) const { | 760 GURL* alternate_nav_url) const { |
| 761 if (popup_->IsOpen() || query_in_progress()) { | 761 if (popup_->IsOpen() || query_in_progress()) { |
| 762 popup_->InfoForCurrentSelection(match, alternate_nav_url); | 762 popup_->InfoForCurrentSelection(match, alternate_nav_url); |
| 763 } else { | 763 } else { |
| 764 profile_->GetAutocompleteClassifier()->Classify( | 764 profile_->GetAutocompleteClassifier()->Classify( |
| 765 UserTextFromDisplayText(view_->GetText()), GetDesiredTLD(), true, | 765 UserTextFromDisplayText(view_->GetText()), GetDesiredTLD(), true, |
| 766 match, alternate_nav_url); | 766 match, alternate_nav_url); |
| 767 } | 767 } |
| 768 } | 768 } |
| 769 | 769 |
| 770 bool AutocompleteEditModel::GetURLForText(const string16& text, | 770 bool AutocompleteEditModel::GetURLForText(const std::wstring& text, |
| 771 GURL* url) const { | 771 GURL* url) const { |
| 772 GURL parsed_url; | 772 GURL parsed_url; |
| 773 const AutocompleteInput::Type type = AutocompleteInput::Parse( | 773 const AutocompleteInput::Type type = AutocompleteInput::Parse( |
| 774 UserTextFromDisplayText(text), string16(), NULL, NULL, &parsed_url); | 774 UserTextFromDisplayText(text), std::wstring(), NULL, NULL, &parsed_url); |
| 775 if (type != AutocompleteInput::URL) | 775 if (type != AutocompleteInput::URL) |
| 776 return false; | 776 return false; |
| 777 | 777 |
| 778 *url = parsed_url; | 778 *url = parsed_url; |
| 779 return true; | 779 return true; |
| 780 } | 780 } |
| 781 | 781 |
| 782 bool AutocompleteEditModel::MaybeAcceptKeywordBySpace( | 782 bool AutocompleteEditModel::MaybeAcceptKeywordBySpace( |
| 783 const string16& new_user_text) { | 783 const std::wstring& new_user_text) { |
| 784 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && | 784 return (paste_state_ == NONE) && is_keyword_hint_ && !keyword_.empty() && |
| 785 inline_autocomplete_text_.empty() && !user_text_.empty() && | 785 inline_autocomplete_text_.empty() && !user_text_.empty() && |
| 786 (new_user_text.length() == user_text_.length() + 1) && | 786 (new_user_text.length() == user_text_.length() + 1) && |
| 787 !new_user_text.compare(0, user_text_.length(), user_text_) && | 787 !new_user_text.compare(0, user_text_.length(), user_text_) && |
| 788 IsSpaceCharForAcceptingKeyword(new_user_text[user_text_.length()]) && | 788 IsSpaceCharForAcceptingKeyword(new_user_text[user_text_.length()]) && |
| 789 !IsWhitespace(user_text_[user_text_.length() - 1]) && | 789 !IsWhitespace(user_text_[user_text_.length() - 1]) && |
| 790 AcceptKeyword(); | 790 AcceptKeyword(); |
| 791 } | 791 } |
| 792 | 792 |
| 793 // static | 793 // static |
| 794 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { | 794 bool AutocompleteEditModel::IsSpaceCharForAcceptingKeyword(wchar_t c) { |
| 795 switch (c) { | 795 switch (c) { |
| 796 case 0x0020: // Space | 796 case 0x0020: // Space |
| 797 case 0x3000: // Ideographic Space | 797 case 0x3000: // Ideographic Space |
| 798 return true; | 798 return true; |
| 799 default: | 799 default: |
| 800 return false; | 800 return false; |
| 801 } | 801 } |
| 802 } | 802 } |
| OLD | NEW |