| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 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.h" | 5 #include "chrome/browser/autocomplete/autocomplete.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 | 8 |
| 9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
| 10 #include "base/command_line.h" | 10 #include "base/command_line.h" |
| (...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 44 | 44 |
| 45 AutocompleteInput::AutocompleteInput() | 45 AutocompleteInput::AutocompleteInput() |
| 46 : type_(INVALID), | 46 : type_(INVALID), |
| 47 initial_prevent_inline_autocomplete_(false), | 47 initial_prevent_inline_autocomplete_(false), |
| 48 prevent_inline_autocomplete_(false), | 48 prevent_inline_autocomplete_(false), |
| 49 prefer_keyword_(false), | 49 prefer_keyword_(false), |
| 50 allow_exact_keyword_match_(true), | 50 allow_exact_keyword_match_(true), |
| 51 synchronous_only_(false) { | 51 synchronous_only_(false) { |
| 52 } | 52 } |
| 53 | 53 |
| 54 AutocompleteInput::AutocompleteInput(const string16& text, | 54 AutocompleteInput::AutocompleteInput(const std::wstring& text, |
| 55 const string16& desired_tld, | 55 const std::wstring& desired_tld, |
| 56 bool prevent_inline_autocomplete, | 56 bool prevent_inline_autocomplete, |
| 57 bool prefer_keyword, | 57 bool prefer_keyword, |
| 58 bool allow_exact_keyword_match, | 58 bool allow_exact_keyword_match, |
| 59 bool synchronous_only) | 59 bool synchronous_only) |
| 60 : desired_tld_(desired_tld), | 60 : desired_tld_(desired_tld), |
| 61 initial_prevent_inline_autocomplete_(prevent_inline_autocomplete), | 61 initial_prevent_inline_autocomplete_(prevent_inline_autocomplete), |
| 62 prevent_inline_autocomplete_(prevent_inline_autocomplete), | 62 prevent_inline_autocomplete_(prevent_inline_autocomplete), |
| 63 prefer_keyword_(prefer_keyword), | 63 prefer_keyword_(prefer_keyword), |
| 64 allow_exact_keyword_match_(allow_exact_keyword_match), | 64 allow_exact_keyword_match_(allow_exact_keyword_match), |
| 65 synchronous_only_(synchronous_only) { | 65 synchronous_only_(synchronous_only) { |
| (...skipping 15 matching lines...) Expand all Loading... |
| 81 canonicalized_url_ = canonicalized_url; | 81 canonicalized_url_ = canonicalized_url; |
| 82 | 82 |
| 83 RemoveForcedQueryStringIfNecessary(type_, &text_); | 83 RemoveForcedQueryStringIfNecessary(type_, &text_); |
| 84 } | 84 } |
| 85 | 85 |
| 86 AutocompleteInput::~AutocompleteInput() { | 86 AutocompleteInput::~AutocompleteInput() { |
| 87 } | 87 } |
| 88 | 88 |
| 89 // static | 89 // static |
| 90 void AutocompleteInput::RemoveForcedQueryStringIfNecessary(Type type, | 90 void AutocompleteInput::RemoveForcedQueryStringIfNecessary(Type type, |
| 91 string16* text) { | 91 std::wstring* text) { |
| 92 if (type == FORCED_QUERY && !text->empty() && (*text)[0] == L'?') | 92 if (type == FORCED_QUERY && !text->empty() && (*text)[0] == L'?') |
| 93 text->erase(0, 1); | 93 text->erase(0, 1); |
| 94 } | 94 } |
| 95 | 95 |
| 96 // static | 96 // static |
| 97 std::string AutocompleteInput::TypeToString(Type type) { | 97 std::string AutocompleteInput::TypeToString(Type type) { |
| 98 switch (type) { | 98 switch (type) { |
| 99 case INVALID: return "invalid"; | 99 case INVALID: return "invalid"; |
| 100 case UNKNOWN: return "unknown"; | 100 case UNKNOWN: return "unknown"; |
| 101 case REQUESTED_URL: return "requested-url"; | 101 case REQUESTED_URL: return "requested-url"; |
| 102 case URL: return "url"; | 102 case URL: return "url"; |
| 103 case QUERY: return "query"; | 103 case QUERY: return "query"; |
| 104 case FORCED_QUERY: return "forced-query"; | 104 case FORCED_QUERY: return "forced-query"; |
| 105 | 105 |
| 106 default: | 106 default: |
| 107 NOTREACHED(); | 107 NOTREACHED(); |
| 108 return std::string(); | 108 return std::string(); |
| 109 } | 109 } |
| 110 } | 110 } |
| 111 | 111 |
| 112 // static | 112 // static |
| 113 AutocompleteInput::Type AutocompleteInput::Parse( | 113 AutocompleteInput::Type AutocompleteInput::Parse( |
| 114 const string16& text, | 114 const std::wstring& text, |
| 115 const string16& desired_tld, | 115 const std::wstring& desired_tld, |
| 116 url_parse::Parsed* parts, | 116 url_parse::Parsed* parts, |
| 117 string16* scheme, | 117 std::wstring* scheme, |
| 118 GURL* canonicalized_url) { | 118 GURL* canonicalized_url) { |
| 119 const size_t first_non_white = text.find_first_not_of(kWhitespaceUTF16, 0); | 119 const size_t first_non_white = text.find_first_not_of(kWhitespaceWide, 0); |
| 120 if (first_non_white == string16::npos) | 120 if (first_non_white == std::wstring::npos) |
| 121 return INVALID; // All whitespace. | 121 return INVALID; // All whitespace. |
| 122 | 122 |
| 123 if (text.at(first_non_white) == L'?') { | 123 if (text.at(first_non_white) == L'?') { |
| 124 // If the first non-whitespace character is a '?', we magically treat this | 124 // If the first non-whitespace character is a '?', we magically treat this |
| 125 // as a query. | 125 // as a query. |
| 126 return FORCED_QUERY; | 126 return FORCED_QUERY; |
| 127 } | 127 } |
| 128 | 128 |
| 129 // Ask our parsing back-end to help us understand what the user typed. We | 129 // Ask our parsing back-end to help us understand what the user typed. We |
| 130 // use the URLFixerUpper here because we want to be smart about what we | 130 // use the URLFixerUpper here because we want to be smart about what we |
| 131 // consider a scheme. For example, we shouldn't consider www.google.com:80 | 131 // consider a scheme. For example, we shouldn't consider www.google.com:80 |
| 132 // to have a scheme. | 132 // to have a scheme. |
| 133 url_parse::Parsed local_parts; | 133 url_parse::Parsed local_parts; |
| 134 if (!parts) | 134 if (!parts) |
| 135 parts = &local_parts; | 135 parts = &local_parts; |
| 136 const string16 parsed_scheme(URLFixerUpper::SegmentURL(text, parts)); | 136 const std::wstring parsed_scheme(URLFixerUpper::SegmentURL(text, parts)); |
| 137 if (scheme) | 137 if (scheme) |
| 138 *scheme = parsed_scheme; | 138 *scheme = parsed_scheme; |
| 139 if (canonicalized_url) { | 139 if (canonicalized_url) { |
| 140 *canonicalized_url = URLFixerUpper::FixupURL(UTF16ToUTF8(text), | 140 *canonicalized_url = URLFixerUpper::FixupURL(WideToUTF8(text), |
| 141 UTF16ToUTF8(desired_tld)); | 141 WideToUTF8(desired_tld)); |
| 142 } | 142 } |
| 143 | 143 |
| 144 if (LowerCaseEqualsASCII(parsed_scheme, chrome::kFileScheme)) { | 144 if (parsed_scheme == L"file") { |
| 145 // A user might or might not type a scheme when entering a file URL. In | 145 // A user might or might not type a scheme when entering a file URL. In |
| 146 // either case, |parsed_scheme| will tell us that this is a file URL, but | 146 // either case, |parsed_scheme| will tell us that this is a file URL, but |
| 147 // |parts->scheme| might be empty, e.g. if the user typed "C:\foo". | 147 // |parts->scheme| might be empty, e.g. if the user typed "C:\foo". |
| 148 return URL; | 148 return URL; |
| 149 } | 149 } |
| 150 | 150 |
| 151 // If the user typed a scheme, and it's HTTP or HTTPS, we know how to parse it | 151 // If the user typed a scheme, and it's HTTP or HTTPS, we know how to parse it |
| 152 // well enough that we can fall through to the heuristics below. If it's | 152 // well enough that we can fall through to the heuristics below. If it's |
| 153 // something else, we can just determine our action based on what we do with | 153 // something else, we can just determine our action based on what we do with |
| 154 // any input of this scheme. In theory we could do better with some schemes | 154 // any input of this scheme. In theory we could do better with some schemes |
| 155 // (e.g. "ftp" or "view-source") but I'll wait to spend the effort on that | 155 // (e.g. "ftp" or "view-source") but I'll wait to spend the effort on that |
| 156 // until I run into some cases that really need it. | 156 // until I run into some cases that really need it. |
| 157 if (parts->scheme.is_nonempty() && | 157 if (parts->scheme.is_nonempty() && |
| 158 !LowerCaseEqualsASCII(parsed_scheme, chrome::kHttpScheme) && | 158 (parsed_scheme != L"http") && (parsed_scheme != L"https")) { |
| 159 !LowerCaseEqualsASCII(parsed_scheme, chrome::kHttpsScheme)) { | |
| 160 // See if we know how to handle the URL internally. | 159 // See if we know how to handle the URL internally. |
| 161 if (net::URLRequest::IsHandledProtocol(UTF16ToASCII(parsed_scheme))) | 160 if (net::URLRequest::IsHandledProtocol(WideToASCII(parsed_scheme))) |
| 162 return URL; | 161 return URL; |
| 163 | 162 |
| 164 // There are also some schemes that we convert to other things before they | 163 // There are also some schemes that we convert to other things before they |
| 165 // reach the renderer or else the renderer handles internally without | 164 // reach the renderer or else the renderer handles internally without |
| 166 // reaching the net::URLRequest logic. We thus won't catch these above, but | 165 // reaching the net::URLRequest logic. We thus won't catch these above, but |
| 167 // we should still claim to handle them. | 166 // we should still claim to handle them. |
| 168 if (LowerCaseEqualsASCII(parsed_scheme, chrome::kViewSourceScheme) || | 167 if (LowerCaseEqualsASCII(parsed_scheme, chrome::kViewSourceScheme) || |
| 169 LowerCaseEqualsASCII(parsed_scheme, chrome::kJavaScriptScheme) || | 168 LowerCaseEqualsASCII(parsed_scheme, chrome::kJavaScriptScheme) || |
| 170 LowerCaseEqualsASCII(parsed_scheme, chrome::kDataScheme)) | 169 LowerCaseEqualsASCII(parsed_scheme, chrome::kDataScheme)) |
| 171 return URL; | 170 return URL; |
| 172 | 171 |
| 173 // Finally, check and see if the user has explicitly opened this scheme as | 172 // Finally, check and see if the user has explicitly opened this scheme as |
| 174 // a URL before, or if the "scheme" is actually a username. We need to do | 173 // a URL before, or if the "scheme" is actually a username. We need to do |
| 175 // this last because some schemes (e.g. "javascript") may be treated as | 174 // this last because some schemes (e.g. "javascript") may be treated as |
| 176 // "blocked" by the external protocol handler because we don't want pages to | 175 // "blocked" by the external protocol handler because we don't want pages to |
| 177 // open them, but users still can. | 176 // open them, but users still can. |
| 178 // TODO(viettrungluu): get rid of conversion. | 177 // TODO(viettrungluu): get rid of conversion. |
| 179 ExternalProtocolHandler::BlockState block_state = | 178 switch (ExternalProtocolHandler::GetBlockState(WideToUTF8(parsed_scheme))) { |
| 180 ExternalProtocolHandler::GetBlockState(UTF16ToUTF8(parsed_scheme)); | |
| 181 switch (block_state) { | |
| 182 case ExternalProtocolHandler::DONT_BLOCK: | 179 case ExternalProtocolHandler::DONT_BLOCK: |
| 183 return URL; | 180 return URL; |
| 184 | 181 |
| 185 case ExternalProtocolHandler::BLOCK: | 182 case ExternalProtocolHandler::BLOCK: |
| 186 // If we don't want the user to open the URL, don't let it be navigated | 183 // If we don't want the user to open the URL, don't let it be navigated |
| 187 // to at all. | 184 // to at all. |
| 188 return QUERY; | 185 return QUERY; |
| 189 | 186 |
| 190 default: { | 187 default: { |
| 191 // We don't know about this scheme. It might be that the user typed a | 188 // We don't know about this scheme. It might be that the user typed a |
| 192 // URL of the form "username:password@foo.com". | 189 // URL of the form "username:password@foo.com". |
| 193 const string16 http_scheme_prefix = | 190 const std::wstring http_scheme_prefix = L"http://"; |
| 194 ASCIIToUTF16(std::string(chrome::kHttpScheme) + | |
| 195 chrome::kStandardSchemeSeparator); | |
| 196 url_parse::Parsed http_parts; | 191 url_parse::Parsed http_parts; |
| 197 string16 http_scheme; | 192 std::wstring http_scheme; |
| 198 GURL http_canonicalized_url; | 193 GURL http_canonicalized_url; |
| 199 Type http_type = Parse(http_scheme_prefix + text, desired_tld, | 194 Type http_type = Parse(http_scheme_prefix + text, desired_tld, |
| 200 &http_parts, &http_scheme, | 195 &http_parts, &http_scheme, |
| 201 &http_canonicalized_url); | 196 &http_canonicalized_url); |
| 202 DCHECK_EQ(std::string(chrome::kHttpScheme), UTF16ToUTF8(http_scheme)); | 197 DCHECK_EQ("http", WideToUTF8(http_scheme)); |
| 203 | 198 |
| 204 if ((http_type == URL || http_type == REQUESTED_URL) && | 199 if ((http_type == URL || http_type == REQUESTED_URL) && |
| 205 http_parts.username.is_nonempty() && | 200 http_parts.username.is_nonempty() && |
| 206 http_parts.password.is_nonempty()) { | 201 http_parts.password.is_nonempty()) { |
| 207 // Manually re-jigger the parsed parts to match |text| (without the | 202 // Manually re-jigger the parsed parts to match |text| (without the |
| 208 // http scheme added). | 203 // http scheme added). |
| 209 http_parts.scheme.reset(); | 204 http_parts.scheme.reset(); |
| 210 url_parse::Component* components[] = { | 205 url_parse::Component* components[] = { |
| 211 &http_parts.username, | 206 &http_parts.username, |
| 212 &http_parts.password, | 207 &http_parts.password, |
| (...skipping 31 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 244 // Either the user didn't type a scheme, in which case we need to distinguish | 239 // Either the user didn't type a scheme, in which case we need to distinguish |
| 245 // between an HTTP URL and a query, or the scheme is HTTP or HTTPS, in which | 240 // between an HTTP URL and a query, or the scheme is HTTP or HTTPS, in which |
| 246 // case we should reject invalid formulations. | 241 // case we should reject invalid formulations. |
| 247 | 242 |
| 248 // If we have an empty host it can't be a URL. | 243 // If we have an empty host it can't be a URL. |
| 249 if (!parts->host.is_nonempty()) | 244 if (!parts->host.is_nonempty()) |
| 250 return QUERY; | 245 return QUERY; |
| 251 | 246 |
| 252 // Likewise, the RCDS can reject certain obviously-invalid hosts. (We also | 247 // Likewise, the RCDS can reject certain obviously-invalid hosts. (We also |
| 253 // use the registry length later below.) | 248 // use the registry length later below.) |
| 254 const string16 host(text.substr(parts->host.begin, parts->host.len)); | 249 const std::wstring host(text.substr(parts->host.begin, parts->host.len)); |
| 255 const size_t registry_length = | 250 const size_t registry_length = |
| 256 net::RegistryControlledDomainService::GetRegistryLength(UTF16ToUTF8(host), | 251 net::RegistryControlledDomainService::GetRegistryLength(host, false); |
| 257 false); | 252 if (registry_length == std::wstring::npos) { |
| 258 if (registry_length == std::string::npos) { | |
| 259 // Try to append the desired_tld. | 253 // Try to append the desired_tld. |
| 260 if (!desired_tld.empty()) { | 254 if (!desired_tld.empty()) { |
| 261 string16 host_with_tld(host); | 255 std::wstring host_with_tld(host); |
| 262 if (host[host.length() - 1] != '.') | 256 if (host[host.length() - 1] != '.') |
| 263 host_with_tld += '.'; | 257 host_with_tld += '.'; |
| 264 host_with_tld += desired_tld; | 258 host_with_tld += desired_tld; |
| 265 if (net::RegistryControlledDomainService::GetRegistryLength( | 259 if (net::RegistryControlledDomainService::GetRegistryLength( |
| 266 UTF16ToUTF8(host_with_tld), false) != std::string::npos) | 260 host_with_tld, false) != std::wstring::npos) |
| 267 return REQUESTED_URL; // Something like "99999999999" that looks like a | 261 return REQUESTED_URL; // Something like "99999999999" that looks like a |
| 268 // bad IP address, but becomes valid on attaching | 262 // bad IP address, but becomes valid on attaching |
| 269 // a TLD. | 263 // a TLD. |
| 270 } | 264 } |
| 271 return QUERY; // Could be a broken IP address, etc. | 265 return QUERY; // Could be a broken IP address, etc. |
| 272 } | 266 } |
| 273 | 267 |
| 274 | 268 |
| 275 // See if the hostname is valid. While IE and GURL allow hostnames to contain | 269 // See if the hostname is valid. While IE and GURL allow hostnames to contain |
| 276 // many other characters (perhaps for weird intranet machines), it's extremely | 270 // many other characters (perhaps for weird intranet machines), it's extremely |
| 277 // unlikely that a user would be trying to type those in for anything other | 271 // unlikely that a user would be trying to type those in for anything other |
| 278 // than a search query. | 272 // than a search query. |
| 279 url_canon::CanonHostInfo host_info; | 273 url_canon::CanonHostInfo host_info; |
| 280 const std::string canonicalized_host(net::CanonicalizeHost(UTF16ToUTF8(host), | 274 const std::string canonicalized_host(net::CanonicalizeHost(host, &host_info)); |
| 281 &host_info)); | |
| 282 if ((host_info.family == url_canon::CanonHostInfo::NEUTRAL) && | 275 if ((host_info.family == url_canon::CanonHostInfo::NEUTRAL) && |
| 283 !net::IsCanonicalizedHostCompliant(canonicalized_host, | 276 !net::IsCanonicalizedHostCompliant(canonicalized_host, |
| 284 UTF16ToUTF8(desired_tld))) { | 277 WideToUTF8(desired_tld))) { |
| 285 // Invalid hostname. There are several possible cases: | 278 // Invalid hostname. There are several possible cases: |
| 286 // * Our checker is too strict and the user pasted in a real-world URL | 279 // * Our checker is too strict and the user pasted in a real-world URL |
| 287 // that's "invalid" but resolves. To catch these, we return UNKNOWN when | 280 // that's "invalid" but resolves. To catch these, we return UNKNOWN when |
| 288 // the user explicitly typed a scheme, so we'll still search by default | 281 // the user explicitly typed a scheme, so we'll still search by default |
| 289 // but we'll show the accidental search infobar if necessary. | 282 // but we'll show the accidental search infobar if necessary. |
| 290 // * The user is typing a multi-word query. If we see a space anywhere in | 283 // * The user is typing a multi-word query. If we see a space anywhere in |
| 291 // the hostname we assume this is a search and return QUERY. | 284 // the hostname we assume this is a search and return QUERY. |
| 292 // * Our checker is too strict and the user is typing a real-world hostname | 285 // * Our checker is too strict and the user is typing a real-world hostname |
| 293 // that's "invalid" but resolves. We return UNKNOWN if the TLD is known. | 286 // that's "invalid" but resolves. We return UNKNOWN if the TLD is known. |
| 294 // Note that we explicitly excluded hosts with spaces above so that | 287 // Note that we explicitly excluded hosts with spaces above so that |
| 295 // "toys at amazon.com" will be treated as a search. | 288 // "toys at amazon.com" will be treated as a search. |
| 296 // * The user is typing some garbage string. Return QUERY. | 289 // * The user is typing some garbage string. Return QUERY. |
| 297 // | 290 // |
| 298 // Thus we fall down in the following cases: | 291 // Thus we fall down in the following cases: |
| 299 // * Trying to navigate to a hostname with spaces | 292 // * Trying to navigate to a hostname with spaces |
| 300 // * Trying to navigate to a hostname with invalid characters and an unknown | 293 // * Trying to navigate to a hostname with invalid characters and an unknown |
| 301 // TLD | 294 // TLD |
| 302 // These are rare, though probably possible in intranets. | 295 // These are rare, though probably possible in intranets. |
| 303 return (parts->scheme.is_nonempty() || | 296 return (parts->scheme.is_nonempty() || |
| 304 ((registry_length != 0) && (host.find(' ') == string16::npos))) ? | 297 ((registry_length != 0) && (host.find(' ') == std::wstring::npos))) ? |
| 305 UNKNOWN : QUERY; | 298 UNKNOWN : QUERY; |
| 306 } | 299 } |
| 307 | 300 |
| 308 // A port number is a good indicator that this is a URL. However, it might | 301 // A port number is a good indicator that this is a URL. However, it might |
| 309 // also be a query like "1.66:1" that looks kind of like an IP address and | 302 // also be a query like "1.66:1" that looks kind of like an IP address and |
| 310 // port number. So here we only check for "port numbers" that are illegal and | 303 // port number. So here we only check for "port numbers" that are illegal and |
| 311 // thus mean this can't be navigated to (e.g. "1.2.3.4:garbage"), and we save | 304 // thus mean this can't be navigated to (e.g. "1.2.3.4:garbage"), and we save |
| 312 // handling legal port numbers until after the "IP address" determination | 305 // handling legal port numbers until after the "IP address" determination |
| 313 // below. | 306 // below. |
| 314 if (parts->port.is_nonempty()) { | 307 if (parts->port.is_nonempty()) { |
| 315 int port; | 308 int port; |
| 316 if (!base::StringToInt(text.substr(parts->port.begin, parts->port.len), | 309 if (!base::StringToInt(WideToUTF8( |
| 317 &port) || | 310 text.substr(parts->port.begin, parts->port.len)), &port) || |
| 318 (port < 0) || (port > 65535)) | 311 (port < 0) || (port > 65535)) |
| 319 return QUERY; | 312 return QUERY; |
| 320 } | 313 } |
| 321 | 314 |
| 322 // Now that we've ruled out all schemes other than http or https and done a | 315 // Now that we've ruled out all schemes other than http or https and done a |
| 323 // little more sanity checking, the presence of a scheme means this is likely | 316 // little more sanity checking, the presence of a scheme means this is likely |
| 324 // a URL. | 317 // a URL. |
| 325 if (parts->scheme.is_nonempty()) | 318 if (parts->scheme.is_nonempty()) |
| 326 return URL; | 319 return URL; |
| 327 | 320 |
| (...skipping 28 matching lines...) Expand all Loading... |
| 356 if (parts->path.is_nonempty()) { | 349 if (parts->path.is_nonempty()) { |
| 357 // Most inputs with paths are URLs, even ones without known registries (e.g. | 350 // Most inputs with paths are URLs, even ones without known registries (e.g. |
| 358 // intranet URLs). However, if there's no known registry and the path has | 351 // intranet URLs). However, if there's no known registry and the path has |
| 359 // a space, this is more likely a query with a slash in the first term | 352 // a space, this is more likely a query with a slash in the first term |
| 360 // (e.g. "ps/2 games") than a URL. We can still open URLs with spaces in | 353 // (e.g. "ps/2 games") than a URL. We can still open URLs with spaces in |
| 361 // the path by escaping the space, and we will still inline autocomplete | 354 // the path by escaping the space, and we will still inline autocomplete |
| 362 // them if users have typed them in the past, but we default to searching | 355 // them if users have typed them in the past, but we default to searching |
| 363 // since that's the common case. | 356 // since that's the common case. |
| 364 return ((registry_length == 0) && | 357 return ((registry_length == 0) && |
| 365 (text.substr(parts->path.begin, parts->path.len).find(' ') != | 358 (text.substr(parts->path.begin, parts->path.len).find(' ') != |
| 366 string16::npos)) ? UNKNOWN : URL; | 359 std::wstring::npos)) ? UNKNOWN : URL; |
| 367 } | 360 } |
| 368 | 361 |
| 369 // If we reach here with a username, our input looks like "user@host". | 362 // If we reach here with a username, our input looks like "user@host". |
| 370 // Because there is no scheme explicitly specified, we think this is more | 363 // Because there is no scheme explicitly specified, we think this is more |
| 371 // likely an email address than an HTTP auth attempt. Hence, we search by | 364 // likely an email address than an HTTP auth attempt. Hence, we search by |
| 372 // default and let users correct us on a case-by-case basis. | 365 // default and let users correct us on a case-by-case basis. |
| 373 if (parts->username.is_nonempty()) | 366 if (parts->username.is_nonempty()) |
| 374 return UNKNOWN; | 367 return UNKNOWN; |
| 375 | 368 |
| 376 // We have a bare host string. If it has a known TLD, it's probably a URL. | 369 // We have a bare host string. If it has a known TLD, it's probably a URL. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 392 // "browser.tabs.closeButtons" or "java.awt.event.*"). This is ideally a | 385 // "browser.tabs.closeButtons" or "java.awt.event.*"). This is ideally a |
| 393 // QUERY. Since the above case and this one are indistinguishable, and this | 386 // QUERY. Since the above case and this one are indistinguishable, and this |
| 394 // case is likely to be much more common, just say these are both UNKNOWN, | 387 // case is likely to be much more common, just say these are both UNKNOWN, |
| 395 // which should default to the right thing and let users correct us on a | 388 // which should default to the right thing and let users correct us on a |
| 396 // case-by-case basis. | 389 // case-by-case basis. |
| 397 return desired_tld.empty() ? UNKNOWN : REQUESTED_URL; | 390 return desired_tld.empty() ? UNKNOWN : REQUESTED_URL; |
| 398 } | 391 } |
| 399 | 392 |
| 400 // static | 393 // static |
| 401 void AutocompleteInput::ParseForEmphasizeComponents( | 394 void AutocompleteInput::ParseForEmphasizeComponents( |
| 402 const string16& text, | 395 const std::wstring& text, |
| 403 const string16& desired_tld, | 396 const std::wstring& desired_tld, |
| 404 url_parse::Component* scheme, | 397 url_parse::Component* scheme, |
| 405 url_parse::Component* host) { | 398 url_parse::Component* host) { |
| 406 url_parse::Parsed parts; | 399 url_parse::Parsed parts; |
| 407 string16 scheme_str; | 400 std::wstring scheme_str; |
| 408 Parse(text, desired_tld, &parts, &scheme_str, NULL); | 401 Parse(text, desired_tld, &parts, &scheme_str, NULL); |
| 409 | 402 |
| 410 *scheme = parts.scheme; | 403 *scheme = parts.scheme; |
| 411 *host = parts.host; | 404 *host = parts.host; |
| 412 | 405 |
| 413 int after_scheme_and_colon = parts.scheme.end() + 1; | 406 int after_scheme_and_colon = parts.scheme.end() + 1; |
| 414 // For the view-source scheme, we should emphasize the scheme and host of the | 407 // For the view-source scheme, we should emphasize the scheme and host of the |
| 415 // URL qualified by the view-source prefix. | 408 // URL qualified by the view-source prefix. |
| 416 if (LowerCaseEqualsASCII(scheme_str, chrome::kViewSourceScheme) && | 409 if (LowerCaseEqualsASCII(scheme_str, chrome::kViewSourceScheme) && |
| 417 (static_cast<int>(text.length()) > after_scheme_and_colon)) { | 410 (static_cast<int>(text.length()) > after_scheme_and_colon)) { |
| 418 // Obtain the URL prefixed by view-source and parse it. | 411 // Obtain the URL prefixed by view-source and parse it. |
| 419 string16 real_url(text.substr(after_scheme_and_colon)); | 412 std::wstring real_url(text.substr(after_scheme_and_colon)); |
| 420 url_parse::Parsed real_parts; | 413 url_parse::Parsed real_parts; |
| 421 AutocompleteInput::Parse(real_url, desired_tld, &real_parts, NULL, NULL); | 414 AutocompleteInput::Parse(real_url, desired_tld, &real_parts, NULL, NULL); |
| 422 if (real_parts.scheme.is_nonempty() || real_parts.host.is_nonempty()) { | 415 if (real_parts.scheme.is_nonempty() || real_parts.host.is_nonempty()) { |
| 423 if (real_parts.scheme.is_nonempty()) { | 416 if (real_parts.scheme.is_nonempty()) { |
| 424 *scheme = url_parse::Component( | 417 *scheme = url_parse::Component( |
| 425 after_scheme_and_colon + real_parts.scheme.begin, | 418 after_scheme_and_colon + real_parts.scheme.begin, |
| 426 real_parts.scheme.len); | 419 real_parts.scheme.len); |
| 427 } else { | 420 } else { |
| 428 scheme->reset(); | 421 scheme->reset(); |
| 429 } | 422 } |
| 430 if (real_parts.host.is_nonempty()) { | 423 if (real_parts.host.is_nonempty()) { |
| 431 *host = url_parse::Component( | 424 *host = url_parse::Component( |
| 432 after_scheme_and_colon + real_parts.host.begin, | 425 after_scheme_and_colon + real_parts.host.begin, |
| 433 real_parts.host.len); | 426 real_parts.host.len); |
| 434 } else { | 427 } else { |
| 435 host->reset(); | 428 host->reset(); |
| 436 } | 429 } |
| 437 } | 430 } |
| 438 } | 431 } |
| 439 } | 432 } |
| 440 | 433 |
| 441 // static | 434 // static |
| 442 string16 AutocompleteInput::FormattedStringWithEquivalentMeaning( | 435 std::wstring AutocompleteInput::FormattedStringWithEquivalentMeaning( |
| 443 const GURL& url, | 436 const GURL& url, |
| 444 const string16& formatted_url) { | 437 const std::wstring& formatted_url) { |
| 445 if (!net::CanStripTrailingSlash(url)) | 438 if (!net::CanStripTrailingSlash(url)) |
| 446 return formatted_url; | 439 return formatted_url; |
| 447 const string16 url_with_path(formatted_url + char16('/')); | 440 const std::wstring url_with_path(formatted_url + L"/"); |
| 448 return (AutocompleteInput::Parse(formatted_url, string16(), NULL, NULL, | 441 return (AutocompleteInput::Parse(formatted_url, std::wstring(), NULL, NULL, |
| 449 NULL) == | 442 NULL) == |
| 450 AutocompleteInput::Parse(url_with_path, string16(), NULL, NULL, | 443 AutocompleteInput::Parse(url_with_path, std::wstring(), NULL, NULL, |
| 451 NULL)) ? | 444 NULL)) ? |
| 452 formatted_url : url_with_path; | 445 formatted_url : url_with_path; |
| 453 } | 446 } |
| 454 | 447 |
| 455 | 448 |
| 456 bool AutocompleteInput::Equals(const AutocompleteInput& other) const { | 449 bool AutocompleteInput::Equals(const AutocompleteInput& other) const { |
| 457 return (text_ == other.text_) && | 450 return (text_ == other.text_) && |
| 458 (type_ == other.type_) && | 451 (type_ == other.type_) && |
| 459 (desired_tld_ == other.desired_tld_) && | 452 (desired_tld_ == other.desired_tld_) && |
| 460 (scheme_ == other.scheme_) && | 453 (scheme_ == other.scheme_) && |
| (...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 501 } | 494 } |
| 502 | 495 |
| 503 void AutocompleteProvider::DeleteMatch(const AutocompleteMatch& match) { | 496 void AutocompleteProvider::DeleteMatch(const AutocompleteMatch& match) { |
| 504 } | 497 } |
| 505 | 498 |
| 506 AutocompleteProvider::~AutocompleteProvider() { | 499 AutocompleteProvider::~AutocompleteProvider() { |
| 507 Stop(); | 500 Stop(); |
| 508 } | 501 } |
| 509 | 502 |
| 510 // static | 503 // static |
| 511 bool AutocompleteProvider::HasHTTPScheme(const string16& input) { | 504 bool AutocompleteProvider::HasHTTPScheme(const std::wstring& input) { |
| 512 std::string utf8_input(UTF16ToUTF8(input)); | 505 std::string utf8_input(WideToUTF8(input)); |
| 513 url_parse::Component scheme; | 506 url_parse::Component scheme; |
| 514 if (url_util::FindAndCompareScheme(utf8_input, chrome::kViewSourceScheme, | 507 if (url_util::FindAndCompareScheme(utf8_input, chrome::kViewSourceScheme, |
| 515 &scheme)) | 508 &scheme)) |
| 516 utf8_input.erase(0, scheme.end() + 1); | 509 utf8_input.erase(0, scheme.end() + 1); |
| 517 return url_util::FindAndCompareScheme(utf8_input, chrome::kHttpScheme, NULL); | 510 return url_util::FindAndCompareScheme(utf8_input, chrome::kHttpScheme, NULL); |
| 518 } | 511 } |
| 519 | 512 |
| 520 void AutocompleteProvider::UpdateStarredStateOfMatches() { | 513 void AutocompleteProvider::UpdateStarredStateOfMatches() { |
| 521 if (matches_.empty()) | 514 if (matches_.empty()) |
| 522 return; | 515 return; |
| 523 | 516 |
| 524 if (!profile_) | 517 if (!profile_) |
| 525 return; | 518 return; |
| 526 BookmarkModel* bookmark_model = profile_->GetBookmarkModel(); | 519 BookmarkModel* bookmark_model = profile_->GetBookmarkModel(); |
| 527 if (!bookmark_model || !bookmark_model->IsLoaded()) | 520 if (!bookmark_model || !bookmark_model->IsLoaded()) |
| 528 return; | 521 return; |
| 529 | 522 |
| 530 for (ACMatches::iterator i = matches_.begin(); i != matches_.end(); ++i) | 523 for (ACMatches::iterator i = matches_.begin(); i != matches_.end(); ++i) |
| 531 i->starred = bookmark_model->IsBookmarked(GURL(i->destination_url)); | 524 i->starred = bookmark_model->IsBookmarked(GURL(i->destination_url)); |
| 532 } | 525 } |
| 533 | 526 |
| 534 string16 AutocompleteProvider::StringForURLDisplay(const GURL& url, | 527 std::wstring AutocompleteProvider::StringForURLDisplay(const GURL& url, |
| 535 bool check_accept_lang, | 528 bool check_accept_lang, |
| 536 bool trim_http) const { | 529 bool trim_http) const { |
| 537 std::string languages = (check_accept_lang && profile_) ? | 530 std::string languages = (check_accept_lang && profile_) ? |
| 538 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages) : std::string(); | 531 profile_->GetPrefs()->GetString(prefs::kAcceptLanguages) : std::string(); |
| 539 return net::FormatUrl( | 532 return UTF16ToWideHack(net::FormatUrl( |
| 540 url, | 533 url, |
| 541 languages, | 534 languages, |
| 542 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP), | 535 net::kFormatUrlOmitAll & ~(trim_http ? 0 : net::kFormatUrlOmitHTTP), |
| 543 UnescapeRule::SPACES, NULL, NULL, NULL); | 536 UnescapeRule::SPACES, NULL, NULL, NULL)); |
| 544 } | 537 } |
| 545 | 538 |
| 546 // AutocompleteResult --------------------------------------------------------- | 539 // AutocompleteResult --------------------------------------------------------- |
| 547 | 540 |
| 548 // static | 541 // static |
| 549 const size_t AutocompleteResult::kMaxMatches = 6; | 542 const size_t AutocompleteResult::kMaxMatches = 6; |
| 550 | 543 |
| 551 void AutocompleteResult::Selection::Clear() { | 544 void AutocompleteResult::Selection::Clear() { |
| 552 destination_url = GURL(); | 545 destination_url = GURL(); |
| 553 provider_affinity = NULL; | 546 provider_affinity = NULL; |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 713 } | 706 } |
| 714 | 707 |
| 715 void AutocompleteController::SetProfile(Profile* profile) { | 708 void AutocompleteController::SetProfile(Profile* profile) { |
| 716 Stop(true); | 709 Stop(true); |
| 717 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) | 710 for (ACProviders::iterator i(providers_.begin()); i != providers_.end(); ++i) |
| 718 (*i)->SetProfile(profile); | 711 (*i)->SetProfile(profile); |
| 719 input_.Clear(); // Ensure we don't try to do a "minimal_changes" query on a | 712 input_.Clear(); // Ensure we don't try to do a "minimal_changes" query on a |
| 720 // different profile. | 713 // different profile. |
| 721 } | 714 } |
| 722 | 715 |
| 723 void AutocompleteController::Start(const string16& text, | 716 void AutocompleteController::Start(const std::wstring& text, |
| 724 const string16& desired_tld, | 717 const std::wstring& desired_tld, |
| 725 bool prevent_inline_autocomplete, | 718 bool prevent_inline_autocomplete, |
| 726 bool prefer_keyword, | 719 bool prefer_keyword, |
| 727 bool allow_exact_keyword_match, | 720 bool allow_exact_keyword_match, |
| 728 bool synchronous_only) { | 721 bool synchronous_only) { |
| 729 const string16 old_input_text(input_.text()); | 722 const std::wstring old_input_text(input_.text()); |
| 730 const bool old_synchronous_only = input_.synchronous_only(); | 723 const bool old_synchronous_only = input_.synchronous_only(); |
| 731 input_ = AutocompleteInput(text, desired_tld, prevent_inline_autocomplete, | 724 input_ = AutocompleteInput(text, desired_tld, prevent_inline_autocomplete, |
| 732 prefer_keyword, allow_exact_keyword_match, synchronous_only); | 725 prefer_keyword, allow_exact_keyword_match, synchronous_only); |
| 733 | 726 |
| 734 // See if we can avoid rerunning autocomplete when the query hasn't changed | 727 // See if we can avoid rerunning autocomplete when the query hasn't changed |
| 735 // much. When the user presses or releases the ctrl key, the desired_tld | 728 // much. When the user presses or releases the ctrl key, the desired_tld |
| 736 // changes, and when the user finishes an IME composition, inline autocomplete | 729 // changes, and when the user finishes an IME composition, inline autocomplete |
| 737 // may no longer be prevented. In both these cases the text itself hasn't | 730 // may no longer be prevented. In both these cases the text itself hasn't |
| 738 // changed since the last query, and some providers can do much less work (and | 731 // changed since the last query, and some providers can do much less work (and |
| 739 // get matches back more quickly). Taking advantage of this reduces flicker. | 732 // get matches back more quickly). Taking advantage of this reduces flicker. |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 895 void AutocompleteController::CheckIfDone() { | 888 void AutocompleteController::CheckIfDone() { |
| 896 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); | 889 for (ACProviders::const_iterator i(providers_.begin()); i != providers_.end(); |
| 897 ++i) { | 890 ++i) { |
| 898 if (!(*i)->done()) { | 891 if (!(*i)->done()) { |
| 899 done_ = false; | 892 done_ = false; |
| 900 return; | 893 return; |
| 901 } | 894 } |
| 902 } | 895 } |
| 903 done_ = true; | 896 done_ = true; |
| 904 } | 897 } |
| OLD | NEW |