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"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/string_tokenizer.h"
147dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "base/strings/string_util.h"
15868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/strings/utf_string_conversions.h"
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/synchronization/lock.h"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_errors.h"
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_log.h"
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/base/net_util.h"
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_info.h"
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/proxy/proxy_resolver_script.h"
227dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/gurl.h"
237dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch#include "url/url_canon.h"
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "v8/include/v8.h"
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Notes on the javascript environment:
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For the majority of the PAC utility functions, we use the same code
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// as Firefox. See the javascript library that proxy_resolver_scipt.h
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// pulls in.
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// In addition, we implement a subset of Microsoft's extensions to PAC.
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - myIpAddressEx()
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - dnsResolveEx()
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - isResolvableEx()
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - isInNetEx()
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// - sortIpAddressList()
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// It is worth noting that the original PAC specification does not describe
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the return values on failure. Consequently, there are compatibility
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// differences between browsers on what to return on failure, which are
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// illustrated below:
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------+-------------+-------------------+--------------
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     | Firefox3    | InternetExplorer8 |  --> Us <---
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------+-------------+-------------------+--------------
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// myIpAddress()       | "127.0.0.1" |  ???              |  "127.0.0.1"
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dnsResolve()        | null        |  false            |  null
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// myIpAddressEx()     | N/A         |  ""               |  ""
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sortIpAddressList() | N/A         |  false            |  false
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dnsResolveEx()      | N/A         |  ""               |  ""
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// isInNetEx()         | N/A         |  false            |  false
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------+-------------+-------------------+--------------
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// TODO(eroman): The cell above reading ??? means I didn't test it.
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Another difference is in how dnsResolve() and myIpAddress() are
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// implemented -- whether they should restrict to IPv4 results, or
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// include both IPv4 and IPv6. The following table illustrates the
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// differences:
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------+-------------+-------------------+--------------
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)//                     | Firefox3    | InternetExplorer8 |  --> Us <---
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// --------------------+-------------+-------------------+--------------
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// myIpAddress()       | IPv4/IPv6   |  IPv4             |  IPv4
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dnsResolve()        | IPv4/IPv6   |  IPv4             |  IPv4
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// isResolvable()      | IPv4/IPv6   |  IPv4             |  IPv4
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// myIpAddressEx()     | N/A         |  IPv4/IPv6        |  IPv4/IPv6
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// dnsResolveEx()      | N/A         |  IPv4/IPv6        |  IPv4/IPv6
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// sortIpAddressList() | N/A         |  IPv4/IPv6        |  IPv4/IPv6
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// isResolvableEx()    | N/A         |  IPv4/IPv6        |  IPv4/IPv6
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// isInNetEx()         | N/A         |  IPv4/IPv6        |  IPv4/IPv6
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// -----------------+-------------+-------------------+--------------
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net {
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace {
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pseudo-name for the PAC script.
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPacResourceName[] = "proxy-pac-script.js";
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Pseudo-name for the PAC utility script.
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const char kPacUtilityResourceName[] = "proxy-pac-utility-script.js";
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// External string wrapper so V8 can access the UTF16 string wrapped by
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyResolverScriptData.
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class V8ExternalStringFromScriptData
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : public v8::String::ExternalStringResource {
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  explicit V8ExternalStringFromScriptData(
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      const scoped_refptr<ProxyResolverScriptData>& script_data)
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : script_data_(script_data) {}
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual const uint16_t* data() const OVERRIDE {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return reinterpret_cast<const uint16*>(script_data_->utf16().data());
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual size_t length() const OVERRIDE {
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return script_data_->utf16().size();
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const scoped_refptr<ProxyResolverScriptData> script_data_;
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(V8ExternalStringFromScriptData);
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// External string wrapper so V8 can access a string literal.
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class V8ExternalASCIILiteral : public v8::String::ExternalAsciiStringResource {
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |ascii| must be a NULL-terminated C string, and must remain valid
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // throughout this object's lifetime.
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  V8ExternalASCIILiteral(const char* ascii, size_t length)
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : ascii_(ascii), length_(length) {
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(IsStringASCII(ascii));
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual const char* data() const OVERRIDE {
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ascii_;
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  virtual size_t length() const OVERRIDE {
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return length_;
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const char* ascii_;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t length_;
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DISALLOW_COPY_AND_ASSIGN(V8ExternalASCIILiteral);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// When creating a v8::String from a C++ string we have two choices: create
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// a copy, or create a wrapper that shares the same underlying storage.
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// For small strings it is better to just make a copy, whereas for large
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// strings there are savings by sharing the storage. This number identifies
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// the cutoff length for when to start wrapping rather than creating copies.
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)const size_t kMaxStringBytesForCopy = 256;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts a V8 String to a UTF8 std::string.
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)std::string V8StringToUTF8(v8::Handle<v8::String> s) {
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = s->Length();
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string result;
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (len > 0)
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->WriteUtf8(WriteInto(&result, len + 1));
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
146c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Converts a V8 String to a UTF16 base::string16.
147c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)base::string16 V8StringToUTF16(v8::Handle<v8::String> s) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int len = s->Length();
149c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  base::string16 result;
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Note that the reinterpret cast is because on Windows string16 is an alias
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // to wstring, and hence has character type wchar_t not uint16_t.
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (len > 0)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    s->Write(reinterpret_cast<uint16_t*>(WriteInto(&result, len + 1)), 0, len);
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return result;
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts an ASCII std::string to a V8 string.
158a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)v8::Local<v8::String> ASCIIStringToV8String(v8::Isolate* isolate,
159a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                            const std::string& s) {
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsStringASCII(s));
161a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return v8::String::NewFromUtf8(isolate, s.data(), v8::String::kNormalString,
162a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 s.size());
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
165c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)// Converts a UTF16 base::string16 (warpped by a ProxyResolverScriptData) to a
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// V8 string.
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)v8::Local<v8::String> ScriptDataToV8String(
168a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v8::Isolate* isolate, const scoped_refptr<ProxyResolverScriptData>& s) {
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (s->utf16().size() * 2 <= kMaxStringBytesForCopy) {
170a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return v8::String::NewFromTwoByte(
171a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        isolate,
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        reinterpret_cast<const uint16_t*>(s->utf16().data()),
173a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::String::kNormalString,
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        s->utf16().size());
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
176a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return v8::String::NewExternal(isolate,
177a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 new V8ExternalStringFromScriptData(s));
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Converts an ASCII string literal to a V8 string.
181a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)v8::Local<v8::String> ASCIILiteralToV8String(v8::Isolate* isolate,
182a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                             const char* ascii) {
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsStringASCII(ascii));
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t length = strlen(ascii);
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (length <= kMaxStringBytesForCopy)
186a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    return v8::String::NewFromUtf8(isolate, ascii, v8::String::kNormalString,
187a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                   length);
188a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  return v8::String::NewExternal(isolate,
189a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                 new V8ExternalASCIILiteral(ascii, length));
1905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
1915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Stringizes a V8 object by calling its toString() method. Returns true
1935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// on success. This may fail if the toString() throws an exception.
1945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool V8ObjectToUTF16String(v8::Handle<v8::Value> object,
19558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           base::string16* utf16_result,
19658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)                           v8::Isolate* isolate) {
1975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (object.IsEmpty())
1985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
20058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)  v8::HandleScope scope(isolate);
2015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Local<v8::String> str_object = object->ToString();
2025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (str_object.IsEmpty())
2035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  *utf16_result = V8StringToUTF16(str_object);
2055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
2065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Extracts an hostname argument from |args|. On success returns true
2095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// and fills |*hostname| with the result.
2107d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)bool GetHostnameArgument(const v8::FunctionCallbackInfo<v8::Value>& args,
2117d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)                         std::string* hostname) {
2125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // The first argument should be a string.
2135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString())
2145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
216c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  const base::string16 hostname_utf16 = V8StringToUTF16(args[0]->ToString());
2175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the hostname is already in ASCII, simply return it as is.
2195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (IsStringASCII(hostname_utf16)) {
2205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *hostname = UTF16ToASCII(hostname_utf16);
2215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return true;
2225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise try to convert it from IDN to punycode.
2255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const int kInitialBufferSize = 256;
2265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  url_canon::RawCanonOutputT<char16, kInitialBufferSize> punycode_output;
2275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!url_canon::IDNToASCII(hostname_utf16.data(),
2285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             hostname_utf16.length(),
2295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             &punycode_output)) {
2305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // |punycode_output| should now be ASCII; convert it to a std::string.
2345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // (We could use UTF16ToASCII() instead, but that requires an extra string
2355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // copy. Since ASCII is a subset of UTF8 the following is equivalent).
2365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool success = UTF16ToUTF8(punycode_output.data(),
2375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             punycode_output.length(),
2385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                             hostname);
2395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(success);
2405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(IsStringASCII(*hostname));
2415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return success;
2425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
2435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Wrapper for passing around IP address strings and IPAddressNumber objects.
2455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)struct IPAddress {
2465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddress(const std::string& ip_string, const IPAddressNumber& ip_number)
2475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      : string_value(ip_string),
2485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ip_address_number(ip_number) {
2495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Used for sorting IP addresses in ascending order in SortIpAddressList().
2525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IP6 addresses are placed ahead of IPv4 addresses.
2535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool operator<(const IPAddress& rhs) const {
2545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPAddressNumber& ip1 = this->ip_address_number;
2555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const IPAddressNumber& ip2 = rhs.ip_address_number;
2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (ip1.size() != ip2.size())
2575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ip1.size() > ip2.size();  // IPv6 before IPv4.
2585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    DCHECK(ip1.size() == ip2.size());
2595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return memcmp(&ip1[0], &ip2[0], ip1.size()) < 0;  // Ascending order.
2605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string string_value;
2635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber ip_address_number;
2645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler for "sortIpAddressList(IpAddressList)". |ip_address_list| is a
2675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// semi-colon delimited string containing IP addresses.
2685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// |sorted_ip_address_list| is the resulting list of sorted semi-colon delimited
2695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// IP addresses or an empty string if unable to sort the IP address list.
2705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Returns 'true' if the sorting was successful, and 'false' if the input was an
2715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// empty string, a string of separators (";" in this case), or if any of the IP
2725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// addresses in the input list failed to parse.
2735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool SortIpAddressList(const std::string& ip_address_list,
2745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       std::string* sorted_ip_address_list) {
2755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  sorted_ip_address_list->clear();
2765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Strip all whitespace (mimics IE behavior).
2785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::string cleaned_ip_address_list;
279a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)  base::RemoveChars(ip_address_list, " \t", &cleaned_ip_address_list);
2805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (cleaned_ip_address_list.empty())
2815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
2825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Split-up IP addresses and store them in a vector.
2845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  std::vector<IPAddress> ip_vector;
2855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber ip_num;
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::StringTokenizer str_tok(cleaned_ip_address_list, ";");
2875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  while (str_tok.GetNext()) {
2885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ParseIPLiteralToNumber(str_tok.token(), &ip_num))
2895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return false;
2905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ip_vector.push_back(IPAddress(str_tok.token(), ip_num));
2915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
2925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ip_vector.empty())  // Can happen if we have something like
2945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;         // sortIpAddressList(";") or sortIpAddressList("; ;")
2955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK(!ip_vector.empty());
2975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
2985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Sort lists according to ascending numeric value.
2995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (ip_vector.size() > 1)
3005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::stable_sort(ip_vector.begin(), ip_vector.end());
3015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Return a semi-colon delimited list of sorted addresses (IPv6 followed by
3035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // IPv4).
3045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (size_t i = 0; i < ip_vector.size(); ++i) {
3055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (i > 0)
3065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      *sorted_ip_address_list += ";";
3075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    *sorted_ip_address_list += ip_vector[i].string_value;
3085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
3105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Handler for "isInNetEx(ip_address, ip_prefix)". |ip_address| is a string
3135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// containing an IPv4/IPv6 address, and |ip_prefix| is a string containg a
3145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// slash-delimited IP prefix with the top 'n' bits specified in the bit
3155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// field. This returns 'true' if the address is in the same subnet, and
3165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// 'false' otherwise. Also returns 'false' if the prefix is in an incorrect
3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// format, or if an address and prefix of different types are used (e.g. IPv6
3185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// address and IPv4 prefix).
3195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)bool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) {
3205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber address;
3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ParseIPLiteralToNumber(ip_address, &address))
3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  IPAddressNumber prefix;
3255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  size_t prefix_length_in_bits;
3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!ParseCIDRBlock(ip_prefix, &prefix, &prefix_length_in_bits))
3275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Both |address| and |prefix| must be of the same type (IPv4 or IPv6).
3305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (address.size() != prefix.size())
3315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
3325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DCHECK((address.size() == 4 && prefix.size() == 4) ||
3345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)         (address.size() == 16 && prefix.size() == 16));
3355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits);
3375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
3385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace
3405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyResolverV8::Context ---------------------------------------------------
3425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class ProxyResolverV8::Context {
3445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) public:
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Context(ProxyResolverV8* parent, v8::Isolate* isolate)
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      : parent_(parent),
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        isolate_(isolate) {
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(isolate);
3495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ~Context() {
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    v8::Locker locked(isolate_);
353f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    v8::Isolate::Scope isolate_scope(isolate_);
3545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
355a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v8_this_.Reset();
356a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    v8_context_.Reset();
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  JSBindings* js_bindings() {
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return parent_->js_bindings_;
3615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
3625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int ResolveProxy(const GURL& query_url, ProxyInfo* results) {
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    v8::Locker locked(isolate_);
365f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    v8::Isolate::Scope isolate_scope(isolate_);
36690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::HandleScope scope(isolate_);
3675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
36890dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Local<v8::Context> context =
36990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        v8::Local<v8::Context>::New(isolate_, v8_context_);
37090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Context::Scope function_scope(context);
3715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::Value> function;
3735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetFindProxyForURL(&function)) {
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      js_bindings()->OnError(
3755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          -1, ASCIIToUTF16("FindProxyForURL() is undefined."));
3765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
3775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Handle<v8::Value> argv[] = {
380a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ASCIIStringToV8String(isolate_, query_url.spec()),
381a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      ASCIIStringToV8String(isolate_, query_url.HostNoBrackets()),
3825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    };
3835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::TryCatch try_catch;
3855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::Value> ret = v8::Function::Cast(*function)->Call(
38690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        context->Global(), arraysize(argv), argv);
3875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (try_catch.HasCaught()) {
3895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HandleError(try_catch.Message());
3905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
3915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
3935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!ret->IsString()) {
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      js_bindings()->OnError(
3955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          -1, ASCIIToUTF16("FindProxyForURL() did not return a string."));
3965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
3975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
3985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
399c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::string16 ret_str = V8StringToUTF16(ret->ToString());
4005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!IsStringASCII(ret_str)) {
4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      // TODO(eroman): Rather than failing when a wide string is returned, we
4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //               could extend the parsing to handle IDNA hostnames by
4045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //               converting them to ASCII punycode.
4055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      //               crbug.com/47234
406c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)      base::string16 error_message =
4075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          ASCIIToUTF16("FindProxyForURL() returned a non-ASCII string "
4085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                       "(crbug.com/47234): ") + ret_str;
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      js_bindings()->OnError(-1, error_message);
4105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
4115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    results->UsePacString(UTF16ToASCII(ret_str));
4145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
4155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
4165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int InitV8(const scoped_refptr<ProxyResolverScriptData>& pac_script) {
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    v8::Locker locked(isolate_);
419f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    v8::Isolate::Scope isolate_scope(isolate_);
42090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::HandleScope scope(isolate_);
4215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
422f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    v8_this_.Reset(isolate_, v8::External::New(isolate_, this));
42390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Local<v8::External> v8_this =
42490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        v8::Local<v8::External>::New(isolate_, v8_this_);
4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
4265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Attach the javascript bindings.
4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> alert_template =
429a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &AlertCallback, v8_this);
430a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "alert"),
431a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         alert_template);
4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> my_ip_address_template =
434a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &MyIpAddressCallback, v8_this);
435a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "myIpAddress"),
436a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         my_ip_address_template);
4375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> dns_resolve_template =
439a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &DnsResolveCallback, v8_this);
440a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "dnsResolve"),
441a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                         dns_resolve_template);
4425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Microsoft's PAC extensions:
4445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> dns_resolve_ex_template =
446a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &DnsResolveExCallback, v8_this);
447a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "dnsResolveEx"),
4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         dns_resolve_ex_template);
4495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> my_ip_address_ex_template =
451a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &MyIpAddressExCallback, v8_this);
452a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "myIpAddressEx"),
4535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         my_ip_address_ex_template);
4545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> sort_ip_address_list_template =
456a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_,
457a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  &SortIpAddressListCallback,
458a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)                                  v8_this);
459a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "sortIpAddressList"),
4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         sort_ip_address_list_template);
4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::FunctionTemplate> is_in_net_ex_template =
463a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::FunctionTemplate::New(isolate_, &IsInNetExCallback, v8_this);
464a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    global_template->Set(ASCIILiteralToV8String(isolate_, "isInNetEx"),
4655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)                         is_in_net_ex_template);
4665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
467a93a17c8d99d686bd4a1511e5504e5e6cc9fcadfTorne (Richard Coles)    v8_context_.Reset(
468c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)        isolate_, v8::Context::New(isolate_, NULL, global_template));
4695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
47090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Local<v8::Context> context =
47190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)        v8::Local<v8::Context>::New(isolate_, v8_context_);
47290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Context::Scope ctx(context);
4735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add the PAC utility functions to the environment.
4755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // (This script should never fail, as it is a string literal!)
4765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Note that the two string literals are concatenated.
4775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    int rv = RunScript(
4785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        ASCIILiteralToV8String(
479a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            isolate_,
4805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PROXY_RESOLVER_SCRIPT
4815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)            PROXY_RESOLVER_SCRIPT_EX),
4825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        kPacUtilityResourceName);
4835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != OK) {
4845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      NOTREACHED();
4855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rv;
4865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
4875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Add the user's PAC code to the environment.
489a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    rv =
490a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        RunScript(ScriptDataToV8String(isolate_, pac_script), kPacResourceName);
4915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (rv != OK)
4925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return rv;
4935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
4945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // At a minimum, the FindProxyForURL() function must be defined for this
4955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // to be a legitimiate PAC script.
4965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::Value> function;
4975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!GetFindProxyForURL(&function)) {
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      js_bindings()->OnError(
4995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          -1, ASCIIToUTF16("FindProxyForURL() is undefined."));
5005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
5015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
5045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void PurgeMemory() {
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    v8::Locker locked(isolate_);
508f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)    v8::Isolate::Scope isolate_scope(isolate_);
5095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::V8::LowMemoryNotification();
5105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) private:
5135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  bool GetFindProxyForURL(v8::Local<v8::Value>* function) {
51490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    v8::Local<v8::Context> context =
515a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::Local<v8::Context>::New(isolate_, v8_context_);
51690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)    *function =
517a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        context->Global()->Get(
518a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            ASCIILiteralToV8String(isolate_, "FindProxyForURL"));
5195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return (*function)->IsFunction();
5205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Handle an exception thrown by V8.
5235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  void HandleError(v8::Handle<v8::Message> message) {
524c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::string16 error_message;
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int line_number = -1;
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!message.IsEmpty()) {
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      line_number = message->GetLineNumber();
52958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      V8ObjectToUTF16String(message->Get(), &error_message, isolate_);
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    js_bindings()->OnError(line_number, error_message);
5335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Compiles and runs |script| in the current V8 context.
5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Returns OK on success, otherwise an error code.
5375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int RunScript(v8::Handle<v8::String> script, const char* script_name) {
5385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::TryCatch try_catch;
5395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Compile the script.
5415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::ScriptOrigin origin =
542a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        v8::ScriptOrigin(ASCIILiteralToV8String(isolate_, script_name));
5435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    v8::Local<v8::Script> code = v8::Script::Compile(script, &origin);
5445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Execute.
5465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!code.IsEmpty())
5475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      code->Run();
5485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Check for errors.
5505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (try_catch.HasCaught()) {
5515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      HandleError(try_catch.Message());
5525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return ERR_PAC_SCRIPT_FAILED;
5535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return OK;
5565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "alert()" is invoked by the PAC script.
5597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void AlertCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
5605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Context* context =
5615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
5625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // Like firefox we assume "undefined" if no argument was specified, and
5645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // disregard any arguments beyond the first.
565c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::string16 message;
5665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (args.Length() == 0) {
5675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      message = ASCIIToUTF16("undefined");
5685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } else {
56958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)      if (!V8ObjectToUTF16String(args[0], &message, args.GetIsolate()))
5707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;  // toString() threw an exception.
5715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
5725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    context->js_bindings()->Alert(message);
5745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "myIpAddress()" is invoked by the PAC script.
5777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void MyIpAddressCallback(
5787d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
5797d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DnsResolveCallbackHelper(args, JSBindings::MY_IP_ADDRESS);
5805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "myIpAddressEx()" is invoked by the PAC script.
5837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void MyIpAddressExCallback(
5847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
5857d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DnsResolveCallbackHelper(args, JSBindings::MY_IP_ADDRESS_EX);
5865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "dnsResolve()" is invoked by the PAC script.
5897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void DnsResolveCallback(
5907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
5917d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DnsResolveCallbackHelper(args, JSBindings::DNS_RESOLVE);
5925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
5935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
5945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "dnsResolveEx()" is invoked by the PAC script.
5957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void DnsResolveExCallback(
5967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
5977d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    DnsResolveCallbackHelper(args, JSBindings::DNS_RESOLVE_EX);
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Shared code for implementing:
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //   - myIpAddress(), myIpAddressEx(), dnsResolve(), dnsResolveEx().
6027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void DnsResolveCallbackHelper(
6037d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args,
6047d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      JSBindings::ResolveDnsOperation op) {
6055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Context* context =
6065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
6075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string hostname;
6095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // dnsResolve() and dnsResolveEx() need at least 1 argument.
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (op == JSBindings::DNS_RESOLVE || op == JSBindings::DNS_RESOLVE_EX) {
6127d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      if (!GetHostnameArgument(args, &hostname)) {
6137d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        if (op == JSBindings::DNS_RESOLVE)
6147d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)          args.GetReturnValue().SetNull();
6157d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
6167d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      }
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string result;
6205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success;
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool terminate = false;
6225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    {
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      v8::Unlocker unlocker(args.GetIsolate());
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      success = context->js_bindings()->ResolveDns(
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          hostname, op, &result, &terminate);
6275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
6285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (terminate)
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      v8::V8::TerminateExecution(args.GetIsolate());
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6327d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (success) {
633a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)      args.GetReturnValue().Set(
634a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)          ASCIIStringToV8String(args.GetIsolate(), result));
6357d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6367d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Each function handles resolution errors differently.
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    switch (op) {
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case JSBindings::DNS_RESOLVE:
6417d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        args.GetReturnValue().SetNull();
6427d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case JSBindings::DNS_RESOLVE_EX:
6447d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        args.GetReturnValue().SetEmptyString();
6457d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case JSBindings::MY_IP_ADDRESS:
647a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        args.GetReturnValue().Set(
648a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)            ASCIILiteralToV8String(args.GetIsolate(), "127.0.0.1"));
6497d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      case JSBindings::MY_IP_ADDRESS_EX:
6517d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        args.GetReturnValue().SetEmptyString();
6527d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        return;
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
6545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NOTREACHED();
6565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "sortIpAddressList()" is invoked by the PAC script.
6597d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void SortIpAddressListCallback(
6607d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
6615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need at least one string argument.
6627d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) {
6637d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().SetNull();
6647d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6657d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
6665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string ip_address_list = V8StringToUTF8(args[0]->ToString());
6687d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (!IsStringASCII(ip_address_list)) {
6697d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().SetNull();
6707d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6717d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
6725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string sorted_ip_address_list;
6735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    bool success = SortIpAddressList(ip_address_list, &sorted_ip_address_list);
6747d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (!success) {
6757d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().Set(false);
6767d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6777d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
678a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)    args.GetReturnValue().Set(
679a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)        ASCIIStringToV8String(args.GetIsolate(), sorted_ip_address_list));
6805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
6815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // V8 callback for when "isInNetEx()" is invoked by the PAC script.
6837d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)  static void IsInNetExCallback(
6847d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      const v8::FunctionCallbackInfo<v8::Value>& args) {
6855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    // We need at least 2 string arguments.
6865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (args.Length() < 2 || args[0].IsEmpty() || !args[0]->IsString() ||
6877d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)        args[1].IsEmpty() || !args[1]->IsString()) {
6887d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().SetNull();
6897d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6907d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
6915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
6925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string ip_address = V8StringToUTF8(args[0]->ToString());
6937d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (!IsStringASCII(ip_address)) {
6947d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().Set(false);
6957d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
6967d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
6975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    std::string ip_prefix = V8StringToUTF8(args[1]->ToString());
6987d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    if (!IsStringASCII(ip_prefix)) {
6997d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      args.GetReturnValue().Set(false);
7007d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)      return;
7017d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    }
7027d4cd473f85ac64c3747c96c277f9e506a0d2246Torne (Richard Coles)    args.GetReturnValue().Set(IsInNetEx(ip_address, ip_prefix));
7035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
7045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  mutable base::Lock lock_;
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyResolverV8* parent_;
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::Isolate* isolate_;
7085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Persistent<v8::External> v8_this_;
7095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  v8::Persistent<v8::Context> v8_context_;
7105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
7115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// ProxyResolverV8 ------------------------------------------------------------
7135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProxyResolverV8::ProxyResolverV8()
7155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    : ProxyResolver(true /*expects_pac_bytes*/),
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      js_bindings_(NULL) {
7175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ProxyResolverV8::~ProxyResolverV8() {}
7205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyResolverV8::GetProxyForURL(
7225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const GURL& query_url, ProxyInfo* results,
7235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CompletionCallback& /*callback*/,
7245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    RequestHandle* /*request*/,
7255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const BoundNetLog& net_log) {
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(js_bindings_);
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // If the V8 instance has not been initialized (either because
7295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // SetPacScript() wasn't called yet, or because it failed.
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!context_)
7315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_FAILED;
7325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Otherwise call into V8.
7345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = context_->ResolveProxy(query_url, results);
7355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
7375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyResolverV8::CancelRequest(RequestHandle request) {
7405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // This is a synchronous ProxyResolver; no possibility for async requests.
7415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
7425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)LoadState ProxyResolverV8::GetLoadState(RequestHandle request) const {
7455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
7465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return LOAD_STATE_IDLE;
7475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyResolverV8::CancelSetPacScript() {
7505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  NOTREACHED();
7515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void ProxyResolverV8::PurgeMemory() {
7544e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)  if (context_)
7554e180b6a0b4720a9b8e9e959a882386f690f08ffTorne (Richard Coles)    context_->PurgeMemory();
7565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)int ProxyResolverV8::SetPacScript(
7595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const scoped_refptr<ProxyResolverScriptData>& script_data,
7605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    const CompletionCallback& /*callback*/) {
761868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(script_data.get());
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(js_bindings_);
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  context_.reset();
7655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (script_data->utf16().empty())
7665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return ERR_PAC_SCRIPT_FAILED;
7675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  // Try parsing the PAC script.
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_ptr<Context> context(new Context(this, GetDefaultIsolate()));
7705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  int rv = context->InitV8(script_data);
7715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (rv == OK)
7725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    context_.reset(context.release());
7735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return rv;
7745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
7755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8::RememberDefaultIsolate() {
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::Isolate* isolate = v8::Isolate::GetCurrent();
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(isolate)
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "ProxyResolverV8::RememberDefaultIsolate called on wrong thread";
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(g_default_isolate_ == NULL || g_default_isolate_ == isolate)
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "Default Isolate can not be changed";
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_default_isolate_ = isolate;
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
786a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#if defined(OS_WIN)
787a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)// static
788a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)void ProxyResolverV8::CreateIsolate() {
789a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  v8::Isolate* isolate = v8::Isolate::New();
790a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(isolate);
791a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  DCHECK(g_default_isolate_ == NULL) << "Default Isolate can not be set twice";
792a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
793a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  isolate->Enter();
794a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  v8::V8::Initialize();
795a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
796a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)  g_default_isolate_ = isolate;
797a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)}
798a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)#endif  // defined(OS_WIN)
799a36e5920737c6adbddd3e43b760e5de8431db6e0Torne (Richard Coles)
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)v8::Isolate* ProxyResolverV8::GetDefaultIsolate() {
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(g_default_isolate_)
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      << "Must call ProxyResolverV8::RememberDefaultIsolate() first";
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return g_default_isolate_;
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)v8::Isolate* ProxyResolverV8::g_default_isolate_ = NULL;
8082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
8102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t ProxyResolverV8::GetTotalHeapSize() {
8112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!g_default_isolate_)
8122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
8132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::Locker locked(g_default_isolate_);
815f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  v8::Isolate::Scope isolate_scope(g_default_isolate_);
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::HeapStatistics heap_statistics;
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_default_isolate_->GetHeapStatistics(&heap_statistics);
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return heap_statistics.total_heap_size();
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t ProxyResolverV8::GetUsedHeapSize() {
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!g_default_isolate_)
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return 0;
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::Locker locked(g_default_isolate_);
827f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles)  v8::Isolate::Scope isolate_scope(g_default_isolate_);
8282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8::HeapStatistics heap_statistics;
8292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  g_default_isolate_->GetHeapStatistics(&heap_statistics);
8302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return heap_statistics.used_heap_size();
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}  // namespace net
834