Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 "net/proxy/proxy_resolver_v8.h" | 5 #include "net/proxy/proxy_resolver_v8.h" |
| 6 | 6 |
| 7 #include <algorithm> | 7 #include <algorithm> |
| 8 #include <cstdio> | 8 #include <cstdio> |
| 9 #include <utility> | 9 #include <utility> |
| 10 | 10 |
| 11 #include "base/auto_reset.h" | 11 #include "base/auto_reset.h" |
| 12 #include "base/compiler_specific.h" | 12 #include "base/compiler_specific.h" |
| 13 #include "base/debug/leak_annotations.h" | 13 #include "base/debug/leak_annotations.h" |
| 14 #include "base/lazy_instance.h" | 14 #include "base/lazy_instance.h" |
| 15 #include "base/logging.h" | 15 #include "base/logging.h" |
| 16 #include "base/macros.h" | 16 #include "base/macros.h" |
| 17 #include "base/strings/string_tokenizer.h" | 17 #include "base/strings/string_tokenizer.h" |
| 18 #include "base/strings/string_util.h" | 18 #include "base/strings/string_util.h" |
| 19 #include "base/strings/utf_string_conversions.h" | 19 #include "base/strings/utf_string_conversions.h" |
| 20 #include "base/synchronization/lock.h" | 20 #include "base/synchronization/lock.h" |
| 21 #include "gin/array_buffer.h" | 21 #include "gin/array_buffer.h" |
| 22 #include "gin/public/isolate_holder.h" | 22 #include "gin/public/isolate_holder.h" |
| 23 #include "gin/v8_initializer.h" | 23 #include "gin/v8_initializer.h" |
| 24 #include "net/base/ip_address_number.h" | 24 #include "net/base/ip_address.h" |
| 25 #include "net/base/net_errors.h" | 25 #include "net/base/net_errors.h" |
| 26 #include "net/proxy/proxy_info.h" | 26 #include "net/proxy/proxy_info.h" |
| 27 #include "net/proxy/proxy_resolver_script.h" | 27 #include "net/proxy/proxy_resolver_script.h" |
| 28 #include "net/proxy/proxy_resolver_script_data.h" | 28 #include "net/proxy/proxy_resolver_script_data.h" |
| 29 #include "url/gurl.h" | 29 #include "url/gurl.h" |
| 30 #include "url/url_canon.h" | 30 #include "url/url_canon.h" |
| 31 #include "v8/include/v8.h" | 31 #include "v8/include/v8.h" |
| 32 | 32 |
| 33 // Notes on the javascript environment: | 33 // Notes on the javascript environment: |
| 34 // | 34 // |
| (...skipping 202 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 237 // (We could use UTF16ToASCII() instead, but that requires an extra string | 237 // (We could use UTF16ToASCII() instead, but that requires an extra string |
| 238 // copy. Since ASCII is a subset of UTF8 the following is equivalent). | 238 // copy. Since ASCII is a subset of UTF8 the following is equivalent). |
| 239 bool success = base::UTF16ToUTF8(punycode_output.data(), | 239 bool success = base::UTF16ToUTF8(punycode_output.data(), |
| 240 punycode_output.length(), | 240 punycode_output.length(), |
| 241 hostname); | 241 hostname); |
| 242 DCHECK(success); | 242 DCHECK(success); |
| 243 DCHECK(base::IsStringASCII(*hostname)); | 243 DCHECK(base::IsStringASCII(*hostname)); |
| 244 return success; | 244 return success; |
| 245 } | 245 } |
| 246 | 246 |
| 247 // Wrapper for passing around IP address strings and IPAddressNumber objects. | 247 // Wrapper around an IP address that stores the original string as well as a |
| 248 struct IPAddress { | 248 // corresponding parsed IPAddress. |
| 249 IPAddress(const std::string& ip_string, const IPAddressNumber& ip_number) | 249 |
| 250 : string_value(ip_string), | 250 // This struct is used as a helper for sorting IP address strings - the IP |
| 251 ip_address_number(ip_number) { | 251 // literal is parsed just once and used as the sorting key, while also |
| 252 } | 252 // preserving the original IP literal string. |
| 253 struct IPAddressSortingEntry { | |
| 254 IPAddressSortingEntry(const std::string& ip_string, | |
| 255 const IPAddress& ip_address) | |
| 256 : string_value(ip_string), ip_address(ip_address) {} | |
| 253 | 257 |
| 254 // Used for sorting IP addresses in ascending order in SortIpAddressList(). | 258 // Used for sorting IP addresses in ascending order in SortIpAddressList(). |
| 255 // IP6 addresses are placed ahead of IPv4 addresses. | 259 // IP6 addresses are placed ahead of IPv4 addresses. |
|
eroman
2016/03/18 23:52:17
Can you fix IP6 --> IPv6 while you are here? Thank
martijnc
2016/03/19 12:06:07
Done.
| |
| 256 bool operator<(const IPAddress& rhs) const { | 260 bool operator<(const IPAddressSortingEntry& rhs) const { |
| 257 const IPAddressNumber& ip1 = this->ip_address_number; | 261 const IPAddress& ip1 = this->ip_address; |
| 258 const IPAddressNumber& ip2 = rhs.ip_address_number; | 262 const IPAddress& ip2 = rhs.ip_address; |
| 259 if (ip1.size() != ip2.size()) | 263 if (ip1.size() != ip2.size()) |
| 260 return ip1.size() > ip2.size(); // IPv6 before IPv4. | 264 return ip1.size() > ip2.size(); // IPv6 before IPv4. |
| 261 DCHECK(ip1.size() == ip2.size()); | 265 DCHECK(ip1.size() == ip2.size()); |
|
eroman
2016/03/18 23:52:17
Can remove this DCHECK as it doesn't serve a purpo
martijnc
2016/03/19 12:06:07
Done.
| |
| 262 return memcmp(&ip1[0], &ip2[0], ip1.size()) < 0; // Ascending order. | 266 return ip1 < ip2; // Ascending order. |
| 263 } | 267 } |
| 264 | 268 |
| 265 std::string string_value; | 269 std::string string_value; |
| 266 IPAddressNumber ip_address_number; | 270 IPAddress ip_address; |
| 267 }; | 271 }; |
| 268 | 272 |
| 269 // Handler for "sortIpAddressList(IpAddressList)". |ip_address_list| is a | 273 // Handler for "sortIpAddressList(IpAddressList)". |ip_address_list| is a |
| 270 // semi-colon delimited string containing IP addresses. | 274 // semi-colon delimited string containing IP addresses. |
| 271 // |sorted_ip_address_list| is the resulting list of sorted semi-colon delimited | 275 // |sorted_ip_address_list| is the resulting list of sorted semi-colon delimited |
| 272 // IP addresses or an empty string if unable to sort the IP address list. | 276 // IP addresses or an empty string if unable to sort the IP address list. |
| 273 // Returns 'true' if the sorting was successful, and 'false' if the input was an | 277 // Returns 'true' if the sorting was successful, and 'false' if the input was an |
| 274 // empty string, a string of separators (";" in this case), or if any of the IP | 278 // empty string, a string of separators (";" in this case), or if any of the IP |
| 275 // addresses in the input list failed to parse. | 279 // addresses in the input list failed to parse. |
| 276 bool SortIpAddressList(const std::string& ip_address_list, | 280 bool SortIpAddressList(const std::string& ip_address_list, |
| 277 std::string* sorted_ip_address_list) { | 281 std::string* sorted_ip_address_list) { |
| 278 sorted_ip_address_list->clear(); | 282 sorted_ip_address_list->clear(); |
| 279 | 283 |
| 280 // Strip all whitespace (mimics IE behavior). | 284 // Strip all whitespace (mimics IE behavior). |
| 281 std::string cleaned_ip_address_list; | 285 std::string cleaned_ip_address_list; |
| 282 base::RemoveChars(ip_address_list, " \t", &cleaned_ip_address_list); | 286 base::RemoveChars(ip_address_list, " \t", &cleaned_ip_address_list); |
| 283 if (cleaned_ip_address_list.empty()) | 287 if (cleaned_ip_address_list.empty()) |
| 284 return false; | 288 return false; |
| 285 | 289 |
| 286 // Split-up IP addresses and store them in a vector. | 290 // Split-up IP addresses and store them in a vector. |
| 287 std::vector<IPAddress> ip_vector; | 291 std::vector<IPAddressSortingEntry> ip_vector; |
| 288 IPAddressNumber ip_num; | 292 IPAddress ip_address; |
| 289 base::StringTokenizer str_tok(cleaned_ip_address_list, ";"); | 293 base::StringTokenizer str_tok(cleaned_ip_address_list, ";"); |
| 290 while (str_tok.GetNext()) { | 294 while (str_tok.GetNext()) { |
| 291 if (!ParseIPLiteralToNumber(str_tok.token(), &ip_num)) | 295 if (!ip_address.AssignFromIPLiteral(str_tok.token())) |
| 292 return false; | 296 return false; |
| 293 ip_vector.push_back(IPAddress(str_tok.token(), ip_num)); | 297 ip_vector.push_back(IPAddressSortingEntry(str_tok.token(), ip_address)); |
| 294 } | 298 } |
| 295 | 299 |
| 296 if (ip_vector.empty()) // Can happen if we have something like | 300 if (ip_vector.empty()) // Can happen if we have something like |
| 297 return false; // sortIpAddressList(";") or sortIpAddressList("; ;") | 301 return false; // sortIpAddressList(";") or sortIpAddressList("; ;") |
| 298 | 302 |
| 299 DCHECK(!ip_vector.empty()); | 303 DCHECK(!ip_vector.empty()); |
| 300 | 304 |
| 301 // Sort lists according to ascending numeric value. | 305 // Sort lists according to ascending numeric value. |
| 302 if (ip_vector.size() > 1) | 306 if (ip_vector.size() > 1) |
| 303 std::stable_sort(ip_vector.begin(), ip_vector.end()); | 307 std::stable_sort(ip_vector.begin(), ip_vector.end()); |
| 304 | 308 |
| 305 // Return a semi-colon delimited list of sorted addresses (IPv6 followed by | 309 // Return a semi-colon delimited list of sorted addresses (IPv6 followed by |
| 306 // IPv4). | 310 // IPv4). |
| 307 for (size_t i = 0; i < ip_vector.size(); ++i) { | 311 for (size_t i = 0; i < ip_vector.size(); ++i) { |
| 308 if (i > 0) | 312 if (i > 0) |
| 309 *sorted_ip_address_list += ";"; | 313 *sorted_ip_address_list += ";"; |
| 310 *sorted_ip_address_list += ip_vector[i].string_value; | 314 *sorted_ip_address_list += ip_vector[i].string_value; |
| 311 } | 315 } |
| 312 return true; | 316 return true; |
| 313 } | 317 } |
| 314 | 318 |
| 315 // Handler for "isInNetEx(ip_address, ip_prefix)". |ip_address| is a string | 319 // Handler for "isInNetEx(ip_address, ip_prefix)". |ip_address| is a string |
| 316 // containing an IPv4/IPv6 address, and |ip_prefix| is a string containg a | 320 // containing an IPv4/IPv6 address, and |ip_prefix| is a string containg a |
| 317 // slash-delimited IP prefix with the top 'n' bits specified in the bit | 321 // slash-delimited IP prefix with the top 'n' bits specified in the bit |
| 318 // field. This returns 'true' if the address is in the same subnet, and | 322 // field. This returns 'true' if the address is in the same subnet, and |
| 319 // 'false' otherwise. Also returns 'false' if the prefix is in an incorrect | 323 // 'false' otherwise. Also returns 'false' if the prefix is in an incorrect |
| 320 // format, or if an address and prefix of different types are used (e.g. IPv6 | 324 // format, or if an address and prefix of different types are used (e.g. IPv6 |
| 321 // address and IPv4 prefix). | 325 // address and IPv4 prefix). |
| 322 bool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) { | 326 bool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) { |
| 323 IPAddressNumber address; | 327 IPAddress address; |
| 324 if (!ParseIPLiteralToNumber(ip_address, &address)) | 328 if (!address.AssignFromIPLiteral(ip_address)) |
| 325 return false; | 329 return false; |
| 326 | 330 |
| 327 IPAddressNumber prefix; | 331 IPAddress prefix; |
| 328 size_t prefix_length_in_bits; | 332 size_t prefix_length_in_bits; |
| 329 if (!ParseCIDRBlock(ip_prefix, &prefix, &prefix_length_in_bits)) | 333 if (!ParseCIDRBlock(ip_prefix, &prefix, &prefix_length_in_bits)) |
| 330 return false; | 334 return false; |
| 331 | 335 |
| 332 // Both |address| and |prefix| must be of the same type (IPv4 or IPv6). | 336 // Both |address| and |prefix| must be of the same type (IPv4 or IPv6). |
| 333 if (address.size() != prefix.size()) | 337 if (address.size() != prefix.size()) |
| 334 return false; | 338 return false; |
| 335 | 339 |
| 336 DCHECK((address.size() == 4 && prefix.size() == 4) || | 340 DCHECK((address.IsIPv4() && prefix.IsIPv4()) || |
| 337 (address.size() == 16 && prefix.size() == 16)); | 341 (address.IsIPv6() && prefix.IsIPv6())); |
| 338 | 342 |
| 339 return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits); | 343 return IPAddressMatchesPrefix(address, prefix, prefix_length_in_bits); |
| 340 } | 344 } |
| 341 | 345 |
| 342 // Consider only single component domains like 'foo' as plain host names. | 346 // Consider only single component domains like 'foo' as plain host names. |
| 343 bool IsPlainHostName(const std::string& hostname_utf8) { | 347 bool IsPlainHostName(const std::string& hostname_utf8) { |
| 344 if (hostname_utf8.find('.') != std::string::npos) | 348 if (hostname_utf8.find('.') != std::string::npos) |
| 345 return false; | 349 return false; |
| 346 | 350 |
| 347 // IPv6 literals might not contain any periods, however are not considered | 351 // IPv6 literals might not contain any periods, however are not considered |
| 348 // plain host names. | 352 // plain host names. |
| 349 IPAddressNumber unused; | 353 IPAddress unused; |
| 350 return !ParseIPLiteralToNumber(hostname_utf8, &unused); | 354 return !unused.AssignFromIPLiteral(hostname_utf8); |
| 351 } | 355 } |
| 352 | 356 |
| 353 // All instances of ProxyResolverV8 share the same v8::Isolate. This isolate is | 357 // All instances of ProxyResolverV8 share the same v8::Isolate. This isolate is |
| 354 // created lazily the first time it is needed and lives until process shutdown. | 358 // created lazily the first time it is needed and lives until process shutdown. |
| 355 // This creation might happen from any thread, as ProxyResolverV8 is typically | 359 // This creation might happen from any thread, as ProxyResolverV8 is typically |
| 356 // run in a threadpool. | 360 // run in a threadpool. |
| 357 // | 361 // |
| 358 // TODO(eroman): The lazily created isolate is never freed. Instead it should be | 362 // TODO(eroman): The lazily created isolate is never freed. Instead it should be |
| 359 // disposed once there are no longer any ProxyResolverV8 referencing it. | 363 // disposed once there are no longer any ProxyResolverV8 referencing it. |
| 360 class SharedIsolateFactory { | 364 class SharedIsolateFactory { |
| (...skipping 527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 888 return 0; | 892 return 0; |
| 889 | 893 |
| 890 v8::Locker locked(isolate); | 894 v8::Locker locked(isolate); |
| 891 v8::Isolate::Scope isolate_scope(isolate); | 895 v8::Isolate::Scope isolate_scope(isolate); |
| 892 v8::HeapStatistics heap_statistics; | 896 v8::HeapStatistics heap_statistics; |
| 893 isolate->GetHeapStatistics(&heap_statistics); | 897 isolate->GetHeapStatistics(&heap_statistics); |
| 894 return heap_statistics.used_heap_size(); | 898 return heap_statistics.used_heap_size(); |
| 895 } | 899 } |
| 896 | 900 |
| 897 } // namespace net | 901 } // namespace net |
| OLD | NEW |