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(base::IsStringASCII(ascii)); | 113 DCHECK(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(base::IsStringASCII(s)); | 160 DCHECK(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(base::IsStringASCII(ascii)); | 183 DCHECK(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 (base::IsStringASCII(hostname_utf16)) { | 219 if (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(base::IsStringASCII(*hostname)); | 240 DCHECK(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 (!base::IsStringASCII(ret_str)) { | 401 if (!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 (!base::IsStringASCII(ip_address_list)) { | 663 if (!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 (!base::IsStringASCII(ip_address)) { | 688 if (!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 (!base::IsStringASCII(ip_prefix)) { | 693 if (!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 |