15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver_v8.h"
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <algorithm>
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include <cstdio>
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/basictypes.h"
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/compiler_specific.h"
12c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "base/debug/leak_annotations.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_tokenizer.h"
157dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/string_util.h"
16868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
181320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci#include "gin/array_buffer.h"
19c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch#include "gin/public/isolate_holder.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_info.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver_script.h"
257dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
267dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/url_canon.h"
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "v8/include/v8.h"
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Notes on the javascript environment:
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For the majority of the PAC utility functions, we use the same code
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as Firefox. See the javascript library that proxy_resolver_scipt.h
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pulls in.
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In addition, we implement a subset of Microsoft's extensions to PAC.
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - myIpAddressEx()
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - dnsResolveEx()
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - isResolvableEx()
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - isInNetEx()
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - sortIpAddressList()
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is worth noting that the original PAC specification does not describe
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the return values on failure. Consequently, there are compatibility
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// differences between browsers on what to return on failure, which are
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// illustrated below:
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------+-------------+-------------------+--------------
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     | Firefox3    | InternetExplorer8 |  --> Us <---
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------+-------------+-------------------+--------------
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// myIpAddress()       | "127.0.0.1" |  ???              |  "127.0.0.1"
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dnsResolve()        | null        |  false            |  null
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// myIpAddressEx()     | N/A         |  ""               |  ""
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sortIpAddressList() | N/A         |  false            |  false
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dnsResolveEx()      | N/A         |  ""               |  ""
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// isInNetEx()         | N/A         |  false            |  false
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------+-------------+-------------------+--------------
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(eroman): The cell above reading ??? means I didn't test it.
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Another difference is in how dnsResolve() and myIpAddress() are
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// implemented -- whether they should restrict to IPv4 results, or
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// include both IPv4 and IPv6. The following table illustrates the
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// differences:
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------+-------------+-------------------+--------------
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     | Firefox3    | InternetExplorer8 |  --> Us <---
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------+-------------+-------------------+--------------
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// myIpAddress()       | IPv4/IPv6   |  IPv4             |  IPv4
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dnsResolve()        | IPv4/IPv6   |  IPv4             |  IPv4
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// isResolvable()      | IPv4/IPv6   |  IPv4             |  IPv4
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// myIpAddressEx()     | N/A         |  IPv4/IPv6        |  IPv4/IPv6
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dnsResolveEx()      | N/A         |  IPv4/IPv6        |  IPv4/IPv6
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sortIpAddressList() | N/A         |  IPv4/IPv6        |  IPv4/IPv6
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// isResolvableEx()    | N/A         |  IPv4/IPv6        |  IPv4/IPv6
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// isInNetEx()         | N/A         |  IPv4/IPv6        |  IPv4/IPv6
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------+-------------+-------------------+--------------
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pseudo-name for the PAC script.
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPacResourceName[] = "proxy-pac-script.js";
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pseudo-name for the PAC utility script.
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPacUtilityResourceName[] = "proxy-pac-utility-script.js";
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// External string wrapper so V8 can access the UTF16 string wrapped by
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyResolverScriptData.
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class V8ExternalStringFromScriptData
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public v8::String::ExternalStringResource {
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit V8ExternalStringFromScriptData(
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<ProxyResolverScriptData>& script_data)
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : script_data_(script_data) {}
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual const uint16_t* data() const OVERRIDE {
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<const uint16*>(script_data_->utf16().data());
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual size_t length() const OVERRIDE {
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return script_data_->utf16().size();
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const scoped_refptr<ProxyResolverScriptData> script_data_;
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(V8ExternalStringFromScriptData);
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// External string wrapper so V8 can access a string literal.
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class V8ExternalASCIILiteral : public v8::String::ExternalAsciiStringResource {
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |ascii| must be a NULL-terminated C string, and must remain valid
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // throughout this object's lifetime.
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ExternalASCIILiteral(const char* ascii, size_t length)
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ascii_(ascii), length_(length) {
116010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    DCHECK(base::IsStringASCII(ascii));
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual const char* data() const OVERRIDE {
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ascii_;
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual size_t length() const OVERRIDE {
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return length_;
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* ascii_;
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t length_;
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(V8ExternalASCIILiteral);
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When creating a v8::String from a C++ string we have two choices: create
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a copy, or create a wrapper that shares the same underlying storage.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For small strings it is better to just make a copy, whereas for large
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// strings there are savings by sharing the storage. This number identifies
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the cutoff length for when to start wrapping rather than creating copies.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxStringBytesForCopy = 256;
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts a V8 String to a UTF8 std::string.
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string V8StringToUTF8(v8::Handle<v8::String> s) {
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = s->Length();
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (len > 0)
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->WriteUtf8(WriteInto(&result, len + 1));
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Converts a V8 String to a UTF16 base::string16.
150c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::string16 V8StringToUTF16(v8::Handle<v8::String> s) {
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = s->Length();
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::string16 result;
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that the reinterpret cast is because on Windows string16 is an alias
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to wstring, and hence has character type wchar_t not uint16_t.
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (len > 0)
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->Write(reinterpret_cast<uint16_t*>(WriteInto(&result, len + 1)), 0, len);
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts an ASCII std::string to a V8 string.
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)v8::Local<v8::String> ASCIIStringToV8String(v8::Isolate* isolate,
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            const std::string& s) {
163010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(base::IsStringASCII(s));
164a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return v8::String::NewFromUtf8(isolate, s.data(), v8::String::kNormalString,
165a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 s.size());
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
168c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Converts a UTF16 base::string16 (warpped by a ProxyResolverScriptData) to a
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// V8 string.
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)v8::Local<v8::String> ScriptDataToV8String(
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v8::Isolate* isolate, const scoped_refptr<ProxyResolverScriptData>& s) {
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (s->utf16().size() * 2 <= kMaxStringBytesForCopy) {
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return v8::String::NewFromTwoByte(
174a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        isolate,
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<const uint16_t*>(s->utf16().data()),
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::String::kNormalString,
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s->utf16().size());
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return v8::String::NewExternal(isolate,
180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 new V8ExternalStringFromScriptData(s));
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts an ASCII string literal to a V8 string.
184a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)v8::Local<v8::String> ASCIILiteralToV8String(v8::Isolate* isolate,
185a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                             const char* ascii) {
186010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(base::IsStringASCII(ascii));
1875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t length = strlen(ascii);
1885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length <= kMaxStringBytesForCopy)
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return v8::String::NewFromUtf8(isolate, ascii, v8::String::kNormalString,
190a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   length);
191a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return v8::String::NewExternal(isolate,
192a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 new V8ExternalASCIILiteral(ascii, length));
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stringizes a V8 object by calling its toString() method. Returns true
1965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on success. This may fail if the toString() throws an exception.
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool V8ObjectToUTF16String(v8::Handle<v8::Value> object,
19858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           base::string16* utf16_result,
19958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           v8::Isolate* isolate) {
2005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (object.IsEmpty())
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  v8::HandleScope scope(isolate);
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Local<v8::String> str_object = object->ToString();
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (str_object.IsEmpty())
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *utf16_result = V8StringToUTF16(str_object);
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Extracts an hostname argument from |args|. On success returns true
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and fills |*hostname| with the result.
2137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool GetHostnameArgument(const v8::FunctionCallbackInfo<v8::Value>& args,
2147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                         std::string* hostname) {
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The first argument should be a string.
2165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString())
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
219c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::string16 hostname_utf16 = V8StringToUTF16(args[0]->ToString());
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the hostname is already in ASCII, simply return it as is.
222010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  if (base::IsStringASCII(hostname_utf16)) {
223a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    *hostname = base::UTF16ToASCII(hostname_utf16);
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise try to convert it from IDN to punycode.
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kInitialBufferSize = 256;
2295c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  url::RawCanonOutputT<base::char16, kInitialBufferSize> punycode_output;
2305c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu  if (!url::IDNToASCII(hostname_utf16.data(), hostname_utf16.length(),
2315c02ac1a9c1b504631c0a3d2b6e737b5d738bae1Bo Liu                       &punycode_output)) {
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |punycode_output| should now be ASCII; convert it to a std::string.
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (We could use UTF16ToASCII() instead, but that requires an extra string
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // copy. Since ASCII is a subset of UTF8 the following is equivalent).
2385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)  bool success = base::UTF16ToUTF8(punycode_output.data(),
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             punycode_output.length(),
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             hostname);
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(success);
242010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)  DCHECK(base::IsStringASCII(*hostname));
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wrapper for passing around IP address strings and IPAddressNumber objects.
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct IPAddress {
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddress(const std::string& ip_string, const IPAddressNumber& ip_number)
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : string_value(ip_string),
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ip_address_number(ip_number) {
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used for sorting IP addresses in ascending order in SortIpAddressList().
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IP6 addresses are placed ahead of IPv4 addresses.
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator<(const IPAddress& rhs) const {
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPAddressNumber& ip1 = this->ip_address_number;
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPAddressNumber& ip2 = rhs.ip_address_number;
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ip1.size() != ip2.size())
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ip1.size() > ip2.size();  // IPv6 before IPv4.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(ip1.size() == ip2.size());
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return memcmp(&ip1[0], &ip2[0], ip1.size()) < 0;  // Ascending order.
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string string_value;
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber ip_address_number;
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler for "sortIpAddressList(IpAddressList)". |ip_address_list| is a
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// semi-colon delimited string containing IP addresses.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |sorted_ip_address_list| is the resulting list of sorted semi-colon delimited
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IP addresses or an empty string if unable to sort the IP address list.
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns 'true' if the sorting was successful, and 'false' if the input was an
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// empty string, a string of separators (";" in this case), or if any of the IP
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// addresses in the input list failed to parse.
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SortIpAddressList(const std::string& ip_address_list,
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       std::string* sorted_ip_address_list) {
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sorted_ip_address_list->clear();
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Strip all whitespace (mimics IE behavior).
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cleaned_ip_address_list;
281a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RemoveChars(ip_address_list, " \t", &cleaned_ip_address_list);
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cleaned_ip_address_list.empty())
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Split-up IP addresses and store them in a vector.
2865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<IPAddress> ip_vector;
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber ip_num;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StringTokenizer str_tok(cleaned_ip_address_list, ";");
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (str_tok.GetNext()) {
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ParseIPLiteralToNumber(str_tok.token(), &ip_num))
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ip_vector.push_back(IPAddress(str_tok.token(), ip_num));
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ip_vector.empty())  // Can happen if we have something like
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;         // sortIpAddressList(";") or sortIpAddressList("; ;")
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!ip_vector.empty());
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sort lists according to ascending numeric value.
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ip_vector.size() > 1)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::stable_sort(ip_vector.begin(), ip_vector.end());
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return a semi-colon delimited list of sorted addresses (IPv6 followed by
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IPv4).
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ip_vector.size(); ++i) {
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i > 0)
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *sorted_ip_address_list += ";";
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *sorted_ip_address_list += ip_vector[i].string_value;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler for "isInNetEx(ip_address, ip_prefix)". |ip_address| is a string
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// containing an IPv4/IPv6 address, and |ip_prefix| is a string containg a
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// slash-delimited IP prefix with the top 'n' bits specified in the bit
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// field. This returns 'true' if the address is in the same subnet, and
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'false' otherwise. Also returns 'false' if the prefix is in an incorrect
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// format, or if an address and prefix of different types are used (e.g. IPv6
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// address and IPv4 prefix).
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) {
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber address;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ParseIPLiteralToNumber(ip_address, &address))
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber prefix;
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t prefix_length_in_bits;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ParseCIDRBlock(ip_prefix, &prefix, &prefix_length_in_bits))
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Both |address| and |prefix| must be of the same type (IPv4 or IPv6).
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address.size() != prefix.size())
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK((address.size() == 4 && prefix.size() == 4) ||
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (address.size() == 16 && prefix.size() == 16));
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits);
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyResolverV8::Context ---------------------------------------------------
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyResolverV8::Context {
3465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Context(ProxyResolverV8* parent, v8::Isolate* isolate)
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : parent_(parent),
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        isolate_(isolate) {
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(isolate);
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Context() {
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    v8::Locker locked(isolate_);
355f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    v8::Isolate::Scope isolate_scope(isolate_);
3565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
357a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v8_this_.Reset();
358a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v8_context_.Reset();
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  JSBindings* js_bindings() {
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return parent_->js_bindings_;
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ResolveProxy(const GURL& query_url, ProxyInfo* results) {
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    v8::Locker locked(isolate_);
367f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    v8::Isolate::Scope isolate_scope(isolate_);
36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::HandleScope scope(isolate_);
3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Local<v8::Context> context =
37190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        v8::Local<v8::Context>::New(isolate_, v8_context_);
37290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Context::Scope function_scope(context);
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::Value> function;
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetFindProxyForURL(&function)) {
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      js_bindings()->OnError(
3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          -1, base::ASCIIToUTF16("FindProxyForURL() is undefined."));
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::Value> argv[] = {
382a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ASCIIStringToV8String(isolate_, query_url.spec()),
383a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ASCIIStringToV8String(isolate_, query_url.HostNoBrackets()),
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::TryCatch try_catch;
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::Value> ret = v8::Function::Cast(*function)->Call(
38890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        context->Global(), arraysize(argv), argv);
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (try_catch.HasCaught()) {
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HandleError(try_catch.Message());
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ret->IsString()) {
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      js_bindings()->OnError(
3975d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          -1, base::ASCIIToUTF16("FindProxyForURL() did not return a string."));
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
3995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
401c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::string16 ret_str = V8StringToUTF16(ret->ToString());
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
403010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!base::IsStringASCII(ret_str)) {
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(eroman): Rather than failing when a wide string is returned, we
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //               could extend the parsing to handle IDNA hostnames by
4065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //               converting them to ASCII punycode.
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //               crbug.com/47234
408c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::string16 error_message =
4095d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          base::ASCIIToUTF16("FindProxyForURL() returned a non-ASCII string "
4105d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)                             "(crbug.com/47234): ") + ret_str;
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      js_bindings()->OnError(-1, error_message);
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
415a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)    results->UsePacString(base::UTF16ToASCII(ret_str));
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int InitV8(const scoped_refptr<ProxyResolverScriptData>& pac_script) {
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    v8::Locker locked(isolate_);
421f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    v8::Isolate::Scope isolate_scope(isolate_);
42290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::HandleScope scope(isolate_);
4235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
424f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    v8_this_.Reset(isolate_, v8::External::New(isolate_, this));
42590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Local<v8::External> v8_this =
42690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        v8::Local<v8::External>::New(isolate_, v8_this_);
4275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    v8::Local<v8::ObjectTemplate> global_template =
4285d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)        v8::ObjectTemplate::New(isolate_);
4295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Attach the javascript bindings.
4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> alert_template =
432a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &AlertCallback, v8_this);
433a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "alert"),
434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         alert_template);
4355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> my_ip_address_template =
437a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &MyIpAddressCallback, v8_this);
438a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "myIpAddress"),
439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         my_ip_address_template);
4405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> dns_resolve_template =
442a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &DnsResolveCallback, v8_this);
443a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "dnsResolve"),
444a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         dns_resolve_template);
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Microsoft's PAC extensions:
4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> dns_resolve_ex_template =
449a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &DnsResolveExCallback, v8_this);
450a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "dnsResolveEx"),
4515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         dns_resolve_ex_template);
4525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> my_ip_address_ex_template =
454a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &MyIpAddressExCallback, v8_this);
455a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "myIpAddressEx"),
4565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         my_ip_address_ex_template);
4575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> sort_ip_address_list_template =
459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_,
460a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  &SortIpAddressListCallback,
461a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  v8_this);
462a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "sortIpAddressList"),
4635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         sort_ip_address_list_template);
4645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> is_in_net_ex_template =
466a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &IsInNetExCallback, v8_this);
467a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "isInNetEx"),
4685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         is_in_net_ex_template);
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
470a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    v8_context_.Reset(
471c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        isolate_, v8::Context::New(isolate_, NULL, global_template));
4725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Local<v8::Context> context =
47490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        v8::Local<v8::Context>::New(isolate_, v8_context_);
47590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Context::Scope ctx(context);
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add the PAC utility functions to the environment.
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (This script should never fail, as it is a string literal!)
4795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that the two string literals are concatenated.
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = RunScript(
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASCIILiteralToV8String(
482a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            isolate_,
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PROXY_RESOLVER_SCRIPT
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PROXY_RESOLVER_SCRIPT_EX),
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kPacUtilityResourceName);
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != OK) {
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rv;
4895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add the user's PAC code to the environment.
492a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    rv =
493a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        RunScript(ScriptDataToV8String(isolate_, pac_script), kPacResourceName);
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != OK)
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rv;
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // At a minimum, the FindProxyForURL() function must be defined for this
4985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to be a legitimiate PAC script.
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::Value> function;
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetFindProxyForURL(&function)) {
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      js_bindings()->OnError(
5025d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)          -1, base::ASCIIToUTF16("FindProxyForURL() is undefined."));
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
5075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetFindProxyForURL(v8::Local<v8::Value>* function) {
51190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Local<v8::Context> context =
512a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::Local<v8::Context>::New(isolate_, v8_context_);
51390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *function =
514a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        context->Global()->Get(
515a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            ASCIILiteralToV8String(isolate_, "FindProxyForURL"));
5165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (*function)->IsFunction();
5175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle an exception thrown by V8.
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleError(v8::Handle<v8::Message> message) {
521c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::string16 error_message;
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int line_number = -1;
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!message.IsEmpty()) {
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      line_number = message->GetLineNumber();
52658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      V8ObjectToUTF16String(message->Get(), &error_message, isolate_);
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    js_bindings()->OnError(line_number, error_message);
5305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Compiles and runs |script| in the current V8 context.
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns OK on success, otherwise an error code.
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int RunScript(v8::Handle<v8::String> script, const char* script_name) {
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::TryCatch try_catch;
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Compile the script.
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::ScriptOrigin origin =
539a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::ScriptOrigin(ASCIILiteralToV8String(isolate_, script_name));
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::Script> code = v8::Script::Compile(script, &origin);
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Execute.
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!code.IsEmpty())
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      code->Run();
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check for errors.
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (try_catch.HasCaught()) {
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HandleError(try_catch.Message());
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "alert()" is invoked by the PAC script.
5567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void AlertCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Context* context =
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
5595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Like firefox we assume "undefined" if no argument was specified, and
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // disregard any arguments beyond the first.
562c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::string16 message;
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (args.Length() == 0) {
5645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)      message = base::ASCIIToUTF16("undefined");
5655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
56658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (!V8ObjectToUTF16String(args[0], &message, args.GetIsolate()))
5677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;  // toString() threw an exception.
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context->js_bindings()->Alert(message);
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "myIpAddress()" is invoked by the PAC script.
5747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void MyIpAddressCallback(
5757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
5767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DnsResolveCallbackHelper(args, JSBindings::MY_IP_ADDRESS);
5775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "myIpAddressEx()" is invoked by the PAC script.
5807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void MyIpAddressExCallback(
5817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
5827d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DnsResolveCallbackHelper(args, JSBindings::MY_IP_ADDRESS_EX);
5835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "dnsResolve()" is invoked by the PAC script.
5867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void DnsResolveCallback(
5877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
5887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DnsResolveCallbackHelper(args, JSBindings::DNS_RESOLVE);
5895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "dnsResolveEx()" is invoked by the PAC script.
5927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void DnsResolveExCallback(
5937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
5947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DnsResolveCallbackHelper(args, JSBindings::DNS_RESOLVE_EX);
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Shared code for implementing:
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   - myIpAddress(), myIpAddressEx(), dnsResolve(), dnsResolveEx().
5997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void DnsResolveCallbackHelper(
6007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args,
6017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      JSBindings::ResolveDnsOperation op) {
6025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Context* context =
6035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
6045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string hostname;
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // dnsResolve() and dnsResolveEx() need at least 1 argument.
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (op == JSBindings::DNS_RESOLVE || op == JSBindings::DNS_RESOLVE_EX) {
6097d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (!GetHostnameArgument(args, &hostname)) {
6107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        if (op == JSBindings::DNS_RESOLVE)
6117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          args.GetReturnValue().SetNull();
6127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
6137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string result;
6175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success;
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool terminate = false;
6195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      v8::Unlocker unlocker(args.GetIsolate());
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      success = context->js_bindings()->ResolveDns(
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          hostname, op, &result, &terminate);
6245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (terminate)
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      v8::V8::TerminateExecution(args.GetIsolate());
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6297d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (success) {
630a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      args.GetReturnValue().Set(
631a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          ASCIIStringToV8String(args.GetIsolate(), result));
6327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6337d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Each function handles resolution errors differently.
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (op) {
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case JSBindings::DNS_RESOLVE:
6387d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        args.GetReturnValue().SetNull();
6397d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case JSBindings::DNS_RESOLVE_EX:
6417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        args.GetReturnValue().SetEmptyString();
6427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case JSBindings::MY_IP_ADDRESS:
644a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        args.GetReturnValue().Set(
645a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            ASCIILiteralToV8String(args.GetIsolate(), "127.0.0.1"));
6467d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case JSBindings::MY_IP_ADDRESS_EX:
6487d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        args.GetReturnValue().SetEmptyString();
6497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
6535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "sortIpAddressList()" is invoked by the PAC script.
6567d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void SortIpAddressListCallback(
6577d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need at least one string argument.
6597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) {
6607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().SetNull();
6617d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
6635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string ip_address_list = V8StringToUTF8(args[0]->ToString());
665010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!base::IsStringASCII(ip_address_list)) {
6667d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().SetNull();
6677d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
6695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string sorted_ip_address_list;
6705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = SortIpAddressList(ip_address_list, &sorted_ip_address_list);
6717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (!success) {
6727d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().Set(false);
6737d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
675a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    args.GetReturnValue().Set(
676a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIStringToV8String(args.GetIsolate(), sorted_ip_address_list));
6775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "isInNetEx()" is invoked by the PAC script.
6807d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void IsInNetExCallback(
6817d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need at least 2 string arguments.
6835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (args.Length() < 2 || args[0].IsEmpty() || !args[0]->IsString() ||
6847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        args[1].IsEmpty() || !args[1]->IsString()) {
6857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().SetNull();
6867d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
6885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string ip_address = V8StringToUTF8(args[0]->ToString());
690010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!base::IsStringASCII(ip_address)) {
6917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().Set(false);
6927d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
6945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string ip_prefix = V8StringToUTF8(args[1]->ToString());
695010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles)    if (!base::IsStringASCII(ip_prefix)) {
6967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().Set(false);
6977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
6997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    args.GetReturnValue().Set(IsInNetEx(ip_address, ip_prefix));
7005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable base::Lock lock_;
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyResolverV8* parent_;
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::Isolate* isolate_;
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Persistent<v8::External> v8_this_;
7065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Persistent<v8::Context> v8_context_;
7075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyResolverV8 ------------------------------------------------------------
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProxyResolverV8::ProxyResolverV8()
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : ProxyResolver(true /*expects_pac_bytes*/),
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      js_bindings_(NULL) {
7145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyResolverV8::~ProxyResolverV8() {}
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyResolverV8::GetProxyForURL(
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& query_url, ProxyInfo* results,
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CompletionCallback& /*callback*/,
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RequestHandle* /*request*/,
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BoundNetLog& net_log) {
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(js_bindings_);
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the V8 instance has not been initialized (either because
7265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SetPacScript() wasn't called yet, or because it failed.
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!context_)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_FAILED;
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise call into V8.
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = context_->ResolveProxy(query_url, results);
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyResolverV8::CancelRequest(RequestHandle request) {
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is a synchronous ProxyResolver; no possibility for async requests.
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState ProxyResolverV8::GetLoadState(RequestHandle request) const {
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return LOAD_STATE_IDLE;
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyResolverV8::CancelSetPacScript() {
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyResolverV8::SetPacScript(
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<ProxyResolverScriptData>& script_data,
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CompletionCallback& /*callback*/) {
753868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(script_data.get());
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(js_bindings_);
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_.reset();
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (script_data->utf16().empty())
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_PAC_SCRIPT_FAILED;
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try parsing the PAC script.
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Context> context(new Context(this, GetDefaultIsolate()));
7625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = context->InitV8(script_data);
7635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == OK)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_.reset(context.release());
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
769c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochvoid ProxyResolverV8::EnsureIsolateCreated() {
770c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (g_proxy_resolver_isolate_)
771c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch    return;
7721320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  gin::IsolateHolder::Initialize(gin::IsolateHolder::kNonStrictMode,
7731320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci                                 gin::ArrayBufferAllocator::SharedInstance());
7741320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci  g_proxy_resolver_isolate_ = new gin::IsolateHolder;
775c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  ANNOTATE_LEAKING_OBJECT_PTR(g_proxy_resolver_isolate_);
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)v8::Isolate* ProxyResolverV8::GetDefaultIsolate() {
780c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  DCHECK(g_proxy_resolver_isolate_)
781c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch      << "Must call ProxyResolverV8::EnsureIsolateCreated() first";
782c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  return g_proxy_resolver_isolate_->isolate();
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
785c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochgin::IsolateHolder* ProxyResolverV8::g_proxy_resolver_isolate_ = NULL;
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t ProxyResolverV8::GetTotalHeapSize() {
789c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!g_proxy_resolver_isolate_)
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
792c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  v8::Locker locked(g_proxy_resolver_isolate_->isolate());
793c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  v8::Isolate::Scope isolate_scope(g_proxy_resolver_isolate_->isolate());
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::HeapStatistics heap_statistics;
795c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  g_proxy_resolver_isolate_->isolate()->GetHeapStatistics(&heap_statistics);
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return heap_statistics.total_heap_size();
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t ProxyResolverV8::GetUsedHeapSize() {
801c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  if (!g_proxy_resolver_isolate_)
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
804c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  v8::Locker locked(g_proxy_resolver_isolate_->isolate());
805c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  v8::Isolate::Scope isolate_scope(g_proxy_resolver_isolate_->isolate());
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::HeapStatistics heap_statistics;
807c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch  g_proxy_resolver_isolate_->isolate()->GetHeapStatistics(&heap_statistics);
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return heap_statistics.used_heap_size();
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
812