| 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 | 9 |
| 10 #include "base/basictypes.h" | 10 #include "base/basictypes.h" |
| (...skipping 94 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 105 DISALLOW_COPY_AND_ASSIGN(V8ExternalStringFromScriptData); | 105 DISALLOW_COPY_AND_ASSIGN(V8ExternalStringFromScriptData); |
| 106 }; | 106 }; |
| 107 | 107 |
| 108 // External string wrapper so V8 can access a string literal. | 108 // External string wrapper so V8 can access a string literal. |
| 109 class V8ExternalASCIILiteral : public v8::String::ExternalAsciiStringResource { | 109 class V8ExternalASCIILiteral : public v8::String::ExternalAsciiStringResource { |
| 110 public: | 110 public: |
| 111 // |ascii| must be a NULL-terminated C string, and must remain valid | 111 // |ascii| must be a NULL-terminated C string, and must remain valid |
| 112 // throughout this object's lifetime. | 112 // throughout this object's lifetime. |
| 113 V8ExternalASCIILiteral(const char* ascii, size_t length) | 113 V8ExternalASCIILiteral(const char* ascii, size_t length) |
| 114 : ascii_(ascii), length_(length) { | 114 : ascii_(ascii), length_(length) { |
| 115 DCHECK(IsStringASCII(ascii)); | 115 DCHECK(base::IsStringASCII(ascii)); |
| 116 } | 116 } |
| 117 | 117 |
| 118 virtual const char* data() const OVERRIDE { | 118 virtual const char* data() const OVERRIDE { |
| 119 return ascii_; | 119 return ascii_; |
| 120 } | 120 } |
| 121 | 121 |
| 122 virtual size_t length() const OVERRIDE { | 122 virtual size_t length() const OVERRIDE { |
| 123 return length_; | 123 return length_; |
| 124 } | 124 } |
| 125 | 125 |
| (...skipping 26 matching lines...) Expand all Loading... |
| 152 // Note that the reinterpret cast is because on Windows string16 is an alias | 152 // Note that the reinterpret cast is because on Windows string16 is an alias |
| 153 // to wstring, and hence has character type wchar_t not uint16_t. | 153 // to wstring, and hence has character type wchar_t not uint16_t. |
| 154 if (len > 0) | 154 if (len > 0) |
| 155 s->Write(reinterpret_cast<uint16_t*>(WriteInto(&result, len + 1)), 0, len); | 155 s->Write(reinterpret_cast<uint16_t*>(WriteInto(&result, len + 1)), 0, len); |
| 156 return result; | 156 return result; |
| 157 } | 157 } |
| 158 | 158 |
| 159 // Converts an ASCII std::string to a V8 string. | 159 // Converts an ASCII std::string to a V8 string. |
| 160 v8::Local<v8::String> ASCIIStringToV8String(v8::Isolate* isolate, | 160 v8::Local<v8::String> ASCIIStringToV8String(v8::Isolate* isolate, |
| 161 const std::string& s) { | 161 const std::string& s) { |
| 162 DCHECK(IsStringASCII(s)); | 162 DCHECK(base::IsStringASCII(s)); |
| 163 return v8::String::NewFromUtf8(isolate, s.data(), v8::String::kNormalString, | 163 return v8::String::NewFromUtf8(isolate, s.data(), v8::String::kNormalString, |
| 164 s.size()); | 164 s.size()); |
| 165 } | 165 } |
| 166 | 166 |
| 167 // Converts a UTF16 base::string16 (warpped by a ProxyResolverScriptData) to a | 167 // Converts a UTF16 base::string16 (warpped by a ProxyResolverScriptData) to a |
| 168 // V8 string. | 168 // V8 string. |
| 169 v8::Local<v8::String> ScriptDataToV8String( | 169 v8::Local<v8::String> ScriptDataToV8String( |
| 170 v8::Isolate* isolate, const scoped_refptr<ProxyResolverScriptData>& s) { | 170 v8::Isolate* isolate, const scoped_refptr<ProxyResolverScriptData>& s) { |
| 171 if (s->utf16().size() * 2 <= kMaxStringBytesForCopy) { | 171 if (s->utf16().size() * 2 <= kMaxStringBytesForCopy) { |
| 172 return v8::String::NewFromTwoByte( | 172 return v8::String::NewFromTwoByte( |
| 173 isolate, | 173 isolate, |
| 174 reinterpret_cast<const uint16_t*>(s->utf16().data()), | 174 reinterpret_cast<const uint16_t*>(s->utf16().data()), |
| 175 v8::String::kNormalString, | 175 v8::String::kNormalString, |
| 176 s->utf16().size()); | 176 s->utf16().size()); |
| 177 } | 177 } |
| 178 return v8::String::NewExternal(isolate, | 178 return v8::String::NewExternal(isolate, |
| 179 new V8ExternalStringFromScriptData(s)); | 179 new V8ExternalStringFromScriptData(s)); |
| 180 } | 180 } |
| 181 | 181 |
| 182 // Converts an ASCII string literal to a V8 string. | 182 // Converts an ASCII string literal to a V8 string. |
| 183 v8::Local<v8::String> ASCIILiteralToV8String(v8::Isolate* isolate, | 183 v8::Local<v8::String> ASCIILiteralToV8String(v8::Isolate* isolate, |
| 184 const char* ascii) { | 184 const char* ascii) { |
| 185 DCHECK(IsStringASCII(ascii)); | 185 DCHECK(base::IsStringASCII(ascii)); |
| 186 size_t length = strlen(ascii); | 186 size_t length = strlen(ascii); |
| 187 if (length <= kMaxStringBytesForCopy) | 187 if (length <= kMaxStringBytesForCopy) |
| 188 return v8::String::NewFromUtf8(isolate, ascii, v8::String::kNormalString, | 188 return v8::String::NewFromUtf8(isolate, ascii, v8::String::kNormalString, |
| 189 length); | 189 length); |
| 190 return v8::String::NewExternal(isolate, | 190 return v8::String::NewExternal(isolate, |
| 191 new V8ExternalASCIILiteral(ascii, length)); | 191 new V8ExternalASCIILiteral(ascii, length)); |
| 192 } | 192 } |
| 193 | 193 |
| 194 // Stringizes a V8 object by calling its toString() method. Returns true | 194 // Stringizes a V8 object by calling its toString() method. Returns true |
| 195 // on success. This may fail if the toString() throws an exception. | 195 // on success. This may fail if the toString() throws an exception. |
| (...skipping 15 matching lines...) Expand all Loading... |
| 211 // and fills |*hostname| with the result. | 211 // and fills |*hostname| with the result. |
| 212 bool GetHostnameArgument(const v8::FunctionCallbackInfo<v8::Value>& args, | 212 bool GetHostnameArgument(const v8::FunctionCallbackInfo<v8::Value>& args, |
| 213 std::string* hostname) { | 213 std::string* hostname) { |
| 214 // The first argument should be a string. | 214 // The first argument should be a string. |
| 215 if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) | 215 if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) |
| 216 return false; | 216 return false; |
| 217 | 217 |
| 218 const base::string16 hostname_utf16 = V8StringToUTF16(args[0]->ToString()); | 218 const base::string16 hostname_utf16 = V8StringToUTF16(args[0]->ToString()); |
| 219 | 219 |
| 220 // If the hostname is already in ASCII, simply return it as is. | 220 // If the hostname is already in ASCII, simply return it as is. |
| 221 if (IsStringASCII(hostname_utf16)) { | 221 if (base::IsStringASCII(hostname_utf16)) { |
| 222 *hostname = base::UTF16ToASCII(hostname_utf16); | 222 *hostname = base::UTF16ToASCII(hostname_utf16); |
| 223 return true; | 223 return true; |
| 224 } | 224 } |
| 225 | 225 |
| 226 // Otherwise try to convert it from IDN to punycode. | 226 // Otherwise try to convert it from IDN to punycode. |
| 227 const int kInitialBufferSize = 256; | 227 const int kInitialBufferSize = 256; |
| 228 url::RawCanonOutputT<base::char16, kInitialBufferSize> punycode_output; | 228 url::RawCanonOutputT<base::char16, kInitialBufferSize> punycode_output; |
| 229 if (!url::IDNToASCII(hostname_utf16.data(), hostname_utf16.length(), | 229 if (!url::IDNToASCII(hostname_utf16.data(), hostname_utf16.length(), |
| 230 &punycode_output)) { | 230 &punycode_output)) { |
| 231 return false; | 231 return false; |
| 232 } | 232 } |
| 233 | 233 |
| 234 // |punycode_output| should now be ASCII; convert it to a std::string. | 234 // |punycode_output| should now be ASCII; convert it to a std::string. |
| 235 // (We could use UTF16ToASCII() instead, but that requires an extra string | 235 // (We could use UTF16ToASCII() instead, but that requires an extra string |
| 236 // copy. Since ASCII is a subset of UTF8 the following is equivalent). | 236 // copy. Since ASCII is a subset of UTF8 the following is equivalent). |
| 237 bool success = base::UTF16ToUTF8(punycode_output.data(), | 237 bool success = base::UTF16ToUTF8(punycode_output.data(), |
| 238 punycode_output.length(), | 238 punycode_output.length(), |
| 239 hostname); | 239 hostname); |
| 240 DCHECK(success); | 240 DCHECK(success); |
| 241 DCHECK(IsStringASCII(*hostname)); | 241 DCHECK(base::IsStringASCII(*hostname)); |
| 242 return success; | 242 return success; |
| 243 } | 243 } |
| 244 | 244 |
| 245 // Wrapper for passing around IP address strings and IPAddressNumber objects. | 245 // Wrapper for passing around IP address strings and IPAddressNumber objects. |
| 246 struct IPAddress { | 246 struct IPAddress { |
| 247 IPAddress(const std::string& ip_string, const IPAddressNumber& ip_number) | 247 IPAddress(const std::string& ip_string, const IPAddressNumber& ip_number) |
| 248 : string_value(ip_string), | 248 : string_value(ip_string), |
| 249 ip_address_number(ip_number) { | 249 ip_address_number(ip_number) { |
| 250 } | 250 } |
| 251 | 251 |
| (...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 392 } | 392 } |
| 393 | 393 |
| 394 if (!ret->IsString()) { | 394 if (!ret->IsString()) { |
| 395 js_bindings()->OnError( | 395 js_bindings()->OnError( |
| 396 -1, base::ASCIIToUTF16("FindProxyForURL() did not return a string.")); | 396 -1, base::ASCIIToUTF16("FindProxyForURL() did not return a string.")); |
| 397 return ERR_PAC_SCRIPT_FAILED; | 397 return ERR_PAC_SCRIPT_FAILED; |
| 398 } | 398 } |
| 399 | 399 |
| 400 base::string16 ret_str = V8StringToUTF16(ret->ToString()); | 400 base::string16 ret_str = V8StringToUTF16(ret->ToString()); |
| 401 | 401 |
| 402 if (!IsStringASCII(ret_str)) { | 402 if (!base::IsStringASCII(ret_str)) { |
| 403 // TODO(eroman): Rather than failing when a wide string is returned, we | 403 // TODO(eroman): Rather than failing when a wide string is returned, we |
| 404 // could extend the parsing to handle IDNA hostnames by | 404 // could extend the parsing to handle IDNA hostnames by |
| 405 // converting them to ASCII punycode. | 405 // converting them to ASCII punycode. |
| 406 // crbug.com/47234 | 406 // crbug.com/47234 |
| 407 base::string16 error_message = | 407 base::string16 error_message = |
| 408 base::ASCIIToUTF16("FindProxyForURL() returned a non-ASCII string " | 408 base::ASCIIToUTF16("FindProxyForURL() returned a non-ASCII string " |
| 409 "(crbug.com/47234): ") + ret_str; | 409 "(crbug.com/47234): ") + ret_str; |
| 410 js_bindings()->OnError(-1, error_message); | 410 js_bindings()->OnError(-1, error_message); |
| 411 return ERR_PAC_SCRIPT_FAILED; | 411 return ERR_PAC_SCRIPT_FAILED; |
| 412 } | 412 } |
| (...skipping 241 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 654 // V8 callback for when "sortIpAddressList()" is invoked by the PAC script. | 654 // V8 callback for when "sortIpAddressList()" is invoked by the PAC script. |
| 655 static void SortIpAddressListCallback( | 655 static void SortIpAddressListCallback( |
| 656 const v8::FunctionCallbackInfo<v8::Value>& args) { | 656 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 657 // We need at least one string argument. | 657 // We need at least one string argument. |
| 658 if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) { | 658 if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) { |
| 659 args.GetReturnValue().SetNull(); | 659 args.GetReturnValue().SetNull(); |
| 660 return; | 660 return; |
| 661 } | 661 } |
| 662 | 662 |
| 663 std::string ip_address_list = V8StringToUTF8(args[0]->ToString()); | 663 std::string ip_address_list = V8StringToUTF8(args[0]->ToString()); |
| 664 if (!IsStringASCII(ip_address_list)) { | 664 if (!base::IsStringASCII(ip_address_list)) { |
| 665 args.GetReturnValue().SetNull(); | 665 args.GetReturnValue().SetNull(); |
| 666 return; | 666 return; |
| 667 } | 667 } |
| 668 std::string sorted_ip_address_list; | 668 std::string sorted_ip_address_list; |
| 669 bool success = SortIpAddressList(ip_address_list, &sorted_ip_address_list); | 669 bool success = SortIpAddressList(ip_address_list, &sorted_ip_address_list); |
| 670 if (!success) { | 670 if (!success) { |
| 671 args.GetReturnValue().Set(false); | 671 args.GetReturnValue().Set(false); |
| 672 return; | 672 return; |
| 673 } | 673 } |
| 674 args.GetReturnValue().Set( | 674 args.GetReturnValue().Set( |
| 675 ASCIIStringToV8String(args.GetIsolate(), sorted_ip_address_list)); | 675 ASCIIStringToV8String(args.GetIsolate(), sorted_ip_address_list)); |
| 676 } | 676 } |
| 677 | 677 |
| 678 // V8 callback for when "isInNetEx()" is invoked by the PAC script. | 678 // V8 callback for when "isInNetEx()" is invoked by the PAC script. |
| 679 static void IsInNetExCallback( | 679 static void IsInNetExCallback( |
| 680 const v8::FunctionCallbackInfo<v8::Value>& args) { | 680 const v8::FunctionCallbackInfo<v8::Value>& args) { |
| 681 // We need at least 2 string arguments. | 681 // We need at least 2 string arguments. |
| 682 if (args.Length() < 2 || args[0].IsEmpty() || !args[0]->IsString() || | 682 if (args.Length() < 2 || args[0].IsEmpty() || !args[0]->IsString() || |
| 683 args[1].IsEmpty() || !args[1]->IsString()) { | 683 args[1].IsEmpty() || !args[1]->IsString()) { |
| 684 args.GetReturnValue().SetNull(); | 684 args.GetReturnValue().SetNull(); |
| 685 return; | 685 return; |
| 686 } | 686 } |
| 687 | 687 |
| 688 std::string ip_address = V8StringToUTF8(args[0]->ToString()); | 688 std::string ip_address = V8StringToUTF8(args[0]->ToString()); |
| 689 if (!IsStringASCII(ip_address)) { | 689 if (!base::IsStringASCII(ip_address)) { |
| 690 args.GetReturnValue().Set(false); | 690 args.GetReturnValue().Set(false); |
| 691 return; | 691 return; |
| 692 } | 692 } |
| 693 std::string ip_prefix = V8StringToUTF8(args[1]->ToString()); | 693 std::string ip_prefix = V8StringToUTF8(args[1]->ToString()); |
| 694 if (!IsStringASCII(ip_prefix)) { | 694 if (!base::IsStringASCII(ip_prefix)) { |
| 695 args.GetReturnValue().Set(false); | 695 args.GetReturnValue().Set(false); |
| 696 return; | 696 return; |
| 697 } | 697 } |
| 698 args.GetReturnValue().Set(IsInNetEx(ip_address, ip_prefix)); | 698 args.GetReturnValue().Set(IsInNetEx(ip_address, ip_prefix)); |
| 699 } | 699 } |
| 700 | 700 |
| 701 mutable base::Lock lock_; | 701 mutable base::Lock lock_; |
| 702 ProxyResolverV8* parent_; | 702 ProxyResolverV8* parent_; |
| 703 v8::Isolate* isolate_; | 703 v8::Isolate* isolate_; |
| 704 v8::Persistent<v8::External> v8_this_; | 704 v8::Persistent<v8::External> v8_this_; |
| (...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 800 return 0; | 800 return 0; |
| 801 | 801 |
| 802 v8::Locker locked(g_proxy_resolver_isolate_->isolate()); | 802 v8::Locker locked(g_proxy_resolver_isolate_->isolate()); |
| 803 v8::Isolate::Scope isolate_scope(g_proxy_resolver_isolate_->isolate()); | 803 v8::Isolate::Scope isolate_scope(g_proxy_resolver_isolate_->isolate()); |
| 804 v8::HeapStatistics heap_statistics; | 804 v8::HeapStatistics heap_statistics; |
| 805 g_proxy_resolver_isolate_->isolate()->GetHeapStatistics(&heap_statistics); | 805 g_proxy_resolver_isolate_->isolate()->GetHeapStatistics(&heap_statistics); |
| 806 return heap_statistics.used_heap_size(); | 806 return heap_statistics.used_heap_size(); |
| 807 } | 807 } |
| 808 | 808 |
| 809 } // namespace net | 809 } // namespace net |
| OLD | NEW |