proxy_resolver_v8.cc revision 86b75a5f88eda8b47d1e34e26dfc0210aec09367
1579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Copyright (c) 2010 The Chromium Authors. All rights reserved. 2579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Use of this source code is governed by a BSD-style license that can be 3579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// found in the LICENSE file. 4579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 5579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <algorithm> 6579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <cstdio> 7579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <string> 8579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 9579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <utils/String16.h> 10579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 11579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "proxy_resolver_v8.h" 12579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 13579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "proxy_resolver_script.h" 14579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include "net_util.h" 15579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <include/v8.h> 16579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <algorithm> 17579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <vector> 18579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 19579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <iostream> 20579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 21579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <string.h> 22579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <utils/String8.h> 23579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson#include <utils/String16.h> 24579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 25579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Notes on the javascript environment: 26579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// 27579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// For the majority of the PAC utility functions, we use the same code 28579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// as Firefox. See the javascript library that proxy_resolver_scipt.h 29579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// pulls in. 30579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// 31579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// In addition, we implement a subset of Microsoft's extensions to PAC. 32579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// - myIpAddressEx() 33579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// - dnsResolveEx() 34579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// - isResolvableEx() 35579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// - isInNetEx() 36579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// - sortIpAddressList() 37579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// 38579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// It is worth noting that the original PAC specification does not describe 39579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// the return values on failure. Consequently, there are compatibility 40579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// differences between browsers on what to return on failure, which are 41579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// illustrated below: 42579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// 43579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// --------------------+-------------+-------------------+-------------- 44579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// | Firefox3 | InternetExplorer8 | --> Us <--- 45579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// --------------------+-------------+-------------------+-------------- 46579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// myIpAddress() | "127.0.0.1" | ??? | "127.0.0.1" 47579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// dnsResolve() | null | false | null 48579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// myIpAddressEx() | N/A | "" | "" 49579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// sortIpAddressList() | N/A | false | false 50579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// dnsResolveEx() | N/A | "" | "" 51579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// isInNetEx() | N/A | false | false 52579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// --------------------+-------------+-------------------+-------------- 53579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// 54579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// TODO: The cell above reading ??? means I didn't test it. 55579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// 56579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Another difference is in how dnsResolve() and myIpAddress() are 57579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// implemented -- whether they should restrict to IPv4 results, or 58579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// include both IPv4 and IPv6. The following table illustrates the 59579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// differences: 60579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// 61579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// --------------------+-------------+-------------------+-------------- 62579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// | Firefox3 | InternetExplorer8 | --> Us <--- 63579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// --------------------+-------------+-------------------+-------------- 64579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// myIpAddress() | IPv4/IPv6 | IPv4 | IPv4 65579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// dnsResolve() | IPv4/IPv6 | IPv4 | IPv4 66579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// isResolvable() | IPv4/IPv6 | IPv4 | IPv4 67579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// myIpAddressEx() | N/A | IPv4/IPv6 | IPv4/IPv6 68579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// dnsResolveEx() | N/A | IPv4/IPv6 | IPv4/IPv6 69579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// sortIpAddressList() | N/A | IPv4/IPv6 | IPv4/IPv6 70579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// isResolvableEx() | N/A | IPv4/IPv6 | IPv4/IPv6 71579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// isInNetEx() | N/A | IPv4/IPv6 | IPv4/IPv6 72579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// -----------------+-------------+-------------------+-------------- 73579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 74579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonstatic bool DoIsStringASCII(const android::String16& str) { 75579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (size_t i = 0; i < str.size(); i++) { 76579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson unsigned short c = str.string()[i]; 77579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (c > 0x7F) 78579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 79579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 80579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return true; 81579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 82579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 83579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonbool IsStringASCII(const android::String16& str) { 84579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return DoIsStringASCII(str); 85579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 86579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 87579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonnamespace net { 88579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 89579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonnamespace { 90579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 91579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Pseudo-name for the PAC script. 92579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonconst char kPacResourceName[] = "proxy-pac-script.js"; 93579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Pseudo-name for the PAC utility script. 94579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonconst char kPacUtilityResourceName[] = "proxy-pac-utility-script.js"; 95579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 96579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// External string wrapper so V8 can access the UTF16 string wrapped by 97579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// ProxyResolverScriptData. 98579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonclass V8ExternalStringFromScriptData 99579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson : public v8::String::ExternalStringResource { 100579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public: 101579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson explicit V8ExternalStringFromScriptData( 102579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson const android::String16& script_data) 103579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson : script_data_(script_data) {} 104579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 105579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson virtual const uint16_t* data() const { 106579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return script_data_.string(); 107579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 108579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 109579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson virtual size_t length() const { 110579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return script_data_.size(); 111579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 112579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 113579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private: 114579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson const android::String16& script_data_; 115579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// DISALLOW_COPY_AND_ASSIGN(V8ExternalStringFromScriptData); 116579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}; 117579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 118579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// External string wrapper so V8 can access a string literal. 119579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonclass V8ExternalASCIILiteral : public v8::String::ExternalAsciiStringResource { 120579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson public: 121579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // |ascii| must be a NULL-terminated C string, and must remain valid 122579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // throughout this object's lifetime. 123579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson V8ExternalASCIILiteral(const char* ascii, size_t length) 124579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson : ascii_(ascii), length_(length) { 125579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 126579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 127579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson virtual const char* data() const { 128579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ascii_; 129579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 130579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 131579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson virtual size_t length() const { 132579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return length_; 133579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 134579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 135579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson private: 136579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson const char* ascii_; 137579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson size_t length_; 138579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}; 139579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 140579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// When creating a v8::String from a C++ string we have two choices: create 141579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// a copy, or create a wrapper that shares the same underlying storage. 142579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// For small strings it is better to just make a copy, whereas for large 143579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// strings there are savings by sharing the storage. This number identifies 144579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// the cutoff length for when to start wrapping rather than creating copies. 145579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonconst size_t kMaxStringBytesForCopy = 256; 146579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 147579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsontemplate <class string_type> 148579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsoninline typename string_type::value_type* WriteInto(string_type* str, 149579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson size_t length_with_null) { 150579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson str->reserve(length_with_null); 151579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson str->resize(length_with_null - 1); 152579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return &((*str)[0]); 153579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 154579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 155579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Converts a V8 String to a UTF8 std::string. 156579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonstd::string V8StringToUTF8(v8::Handle<v8::String> s) { 157579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson std::string result; 158579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson s->WriteUtf8(WriteInto(&result, s->Length() + 1)); 159579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return result; 160579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 161579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 162579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Converts a V8 String to a UTF16 string. 163579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonandroid::String16 V8StringToUTF16(v8::Handle<v8::String> s) { 164579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson int len = s->Length(); 165579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson char16_t* buf = new char16_t[len + 1]; 166579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson s->Write(buf, 0, len); 167579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson android::String16 ret(buf, len); 168579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson delete buf; 169579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ret; 170579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 171579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 172579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonstd::string UTF16ToASCII(const android::String16& str) { 173579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson android::String8 rstr(str); 174579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return std::string(rstr.string()); 175579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 176579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 177579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonandroid::String16 ASCIIToUTF16(const std::string str) { 178579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson android::String8 str8(str.c_str()); 179579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return android::String16(str8); 180579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 181579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 182579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Converts an ASCII std::string to a V8 string. 183579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonv8::Local<v8::String> ASCIIStringToV8String(const std::string& s) { 184579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return v8::String::New(s.data(), s.size()); 185579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 186579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 187579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonv8::Local<v8::String> UTF16StringToV8String(const android::String16& s) { 188579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return v8::String::New(s.string(), s.size()); 189579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 190579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 191579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Converts an ASCII string literal to a V8 string. 192579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonv8::Local<v8::String> ASCIILiteralToV8String(const char* ascii) { 193579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// DCHECK(IsStringASCII(ascii)); 194579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson size_t length = strlen(ascii); 195579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (length <= kMaxStringBytesForCopy) 196579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return v8::String::New(ascii, length); 197579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return v8::String::NewExternal(new V8ExternalASCIILiteral(ascii, length)); 198579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 199579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 200579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Stringizes a V8 object by calling its toString() method. Returns true 201579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// on success. This may fail if the toString() throws an exception. 202579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonbool V8ObjectToUTF16String(v8::Handle<v8::Value> object, 203579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson android::String16* utf16_result) { 204579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (object.IsEmpty()) 205579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 206579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 207579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson v8::HandleScope scope; 208579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson v8::Local<v8::String> str_object = object->ToString(); 209579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (str_object.IsEmpty()) 210579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 211579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *utf16_result = V8StringToUTF16(str_object); 212579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return true; 213579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 214579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 215579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Extracts an hostname argument from |args|. On success returns true 216579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// and fills |*hostname| with the result. 217579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonbool GetHostnameArgument(const v8::Arguments& args, std::string* hostname) { 218579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // The first argument should be a string. 219579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) 220579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 221579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 222579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson const android::String16 hostname_utf16 = V8StringToUTF16(args[0]->ToString()); 223579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 224579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // If the hostname is already in ASCII, simply return it as is. 225579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (IsStringASCII(hostname_utf16)) { 226579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *hostname = UTF16ToASCII(hostname_utf16); 227579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return true; 228579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 229579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 230579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 231579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 232579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Wrapper for passing around IP address strings and IPAddressNumber objects. 233579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonstruct IPAddress { 234579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson IPAddress(const std::string& ip_string, const IPAddressNumber& ip_number) 235579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson : string_value(ip_string), 236579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ip_address_number(ip_number) { 237579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 238579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 239579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Used for sorting IP addresses in ascending order in SortIpAddressList(). 240579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // IP6 addresses are placed ahead of IPv4 addresses. 241579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson bool operator<(const IPAddress& rhs) const { 242579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson const IPAddressNumber& ip1 = this->ip_address_number; 243579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson const IPAddressNumber& ip2 = rhs.ip_address_number; 244579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (ip1.size() != ip2.size()) 245579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return ip1.size() > ip2.size(); // IPv6 before IPv4. 246579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return memcmp(&ip1[0], &ip2[0], ip1.size()) < 0; // Ascending order. 247579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 248579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 249579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson std::string string_value; 250579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson IPAddressNumber ip_address_number; 251579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson}; 252579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 253579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsontemplate<typename STR> 254579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonbool RemoveCharsT(const STR& input, 255579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson const typename STR::value_type remove_chars[], 256579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson STR* output) { 257579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson bool removed = false; 258579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson size_t found; 259579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 260579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson *output = input; 261579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 262579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson found = output->find_first_of(remove_chars); 263579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson while (found != STR::npos) { 264579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson removed = true; 265579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson output->replace(found, 1, STR()); 266579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson found = output->find_first_of(remove_chars, found); 267579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 268579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 269579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return removed; 270579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 271579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 272579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonbool RemoveChars(const std::string& input, 273579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson const char remove_chars[], 274579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson std::string* output) { 275579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return RemoveCharsT(input, remove_chars, output); 276579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson} 277579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 278579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Handler for "sortIpAddressList(IpAddressList)". |ip_address_list| is a 279579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// semi-colon delimited string containing IP addresses. 280579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// |sorted_ip_address_list| is the resulting list of sorted semi-colon delimited 281579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// IP addresses or an empty string if unable to sort the IP address list. 282579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// Returns 'true' if the sorting was successful, and 'false' if the input was an 283579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// empty string, a string of separators (";" in this case), or if any of the IP 284579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson// addresses in the input list failed to parse. 285579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilsonbool SortIpAddressList(const std::string& ip_address_list, 286579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson std::string* sorted_ip_address_list) { 287579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson sorted_ip_address_list->clear(); 288579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 289579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Strip all whitespace (mimics IE behavior). 290579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson std::string cleaned_ip_address_list; 291579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson RemoveChars(ip_address_list, " \t", &cleaned_ip_address_list); 292579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (cleaned_ip_address_list.empty()) 293579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 294579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 295579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Split-up IP addresses and store them in a vector. 296579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson std::vector<IPAddress> ip_vector; 297579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson IPAddressNumber ip_num; 298579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson char *tok_list = strtok((char *)cleaned_ip_address_list.c_str(), ";"); 299579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson while (tok_list != NULL) { 300579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (!ParseIPLiteralToNumber(tok_list, &ip_num)) 301579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; 302579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson ip_vector.push_back(IPAddress(tok_list, ip_num)); 303579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson tok_list = strtok(NULL, ";"); 304579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson } 305579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 306579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (ip_vector.empty()) // Can happen if we have something like 307579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson return false; // sortIpAddressList(";") or sortIpAddressList("; ;") 308579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 309579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Sort lists according to ascending numeric value. 310579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (ip_vector.size() > 1) 311579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson std::stable_sort(ip_vector.begin(), ip_vector.end()); 312579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson 313579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // Return a semi-colon delimited list of sorted addresses (IPv6 followed by 314579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson // IPv4). 315579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson for (size_t i = 0; i < ip_vector.size(); ++i) { 316579d7739c53a2707ad711a2d2cae46d7d782f06Jesse Wilson if (i > 0) 317 *sorted_ip_address_list += ";"; 318 *sorted_ip_address_list += ip_vector[i].string_value; 319 } 320 return true; 321} 322 323 324// Handler for "isInNetEx(ip_address, ip_prefix)". |ip_address| is a string 325// containing an IPv4/IPv6 address, and |ip_prefix| is a string containg a 326// slash-delimited IP prefix with the top 'n' bits specified in the bit 327// field. This returns 'true' if the address is in the same subnet, and 328// 'false' otherwise. Also returns 'false' if the prefix is in an incorrect 329// format, or if an address and prefix of different types are used (e.g. IPv6 330// address and IPv4 prefix). 331bool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) { 332 IPAddressNumber address; 333 if (!ParseIPLiteralToNumber(ip_address, &address)) 334 return false; 335 336 IPAddressNumber prefix; 337 size_t prefix_length_in_bits; 338 if (!ParseCIDRBlock(ip_prefix, &prefix, &prefix_length_in_bits)) 339 return false; 340 341 // Both |address| and |prefix| must be of the same type (IPv4 or IPv6). 342 if (address.size() != prefix.size()) 343 return false; 344 345 return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits); 346} 347 348} // namespace 349 350// ProxyResolverV8::Context --------------------------------------------------- 351 352class ProxyResolverV8::Context { 353 public: 354 explicit Context(ProxyResolverJSBindings* js_bindings, 355 ProxyErrorListener* error_listener) 356 : js_bindings_(js_bindings), error_listener_(error_listener) { 357 } 358 359 ~Context() { 360 v8::Locker locked; 361 362 v8_this_.Dispose(); 363 v8_context_.Dispose(); 364 365 // Run the V8 garbage collector. We do this to be sure the 366 // ExternalStringResource objects we allocated get properly disposed. 367 // Otherwise when running the unit-tests they may get leaked. 368 // See crbug.com/48145. 369 PurgeMemory(); 370 } 371 372 int ResolveProxy(const android::String16 url, const android::String16 host, android::String16* results) { 373 v8::Locker locked; 374 v8::HandleScope scope; 375 376 v8::Context::Scope function_scope(v8_context_); 377 378 v8::Local<v8::Value> function; 379 if (!GetFindProxyForURL(&function)) { 380 *results = ASCIIToUTF16("FindProxyForURL() is undefined"); 381 return ERR_PAC_SCRIPT_FAILED; 382 } 383 384 v8::Handle<v8::Value> argv[] = { 385 UTF16StringToV8String(url), 386 UTF16StringToV8String(host) }; 387 388 v8::TryCatch try_catch; 389 v8::Local<v8::Value> ret = v8::Function::Cast(*function)->Call( 390 v8_context_->Global(), 2, argv); 391 392 if (try_catch.HasCaught()) { 393 *results = V8StringToUTF16(try_catch.Message()->Get()); 394 return ERR_PAC_SCRIPT_FAILED; 395 } 396 397 if (!ret->IsString()) { 398 *results = ASCIIToUTF16("FindProxyForURL() did not return a string."); 399 return ERR_PAC_SCRIPT_FAILED; 400 } 401 402 *results = V8StringToUTF16(ret->ToString()); 403 404 if (!IsStringASCII(*results)) { 405 // TODO: Rather than failing when a wide string is returned, we 406 // could extend the parsing to handle IDNA hostnames by 407 // converting them to ASCII punycode. 408 // crbug.com/47234 409 *results = ASCIIToUTF16("FindProxyForURL() returned a non-ASCII string"); 410 return ERR_PAC_SCRIPT_FAILED; 411 } 412 413 return OK; 414 } 415 416 int InitV8(const android::String16& pac_script) { 417 v8::Locker locked; 418 v8::HandleScope scope; 419 420 v8_this_ = v8::Persistent<v8::External>::New(v8::External::New(this)); 421 v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); 422 423 // Attach the javascript bindings. 424 v8::Local<v8::FunctionTemplate> alert_template = 425 v8::FunctionTemplate::New(&AlertCallback, v8_this_); 426 global_template->Set(ASCIILiteralToV8String("alert"), alert_template); 427 428 v8::Local<v8::FunctionTemplate> my_ip_address_template = 429 v8::FunctionTemplate::New(&MyIpAddressCallback, v8_this_); 430 global_template->Set(ASCIILiteralToV8String("myIpAddress"), 431 my_ip_address_template); 432 433 v8::Local<v8::FunctionTemplate> dns_resolve_template = 434 v8::FunctionTemplate::New(&DnsResolveCallback, v8_this_); 435 global_template->Set(ASCIILiteralToV8String("dnsResolve"), 436 dns_resolve_template); 437 438 // Microsoft's PAC extensions: 439 440 v8::Local<v8::FunctionTemplate> dns_resolve_ex_template = 441 v8::FunctionTemplate::New(&DnsResolveExCallback, v8_this_); 442 global_template->Set(ASCIILiteralToV8String("dnsResolveEx"), 443 dns_resolve_ex_template); 444 445 v8::Local<v8::FunctionTemplate> my_ip_address_ex_template = 446 v8::FunctionTemplate::New(&MyIpAddressExCallback, v8_this_); 447 global_template->Set(ASCIILiteralToV8String("myIpAddressEx"), 448 my_ip_address_ex_template); 449 450 v8::Local<v8::FunctionTemplate> sort_ip_address_list_template = 451 v8::FunctionTemplate::New(&SortIpAddressListCallback, v8_this_); 452 global_template->Set(ASCIILiteralToV8String("sortIpAddressList"), 453 sort_ip_address_list_template); 454 455 v8::Local<v8::FunctionTemplate> is_in_net_ex_template = 456 v8::FunctionTemplate::New(&IsInNetExCallback, v8_this_); 457 global_template->Set(ASCIILiteralToV8String("isInNetEx"), 458 is_in_net_ex_template); 459 460 v8_context_ = v8::Context::New(NULL, global_template); 461 462 v8::Context::Scope ctx(v8_context_); 463 464 // Add the PAC utility functions to the environment. 465 // (This script should never fail, as it is a string literal!) 466 // Note that the two string literals are concatenated. 467 int rv = RunScript( 468 ASCIILiteralToV8String( 469 PROXY_RESOLVER_SCRIPT 470 PROXY_RESOLVER_SCRIPT_EX), 471 kPacUtilityResourceName); 472 if (rv != OK) { 473 return rv; 474 } 475 476 // Add the user's PAC code to the environment. 477 rv = RunScript(UTF16StringToV8String(pac_script), kPacResourceName); 478 if (rv != OK) { 479 return rv; 480 } 481 482 // At a minimum, the FindProxyForURL() function must be defined for this 483 // to be a legitimiate PAC script. 484 v8::Local<v8::Value> function; 485 if (!GetFindProxyForURL(&function)) 486 return ERR_PAC_SCRIPT_FAILED; 487 488 return OK; 489 } 490 491 void PurgeMemory() { 492 v8::Locker locked; 493 // Repeatedly call the V8 idle notification until it returns true ("nothing 494 // more to free"). Note that it makes more sense to do this than to 495 // implement a new "delete everything" pass because object references make 496 // it difficult to free everything possible in just one pass. 497 while (!v8::V8::IdleNotification()) 498 ; 499 } 500 501 private: 502 bool GetFindProxyForURL(v8::Local<v8::Value>* function) { 503 *function = v8_context_->Global()->Get( 504 ASCIILiteralToV8String("FindProxyForURL")); 505 return (*function)->IsFunction(); 506 } 507 508 // Handle an exception thrown by V8. 509 void HandleError(v8::Handle<v8::Message> message) { 510 if (message.IsEmpty()) 511 return; 512 error_listener_->ErrorMessage(V8StringToUTF16(message->Get())); 513 } 514 515 // Compiles and runs |script| in the current V8 context. 516 // Returns OK on success, otherwise an error code. 517 int RunScript(v8::Handle<v8::String> script, const char* script_name) { 518 v8::TryCatch try_catch; 519 520 // Compile the script. 521 v8::ScriptOrigin origin = 522 v8::ScriptOrigin(ASCIILiteralToV8String(script_name)); 523 v8::Local<v8::Script> code = v8::Script::Compile(script, &origin); 524 525 // Execute. 526 if (!code.IsEmpty()) 527 code->Run(); 528 529 // Check for errors. 530 if (try_catch.HasCaught()) { 531 HandleError(try_catch.Message()); 532 return ERR_PAC_SCRIPT_FAILED; 533 } 534 535 return OK; 536 } 537 538 // V8 callback for when "alert()" is invoked by the PAC script. 539 static v8::Handle<v8::Value> AlertCallback(const v8::Arguments& args) { 540 Context* context = 541 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 542 543 // Like firefox we assume "undefined" if no argument was specified, and 544 // disregard any arguments beyond the first. 545 android::String16 message; 546 if (args.Length() == 0) { 547 std::string undef = "undefined"; 548 android::String8 undef8(undef.c_str()); 549 android::String16 wundef(undef8); 550 message = wundef; 551 } else { 552 if (!V8ObjectToUTF16String(args[0], &message)) 553 return v8::Undefined(); // toString() threw an exception. 554 } 555 556 context->error_listener_->AlertMessage(message); 557 return v8::Undefined(); 558 } 559 560 // V8 callback for when "myIpAddress()" is invoked by the PAC script. 561 static v8::Handle<v8::Value> MyIpAddressCallback(const v8::Arguments& args) { 562 Context* context = 563 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 564 565 std::string result; 566 bool success; 567 568 { 569 v8::Unlocker unlocker; 570 571 // We shouldn't be called with any arguments, but will not complain if 572 // we are. 573 success = context->js_bindings_->MyIpAddress(&result); 574 } 575 576 if (!success) 577 return ASCIILiteralToV8String("127.0.0.1"); 578 return ASCIIStringToV8String(result); 579 } 580 581 // V8 callback for when "myIpAddressEx()" is invoked by the PAC script. 582 static v8::Handle<v8::Value> MyIpAddressExCallback( 583 const v8::Arguments& args) { 584 Context* context = 585 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 586 587 std::string ip_address_list; 588 bool success; 589 590 { 591 v8::Unlocker unlocker; 592 593 // We shouldn't be called with any arguments, but will not complain if 594 // we are. 595 success = context->js_bindings_->MyIpAddressEx(&ip_address_list); 596 } 597 598 if (!success) 599 ip_address_list = std::string(); 600 return ASCIIStringToV8String(ip_address_list); 601 } 602 603 // V8 callback for when "dnsResolve()" is invoked by the PAC script. 604 static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) { 605 Context* context = 606 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 607 608 // We need at least one string argument. 609 std::string hostname; 610 if (!GetHostnameArgument(args, &hostname)) 611 return v8::Null(); 612 613 std::string ip_address; 614 bool success; 615 616 { 617 v8::Unlocker unlocker; 618 success = context->js_bindings_->DnsResolve(hostname, &ip_address); 619 } 620 621 return success ? ASCIIStringToV8String(ip_address) : v8::Null(); 622 } 623 624 // V8 callback for when "dnsResolveEx()" is invoked by the PAC script. 625 static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) { 626 Context* context = 627 static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 628 629 // We need at least one string argument. 630 std::string hostname; 631 if (!GetHostnameArgument(args, &hostname)) 632 return v8::Undefined(); 633 634 std::string ip_address_list; 635 bool success; 636 637 { 638 v8::Unlocker unlocker; 639 success = context->js_bindings_->DnsResolveEx(hostname, &ip_address_list); 640 } 641 642 if (!success) 643 ip_address_list = std::string(); 644 645 return ASCIIStringToV8String(ip_address_list); 646 } 647 648 // V8 callback for when "sortIpAddressList()" is invoked by the PAC script. 649 static v8::Handle<v8::Value> SortIpAddressListCallback( 650 const v8::Arguments& args) { 651 // We need at least one string argument. 652 if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) 653 return v8::Null(); 654 655 std::string ip_address_list = V8StringToUTF8(args[0]->ToString()); 656 std::string sorted_ip_address_list; 657 bool success = SortIpAddressList(ip_address_list, &sorted_ip_address_list); 658 if (!success) 659 return v8::False(); 660 return ASCIIStringToV8String(sorted_ip_address_list); 661 } 662 663 // V8 callback for when "isInNetEx()" is invoked by the PAC script. 664 static v8::Handle<v8::Value> IsInNetExCallback(const v8::Arguments& args) { 665 // We need at least 2 string arguments. 666 if (args.Length() < 2 || args[0].IsEmpty() || !args[0]->IsString() || 667 args[1].IsEmpty() || !args[1]->IsString()) 668 return v8::Null(); 669 670 std::string ip_address = V8StringToUTF8(args[0]->ToString()); 671 std::string ip_prefix = V8StringToUTF8(args[1]->ToString()); 672 return IsInNetEx(ip_address, ip_prefix) ? v8::True() : v8::False(); 673 } 674 675 ProxyResolverJSBindings* js_bindings_; 676 ProxyErrorListener* error_listener_; 677 v8::Persistent<v8::External> v8_this_; 678 v8::Persistent<v8::Context> v8_context_; 679}; 680 681// ProxyResolverV8 ------------------------------------------------------------ 682 683ProxyResolverV8::ProxyResolverV8( 684 ProxyResolverJSBindings* custom_js_bindings, 685 ProxyErrorListener* error_listener) 686 : context_(NULL), js_bindings_(custom_js_bindings), 687 error_listener_(error_listener) { 688 689} 690 691ProxyResolverV8::~ProxyResolverV8() { 692 if (context_ != NULL) { 693 delete context_; 694 context_ = NULL; 695 } 696 if (js_bindings_ != NULL) { 697 delete js_bindings_; 698 } 699} 700 701int ProxyResolverV8::GetProxyForURL(const android::String16 spec, const android::String16 host, 702 android::String16* results) { 703 // If the V8 instance has not been initialized (either because 704 // SetPacScript() wasn't called yet, or because it failed. 705 if (context_ == NULL) 706 return ERR_FAILED; 707 708 // Otherwise call into V8. 709 int rv = context_->ResolveProxy(spec, host, results); 710 711 return rv; 712} 713 714void ProxyResolverV8::PurgeMemory() { 715 context_->PurgeMemory(); 716} 717 718int ProxyResolverV8::SetPacScript(android::String16& script_data) { 719 if (context_ != NULL) { 720 delete context_; 721 context_ = NULL; 722 } 723 if (script_data.size() == 0) 724 return ERR_PAC_SCRIPT_FAILED; 725 726 // Try parsing the PAC script. 727 context_ = new Context(js_bindings_, error_listener_); 728 int rv; 729 if ((rv = context_->InitV8(script_data)) != OK) { 730 context_ = NULL; 731 } 732 if (rv != OK) 733 context_ = NULL; 734 return rv; 735} 736 737} // namespace net 738