1fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Use of this source code is governed by a BSD-style license that can be
3fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// found in the LICENSE file.
4fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
5fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk#include <algorithm>
6fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk#include <cstdio>
7fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk#include <string>
8fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
9f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk#include <utils/String16.h>
10f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk
11fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk#include "proxy_resolver_v8.h"
12fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
13fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk#include "proxy_resolver_script.h"
14fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk#include "net_util.h"
15fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk#include <include/v8.h>
16fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk#include <algorithm>
17fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk#include <vector>
18fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
19fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk#include <iostream>
20fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
21fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk#include <string.h>
22f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk#include <utils/String8.h>
23f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk#include <utils/String16.h>
24fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
25fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Notes on the javascript environment:
26fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk//
27fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// For the majority of the PAC utility functions, we use the same code
28fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// as Firefox. See the javascript library that proxy_resolver_scipt.h
29fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// pulls in.
30fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk//
31fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// In addition, we implement a subset of Microsoft's extensions to PAC.
32fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// - myIpAddressEx()
33fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// - dnsResolveEx()
34fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// - isResolvableEx()
35fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// - isInNetEx()
36fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// - sortIpAddressList()
37fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk//
38fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// It is worth noting that the original PAC specification does not describe
39fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// the return values on failure. Consequently, there are compatibility
40fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// differences between browsers on what to return on failure, which are
41fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// illustrated below:
42fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk//
43fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// --------------------+-------------+-------------------+--------------
44fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk//                     | Firefox3    | InternetExplorer8 |  --> Us <---
45fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// --------------------+-------------+-------------------+--------------
46fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// myIpAddress()       | "127.0.0.1" |  ???              |  "127.0.0.1"
47fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// dnsResolve()        | null        |  false            |  null
48fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// myIpAddressEx()     | N/A         |  ""               |  ""
49fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// sortIpAddressList() | N/A         |  false            |  false
50fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// dnsResolveEx()      | N/A         |  ""               |  ""
51fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// isInNetEx()         | N/A         |  false            |  false
52fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// --------------------+-------------+-------------------+--------------
53fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk//
54fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// TODO: The cell above reading ??? means I didn't test it.
55fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk//
56fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Another difference is in how dnsResolve() and myIpAddress() are
57fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// implemented -- whether they should restrict to IPv4 results, or
58fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// include both IPv4 and IPv6. The following table illustrates the
59fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// differences:
60fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk//
61fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// --------------------+-------------+-------------------+--------------
62fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk//                     | Firefox3    | InternetExplorer8 |  --> Us <---
63fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// --------------------+-------------+-------------------+--------------
64fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// myIpAddress()       | IPv4/IPv6   |  IPv4             |  IPv4
65fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// dnsResolve()        | IPv4/IPv6   |  IPv4             |  IPv4
66fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// isResolvable()      | IPv4/IPv6   |  IPv4             |  IPv4
67fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// myIpAddressEx()     | N/A         |  IPv4/IPv6        |  IPv4/IPv6
68fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// dnsResolveEx()      | N/A         |  IPv4/IPv6        |  IPv4/IPv6
69fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// sortIpAddressList() | N/A         |  IPv4/IPv6        |  IPv4/IPv6
70fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// isResolvableEx()    | N/A         |  IPv4/IPv6        |  IPv4/IPv6
71fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// isInNetEx()         | N/A         |  IPv4/IPv6        |  IPv4/IPv6
72fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// -----------------+-------------+-------------------+--------------
73fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
74f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monkstatic bool DoIsStringASCII(const android::String16& str) {
75f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  for (size_t i = 0; i < str.size(); i++) {
76f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk    unsigned short c = str.string()[i];
77fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (c > 0x7F)
78fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return false;
79fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
80fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return true;
81fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
82fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
83f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monkbool IsStringASCII(const android::String16& str) {
84fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return DoIsStringASCII(str);
85fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
86fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
87fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monknamespace net {
88fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
89fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monknamespace {
90fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
91fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Pseudo-name for the PAC script.
92fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkconst char kPacResourceName[] = "proxy-pac-script.js";
93fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Pseudo-name for the PAC utility script.
94fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkconst char kPacUtilityResourceName[] = "proxy-pac-utility-script.js";
95fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
96fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// External string wrapper so V8 can access the UTF16 string wrapped by
97fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// ProxyResolverScriptData.
98fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkclass V8ExternalStringFromScriptData
99fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    : public v8::String::ExternalStringResource {
100fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk public:
101fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  explicit V8ExternalStringFromScriptData(
102f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk      const android::String16& script_data)
103fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      : script_data_(script_data) {}
104fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
105fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  virtual const uint16_t* data() const {
106f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk    return script_data_.string();
107fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
108fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
109fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  virtual size_t length() const {
110fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return script_data_.size();
111fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
112fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
113fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk private:
114f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  const android::String16& script_data_;
115fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk//  DISALLOW_COPY_AND_ASSIGN(V8ExternalStringFromScriptData);
116fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk};
117fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
118fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// External string wrapper so V8 can access a string literal.
119fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkclass V8ExternalASCIILiteral : public v8::String::ExternalAsciiStringResource {
120fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk public:
121fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // |ascii| must be a NULL-terminated C string, and must remain valid
122fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // throughout this object's lifetime.
123fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  V8ExternalASCIILiteral(const char* ascii, size_t length)
124fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      : ascii_(ascii), length_(length) {
125fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
126fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
127fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  virtual const char* data() const {
128fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return ascii_;
129fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
130fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
131fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  virtual size_t length() const {
132fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return length_;
133fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
134fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
135fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk private:
136fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  const char* ascii_;
137fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  size_t length_;
138fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk};
139fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
140fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// When creating a v8::String from a C++ string we have two choices: create
141fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// a copy, or create a wrapper that shares the same underlying storage.
142fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// For small strings it is better to just make a copy, whereas for large
143fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// strings there are savings by sharing the storage. This number identifies
144fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// the cutoff length for when to start wrapping rather than creating copies.
145fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkconst size_t kMaxStringBytesForCopy = 256;
146fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
147fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monktemplate <class string_type>
148fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkinline typename string_type::value_type* WriteInto(string_type* str,
149fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk                                                   size_t length_with_null) {
150fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  str->reserve(length_with_null);
151fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  str->resize(length_with_null - 1);
152fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return &((*str)[0]);
153fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
154fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
155fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Converts a V8 String to a UTF8 std::string.
156fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkstd::string V8StringToUTF8(v8::Handle<v8::String> s) {
157fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  std::string result;
158fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  s->WriteUtf8(WriteInto(&result, s->Length() + 1));
159fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return result;
160fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
161fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
162fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Converts a V8 String to a UTF16 string.
163f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monkandroid::String16 V8StringToUTF16(v8::Handle<v8::String> s) {
164fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  int len = s->Length();
165f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  char16_t* buf = new char16_t[len + 1];
166f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  s->Write(buf, 0, len);
167f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  android::String16 ret(buf, len);
168f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  delete buf;
169f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  return ret;
170f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk}
171f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk
172f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monkstd::string UTF16ToASCII(const android::String16& str) {
17340adcb542a80576ad761fcb7362b98e9afd754faJason Monk  android::String8 rstr(str);
17440adcb542a80576ad761fcb7362b98e9afd754faJason Monk  return std::string(rstr.string());
175fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
176fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
177fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Converts an ASCII std::string to a V8 string.
1789fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monkv8::Local<v8::String> ASCIIStringToV8String(v8::Isolate* isolate, const std::string& s) {
1799fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  return v8::String::NewFromUtf8(isolate, s.data(), v8::String::kNormalString, s.size());
180fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
181fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
1829fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monkv8::Local<v8::String> UTF16StringToV8String(v8::Isolate* isolate, const android::String16& s) {
1839fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  return v8::String::NewFromTwoByte(isolate, s.string(), v8::String::kNormalString, s.size());
184f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk}
185f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk
186fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Converts an ASCII string literal to a V8 string.
1879fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monkv8::Local<v8::String> ASCIILiteralToV8String(v8::Isolate* isolate, const char* ascii) {
188fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk//  DCHECK(IsStringASCII(ascii));
189fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  size_t length = strlen(ascii);
190fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (length <= kMaxStringBytesForCopy)
1919fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    return v8::String::NewFromUtf8(isolate, ascii, v8::String::kNormalString, length);
1929fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  return v8::String::NewExternal(isolate, new V8ExternalASCIILiteral(ascii, length));
193fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
194fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
195fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Stringizes a V8 object by calling its toString() method. Returns true
196fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// on success. This may fail if the toString() throws an exception.
197fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkbool V8ObjectToUTF16String(v8::Handle<v8::Value> object,
1989fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk                           android::String16* utf16_result,
1999fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk                           v8::Isolate* isolate) {
200fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (object.IsEmpty())
201fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return false;
202fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
2039fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  v8::HandleScope scope(isolate);
204fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  v8::Local<v8::String> str_object = object->ToString();
205fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (str_object.IsEmpty())
206fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return false;
207fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  *utf16_result = V8StringToUTF16(str_object);
208fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return true;
209fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
210fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
211fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Extracts an hostname argument from |args|. On success returns true
212fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// and fills |*hostname| with the result.
2139fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monkbool GetHostnameArgument(const v8::FunctionCallbackInfo<v8::Value>& args, std::string* hostname) {
214fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // The first argument should be a string.
215fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString())
216fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return false;
217fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
218f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  const android::String16 hostname_utf16 = V8StringToUTF16(args[0]->ToString());
219fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
220fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // If the hostname is already in ASCII, simply return it as is.
221fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (IsStringASCII(hostname_utf16)) {
222fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    *hostname = UTF16ToASCII(hostname_utf16);
223fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return true;
224fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
225fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return false;
226fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
227fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
228fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Wrapper for passing around IP address strings and IPAddressNumber objects.
229fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkstruct IPAddress {
230fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  IPAddress(const std::string& ip_string, const IPAddressNumber& ip_number)
231fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      : string_value(ip_string),
232fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk        ip_address_number(ip_number) {
233fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
234fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
235fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // Used for sorting IP addresses in ascending order in SortIpAddressList().
236fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // IP6 addresses are placed ahead of IPv4 addresses.
237fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  bool operator<(const IPAddress& rhs) const {
238fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    const IPAddressNumber& ip1 = this->ip_address_number;
239fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    const IPAddressNumber& ip2 = rhs.ip_address_number;
240fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (ip1.size() != ip2.size())
241fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return ip1.size() > ip2.size();  // IPv6 before IPv4.
242fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return memcmp(&ip1[0], &ip2[0], ip1.size()) < 0;  // Ascending order.
243fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
244fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
245fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  std::string string_value;
246fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  IPAddressNumber ip_address_number;
247fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk};
248fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
249fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monktemplate<typename STR>
250fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkbool RemoveCharsT(const STR& input,
251fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk                  const typename STR::value_type remove_chars[],
252fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk                  STR* output) {
253fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  bool removed = false;
254fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  size_t found;
255fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
256fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  *output = input;
257fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
258fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  found = output->find_first_of(remove_chars);
259fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  while (found != STR::npos) {
260fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    removed = true;
261fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    output->replace(found, 1, STR());
262fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    found = output->find_first_of(remove_chars, found);
263fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
264fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
265fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return removed;
266fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
267fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
268fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkbool RemoveChars(const std::string& input,
269fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk                 const char remove_chars[],
270fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk                 std::string* output) {
271fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return RemoveCharsT(input, remove_chars, output);
272fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
273fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
274fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Handler for "sortIpAddressList(IpAddressList)". |ip_address_list| is a
275fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// semi-colon delimited string containing IP addresses.
276fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// |sorted_ip_address_list| is the resulting list of sorted semi-colon delimited
277fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// IP addresses or an empty string if unable to sort the IP address list.
278fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Returns 'true' if the sorting was successful, and 'false' if the input was an
279fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// empty string, a string of separators (";" in this case), or if any of the IP
280fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// addresses in the input list failed to parse.
281fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkbool SortIpAddressList(const std::string& ip_address_list,
282fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk                       std::string* sorted_ip_address_list) {
283fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  sorted_ip_address_list->clear();
284fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
285fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // Strip all whitespace (mimics IE behavior).
286fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  std::string cleaned_ip_address_list;
287fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  RemoveChars(ip_address_list, " \t", &cleaned_ip_address_list);
288fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (cleaned_ip_address_list.empty())
289fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return false;
290fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
291fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // Split-up IP addresses and store them in a vector.
292fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  std::vector<IPAddress> ip_vector;
293fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  IPAddressNumber ip_num;
294fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  char *tok_list = strtok((char *)cleaned_ip_address_list.c_str(), ";");
295fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  while (tok_list != NULL) {
296fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (!ParseIPLiteralToNumber(tok_list, &ip_num))
297fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return false;
298fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    ip_vector.push_back(IPAddress(tok_list, ip_num));
29986b75a5f88eda8b47d1e34e26dfc0210aec09367Jason Monk    tok_list = strtok(NULL, ";");
300fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
301fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
302fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (ip_vector.empty())  // Can happen if we have something like
303fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return false;         // sortIpAddressList(";") or sortIpAddressList("; ;")
304fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
305fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // Sort lists according to ascending numeric value.
306fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (ip_vector.size() > 1)
307fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    std::stable_sort(ip_vector.begin(), ip_vector.end());
308fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
309fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // Return a semi-colon delimited list of sorted addresses (IPv6 followed by
310fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // IPv4).
311fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  for (size_t i = 0; i < ip_vector.size(); ++i) {
312fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (i > 0)
313fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      *sorted_ip_address_list += ";";
314fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    *sorted_ip_address_list += ip_vector[i].string_value;
315fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
316fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return true;
317fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
318fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
319fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
320fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Handler for "isInNetEx(ip_address, ip_prefix)". |ip_address| is a string
321fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// containing an IPv4/IPv6 address, and |ip_prefix| is a string containg a
322fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// slash-delimited IP prefix with the top 'n' bits specified in the bit
323fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// field. This returns 'true' if the address is in the same subnet, and
324fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// 'false' otherwise. Also returns 'false' if the prefix is in an incorrect
325fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// format, or if an address and prefix of different types are used (e.g. IPv6
326fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// address and IPv4 prefix).
327fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkbool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) {
328fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  IPAddressNumber address;
329eafc0fa00299168e43ad7d42c545c18b12aa8f3eJason Monk  std::string cleaned_ip_address;
330eafc0fa00299168e43ad7d42c545c18b12aa8f3eJason Monk  if (RemoveChars(ip_address, " \t", &cleaned_ip_address))
331eafc0fa00299168e43ad7d42c545c18b12aa8f3eJason Monk    return false;
332fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (!ParseIPLiteralToNumber(ip_address, &address))
333fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return false;
334fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
335fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  IPAddressNumber prefix;
336fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  size_t prefix_length_in_bits;
337fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (!ParseCIDRBlock(ip_prefix, &prefix, &prefix_length_in_bits))
338fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return false;
339fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
340fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // Both |address| and |prefix| must be of the same type (IPv4 or IPv6).
341fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (address.size() != prefix.size())
342fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return false;
343fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
344fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits);
345fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
346fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
347fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}  // namespace
348fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
349fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// ProxyResolverV8::Context ---------------------------------------------------
350fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
351fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkclass ProxyResolverV8::Context {
352fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk public:
353f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  explicit Context(ProxyResolverJSBindings* js_bindings,
3549fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk          ProxyErrorListener* error_listener, v8::Isolate* isolate)
3559fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      : js_bindings_(js_bindings), error_listener_(error_listener), isolate_(isolate) {
356fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
357fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
358fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  ~Context() {
3599fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Locker locked(isolate_);
3609fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Isolate::Scope isolate_scope(isolate_);
361fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
3629fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8_this_.Reset();
3639fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8_context_.Reset();
364fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
365fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
36640adcb542a80576ad761fcb7362b98e9afd754faJason Monk  int ResolveProxy(const android::String16 url, const android::String16 host,
36740adcb542a80576ad761fcb7362b98e9afd754faJason Monk        android::String16* results) {
3689fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Locker locked(isolate_);
3699fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Isolate::Scope isolate_scope(isolate_);
3709fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::HandleScope scope(isolate_);
371fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
3729fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Local<v8::Context> context =
3739fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::Local<v8::Context>::New(isolate_, v8_context_);
3749fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Context::Scope function_scope(context);
375fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
376fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::Value> function;
377fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (!GetFindProxyForURL(&function)) {
37840adcb542a80576ad761fcb7362b98e9afd754faJason Monk      error_listener_->ErrorMessage(
37940adcb542a80576ad761fcb7362b98e9afd754faJason Monk          android::String16("FindProxyForURL() is undefined"));
380fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return ERR_PAC_SCRIPT_FAILED;
381fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
382fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
383fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Handle<v8::Value> argv[] = {
3849fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        UTF16StringToV8String(isolate_, url),
3859fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        UTF16StringToV8String(isolate_, host) };
386fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
387fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::TryCatch try_catch;
388fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::Value> ret = v8::Function::Cast(*function)->Call(
3899fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        context->Global(), 2, argv);
390fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
391fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (try_catch.HasCaught()) {
39240adcb542a80576ad761fcb7362b98e9afd754faJason Monk      error_listener_->ErrorMessage(
39340adcb542a80576ad761fcb7362b98e9afd754faJason Monk          V8StringToUTF16(try_catch.Message()->Get()));
394fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return ERR_PAC_SCRIPT_FAILED;
395fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
396fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
397fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (!ret->IsString()) {
39840adcb542a80576ad761fcb7362b98e9afd754faJason Monk      error_listener_->ErrorMessage(
39940adcb542a80576ad761fcb7362b98e9afd754faJason Monk          android::String16("FindProxyForURL() did not return a string."));
400fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return ERR_PAC_SCRIPT_FAILED;
401fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
402fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
403f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk    *results = V8StringToUTF16(ret->ToString());
404fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
405f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk    if (!IsStringASCII(*results)) {
406fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      // TODO:         Rather than failing when a wide string is returned, we
407fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      //               could extend the parsing to handle IDNA hostnames by
408fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      //               converting them to ASCII punycode.
409fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      //               crbug.com/47234
41040adcb542a80576ad761fcb7362b98e9afd754faJason Monk      error_listener_->ErrorMessage(
41140adcb542a80576ad761fcb7362b98e9afd754faJason Monk          android::String16("FindProxyForURL() returned a non-ASCII string"));
412fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return ERR_PAC_SCRIPT_FAILED;
413fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
414fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
415fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return OK;
416fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
417fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
418f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  int InitV8(const android::String16& pac_script) {
4199fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Locker locked(isolate_);
4209fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Isolate::Scope isolate_scope(isolate_);
4219fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::HandleScope scope(isolate_);
422fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
4239fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8_this_.Reset(isolate_, v8::External::New(isolate_, this));
4249fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Local<v8::External> v8_this =
4259fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::Local<v8::External>::New(isolate_, v8_this_);
426fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New();
427fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
428fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // Attach the javascript bindings.
429fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::FunctionTemplate> alert_template =
4309fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::FunctionTemplate::New(isolate_, &AlertCallback, v8_this);
4319fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    global_template->Set(ASCIILiteralToV8String(isolate_, "alert"), alert_template);
432fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
433fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::FunctionTemplate> my_ip_address_template =
4349fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::FunctionTemplate::New(isolate_, &MyIpAddressCallback, v8_this);
4359fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    global_template->Set(ASCIILiteralToV8String(isolate_, "myIpAddress"),
436fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk        my_ip_address_template);
437fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
438fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::FunctionTemplate> dns_resolve_template =
4399fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::FunctionTemplate::New(isolate_, &DnsResolveCallback, v8_this);
4409fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    global_template->Set(ASCIILiteralToV8String(isolate_, "dnsResolve"),
441fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk        dns_resolve_template);
442fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
443fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // Microsoft's PAC extensions:
444fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
445fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::FunctionTemplate> dns_resolve_ex_template =
4469fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::FunctionTemplate::New(isolate_, &DnsResolveExCallback, v8_this);
4479fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    global_template->Set(ASCIILiteralToV8String(isolate_, "dnsResolveEx"),
448fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk                         dns_resolve_ex_template);
449fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
450fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::FunctionTemplate> my_ip_address_ex_template =
4519fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::FunctionTemplate::New(isolate_, &MyIpAddressExCallback, v8_this);
4529fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    global_template->Set(ASCIILiteralToV8String(isolate_, "myIpAddressEx"),
453fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk                         my_ip_address_ex_template);
454fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
455fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::FunctionTemplate> sort_ip_address_list_template =
4569fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::FunctionTemplate::New(isolate_, &SortIpAddressListCallback, v8_this);
4579fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    global_template->Set(ASCIILiteralToV8String(isolate_, "sortIpAddressList"),
458fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk                         sort_ip_address_list_template);
459fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
460fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::FunctionTemplate> is_in_net_ex_template =
4619fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::FunctionTemplate::New(isolate_, &IsInNetExCallback, v8_this);
4629fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    global_template->Set(ASCIILiteralToV8String(isolate_, "isInNetEx"),
463fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk                         is_in_net_ex_template);
464fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
4659fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8_context_.Reset(
4669fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        isolate_, v8::Context::New(isolate_, NULL, global_template));
467fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
4689fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Local<v8::Context> context =
4699fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::Local<v8::Context>::New(isolate_, v8_context_);
4709fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Context::Scope ctx(context);
471fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
472fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // Add the PAC utility functions to the environment.
473fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // (This script should never fail, as it is a string literal!)
474fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // Note that the two string literals are concatenated.
475fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    int rv = RunScript(
4769fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        ASCIILiteralToV8String(isolate_,
477fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk            PROXY_RESOLVER_SCRIPT
478fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk            PROXY_RESOLVER_SCRIPT_EX),
479fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk        kPacUtilityResourceName);
480fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (rv != OK) {
481fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return rv;
482fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
483fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
484fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // Add the user's PAC code to the environment.
4859fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    rv = RunScript(UTF16StringToV8String(isolate_, pac_script), kPacResourceName);
486fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (rv != OK) {
487fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return rv;
488fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
489fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
490fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // At a minimum, the FindProxyForURL() function must be defined for this
491fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // to be a legitimiate PAC script.
492fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::Value> function;
493fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (!GetFindProxyForURL(&function))
494fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return ERR_PAC_SCRIPT_FAILED;
495fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
496fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return OK;
497fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
498fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
499fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  void PurgeMemory() {
5009fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Locker locked(isolate_);
5019fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Isolate::Scope isolate_scope(isolate_);
50270629c0d8c1463827b3e81d50cd9aebd77d690a6Bill Yi    isolate_->LowMemoryNotification();
503fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
504fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
505fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk private:
506fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  bool GetFindProxyForURL(v8::Local<v8::Value>* function) {
5079fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    v8::Local<v8::Context> context =
5089fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::Local<v8::Context>::New(isolate_, v8_context_);
5099fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    *function = context->Global()->Get(
5109fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        ASCIILiteralToV8String(isolate_, "FindProxyForURL"));
511fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return (*function)->IsFunction();
512fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
513fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
514fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // Handle an exception thrown by V8.
515fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  void HandleError(v8::Handle<v8::Message> message) {
516fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (message.IsEmpty())
517fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return;
518f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk    error_listener_->ErrorMessage(V8StringToUTF16(message->Get()));
519fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
520fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
521fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // Compiles and runs |script| in the current V8 context.
522fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // Returns OK on success, otherwise an error code.
523fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  int RunScript(v8::Handle<v8::String> script, const char* script_name) {
524fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::TryCatch try_catch;
525fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
526fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // Compile the script.
527fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::ScriptOrigin origin =
5289fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        v8::ScriptOrigin(ASCIILiteralToV8String(isolate_, script_name));
529fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    v8::Local<v8::Script> code = v8::Script::Compile(script, &origin);
530fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
531fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // Execute.
532fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (!code.IsEmpty())
533fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      code->Run();
534fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
535fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // Check for errors.
536fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (try_catch.HasCaught()) {
537fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      HandleError(try_catch.Message());
538fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      return ERR_PAC_SCRIPT_FAILED;
539fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
540fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
541fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return OK;
542fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
543fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
544fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // V8 callback for when "alert()" is invoked by the PAC script.
5459fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  static void AlertCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
546fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    Context* context =
547fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk        static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
548fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
549fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // Like firefox we assume "undefined" if no argument was specified, and
550fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // disregard any arguments beyond the first.
551f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk    android::String16 message;
552fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (args.Length() == 0) {
553fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      std::string undef = "undefined";
554f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk      android::String8 undef8(undef.c_str());
555f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk      android::String16 wundef(undef8);
556fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      message = wundef;
557fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    } else {
5589fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      if (!V8ObjectToUTF16String(args[0], &message, args.GetIsolate()))
5599fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        return;  // toString() threw an exception.
560fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
561fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
562f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk    context->error_listener_->AlertMessage(message);
5639fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    return;
564fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
565fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
566fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // V8 callback for when "myIpAddress()" is invoked by the PAC script.
5679fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  static void MyIpAddressCallback(
5689fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      const v8::FunctionCallbackInfo<v8::Value>& args) {
569fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    Context* context =
570fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk        static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
571fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
572fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    std::string result;
573fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    bool success;
574fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
575fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    {
5769fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      v8::Unlocker unlocker(args.GetIsolate());
577fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
578fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      // We shouldn't be called with any arguments, but will not complain if
579fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      // we are.
580fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      success = context->js_bindings_->MyIpAddress(&result);
581fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
582fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
5839fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    if (!success) {
5849fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      args.GetReturnValue().Set(ASCIILiteralToV8String(args.GetIsolate(), "127.0.0.1"));
5859fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    } else {
5869fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      args.GetReturnValue().Set(ASCIIStringToV8String(args.GetIsolate(), result));
5879fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    }
588fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
589fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
590fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // V8 callback for when "myIpAddressEx()" is invoked by the PAC script.
5919fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  static void MyIpAddressExCallback(
5929fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      const v8::FunctionCallbackInfo<v8::Value>& args) {
593fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    Context* context =
594fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk        static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
595fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
596fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    std::string ip_address_list;
597fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    bool success;
598fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
599fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    {
6009fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      v8::Unlocker unlocker(args.GetIsolate());
601fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
602fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      // We shouldn't be called with any arguments, but will not complain if
603fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      // we are.
604fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      success = context->js_bindings_->MyIpAddressEx(&ip_address_list);
605fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
606fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
607fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (!success)
608fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      ip_address_list = std::string();
6099fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    args.GetReturnValue().Set(ASCIIStringToV8String(args.GetIsolate(), ip_address_list));
610fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
611fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
612fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // V8 callback for when "dnsResolve()" is invoked by the PAC script.
6139fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  static void DnsResolveCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
614fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    Context* context =
615fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk        static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
616fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
617fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // We need at least one string argument.
618fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    std::string hostname;
6199fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    if (!GetHostnameArgument(args, &hostname)) {
6209fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      return;
6219fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    }
622fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
623fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    std::string ip_address;
624fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    bool success;
625fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
626fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    {
6279fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      v8::Unlocker unlocker(args.GetIsolate());
628fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      success = context->js_bindings_->DnsResolve(hostname, &ip_address);
629fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
630fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
6319fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    if (success) {
6329fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      args.GetReturnValue().Set(ASCIIStringToV8String(args.GetIsolate(), ip_address));
6339fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    } else {
6349fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      args.GetReturnValue().SetNull();
6359fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    }
636fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
637fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
638fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // V8 callback for when "dnsResolveEx()" is invoked by the PAC script.
6399fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  static void DnsResolveExCallback(
6409fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      const v8::FunctionCallbackInfo<v8::Value>& args) {
641fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    Context* context =
642fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk        static_cast<Context*>(v8::External::Cast(*args.Data())->Value());
643fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
644fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // We need at least one string argument.
645fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    std::string hostname;
6469fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    if (!GetHostnameArgument(args, &hostname)) {
6479fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      args.GetReturnValue().SetNull();
6489fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      return;
6499fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    }
650fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
651fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    std::string ip_address_list;
652fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    bool success;
653fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
654fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    {
6559fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      v8::Unlocker unlocker(args.GetIsolate());
656fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      success = context->js_bindings_->DnsResolveEx(hostname, &ip_address_list);
657fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    }
658fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
659fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (!success)
660fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk      ip_address_list = std::string();
661fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
6629fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    args.GetReturnValue().Set(ASCIIStringToV8String(args.GetIsolate(), ip_address_list));
663fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
664fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
665fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // V8 callback for when "sortIpAddressList()" is invoked by the PAC script.
6669fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  static void SortIpAddressListCallback(
6679fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      const v8::FunctionCallbackInfo<v8::Value>& args) {
668fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // We need at least one string argument.
6699fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) {
6709fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      args.GetReturnValue().SetNull();
6719fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      return;
6729fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    }
673fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
674fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    std::string ip_address_list = V8StringToUTF8(args[0]->ToString());
675fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    std::string sorted_ip_address_list;
676fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    bool success = SortIpAddressList(ip_address_list, &sorted_ip_address_list);
6779fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    if (!success) {
6789fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      args.GetReturnValue().Set(false);
6799fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      return;
6809fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    }
6819fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    args.GetReturnValue().Set(ASCIIStringToV8String(args.GetIsolate(), sorted_ip_address_list));
682fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
683fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
684fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // V8 callback for when "isInNetEx()" is invoked by the PAC script.
6859fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  static void IsInNetExCallback(const v8::FunctionCallbackInfo<v8::Value>& args) {
686fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    // We need at least 2 string arguments.
687fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    if (args.Length() < 2 || args[0].IsEmpty() || !args[0]->IsString() ||
6889fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk        args[1].IsEmpty() || !args[1]->IsString()) {
6899fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      args.GetReturnValue().SetNull();
6909fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk      return;
6919fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    }
692fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
693fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    std::string ip_address = V8StringToUTF8(args[0]->ToString());
694fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    std::string ip_prefix = V8StringToUTF8(args[1]->ToString());
6959fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk    args.GetReturnValue().Set(IsInNetEx(ip_address, ip_prefix));
696fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
697fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
698fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  ProxyResolverJSBindings* js_bindings_;
699f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  ProxyErrorListener* error_listener_;
7009fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  v8::Isolate* isolate_;
701fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  v8::Persistent<v8::External> v8_this_;
702fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  v8::Persistent<v8::Context> v8_context_;
703fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk};
704fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
705fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// ProxyResolverV8 ------------------------------------------------------------
706fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
707fc93418c483ce474a1f4888b50f92574a1b81be3Jason MonkProxyResolverV8::ProxyResolverV8(
708f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk    ProxyResolverJSBindings* custom_js_bindings,
709f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk    ProxyErrorListener* error_listener)
710f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk    : context_(NULL), js_bindings_(custom_js_bindings),
711f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk      error_listener_(error_listener) {
7127439df18c87ef1ffff4b3d8b77fa9b07f829c45dJason Monk  v8::V8::Initialize();
713fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
714fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
715fc93418c483ce474a1f4888b50f92574a1b81be3Jason MonkProxyResolverV8::~ProxyResolverV8() {
716c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk  if (context_ != NULL) {
717c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk    delete context_;
718c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk    context_ = NULL;
719c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk  }
720c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk  if (js_bindings_ != NULL) {
721c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk    delete js_bindings_;
722c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk  }
723fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
724fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
725f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monkint ProxyResolverV8::GetProxyForURL(const android::String16 spec, const android::String16 host,
726f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk                                    android::String16* results) {
727fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // If the V8 instance has not been initialized (either because
728fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // SetPacScript() wasn't called yet, or because it failed.
729fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (context_ == NULL)
730fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return ERR_FAILED;
731fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
732fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // Otherwise call into V8.
733fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  int rv = context_->ResolveProxy(spec, host, results);
734fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
735fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return rv;
736fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
737fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
738fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkvoid ProxyResolverV8::PurgeMemory() {
739fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  context_->PurgeMemory();
740fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
741fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
74240adcb542a80576ad761fcb7362b98e9afd754faJason Monkint ProxyResolverV8::SetPacScript(const android::String16& script_data) {
743fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (context_ != NULL) {
744fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    delete context_;
745c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk    context_ = NULL;
746fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
747f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk  if (script_data.size() == 0)
748fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    return ERR_PAC_SCRIPT_FAILED;
749fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
750fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  // Try parsing the PAC script.
7519fd69be73a96299c7658aa72fc02c4cca4c7b3eaJason Monk  context_ = new Context(js_bindings_, error_listener_, v8::Isolate::New());
752fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  int rv;
753fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if ((rv = context_->InitV8(script_data)) != OK) {
754fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    context_ = NULL;
755fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  }
756fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  if (rv != OK)
757fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk    context_ = NULL;
758fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk  return rv;
759fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}
760fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk
761fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}  // namespace net
762