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