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. 178fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkv8::Local<v8::String> ASCIIStringToV8String(const std::string& s) { 179fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return v8::String::New(s.data(), s.size()); 180fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 181fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 182f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monkv8::Local<v8::String> UTF16StringToV8String(const android::String16& s) { 183f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk return v8::String::New(s.string(), s.size()); 184f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk} 185f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk 186fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Converts an ASCII string literal to a V8 string. 187fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkv8::Local<v8::String> ASCIILiteralToV8String(const char* ascii) { 188fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// DCHECK(IsStringASCII(ascii)); 189fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk size_t length = strlen(ascii); 190fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (length <= kMaxStringBytesForCopy) 191fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return v8::String::New(ascii, length); 192fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return v8::String::NewExternal(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, 198f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk android::String16* utf16_result) { 199fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (object.IsEmpty()) 200fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return false; 201fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 202fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::HandleScope scope; 203fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::String> str_object = object->ToString(); 204fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (str_object.IsEmpty()) 205fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return false; 206fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk *utf16_result = V8StringToUTF16(str_object); 207fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return true; 208fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 209fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 210fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Extracts an hostname argument from |args|. On success returns true 211fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// and fills |*hostname| with the result. 212fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkbool GetHostnameArgument(const v8::Arguments& args, std::string* hostname) { 213fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // The first argument should be a string. 214fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) 215fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return false; 216fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 217f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk const android::String16 hostname_utf16 = V8StringToUTF16(args[0]->ToString()); 218fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 219fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // If the hostname is already in ASCII, simply return it as is. 220fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (IsStringASCII(hostname_utf16)) { 221fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk *hostname = UTF16ToASCII(hostname_utf16); 222fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return true; 223fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 224fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return false; 225fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 226fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 227fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Wrapper for passing around IP address strings and IPAddressNumber objects. 228fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkstruct IPAddress { 229fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk IPAddress(const std::string& ip_string, const IPAddressNumber& ip_number) 230fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk : string_value(ip_string), 231fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk ip_address_number(ip_number) { 232fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 233fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 234fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Used for sorting IP addresses in ascending order in SortIpAddressList(). 235fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // IP6 addresses are placed ahead of IPv4 addresses. 236fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk bool operator<(const IPAddress& rhs) const { 237fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk const IPAddressNumber& ip1 = this->ip_address_number; 238fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk const IPAddressNumber& ip2 = rhs.ip_address_number; 239fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (ip1.size() != ip2.size()) 240fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ip1.size() > ip2.size(); // IPv6 before IPv4. 241fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return memcmp(&ip1[0], &ip2[0], ip1.size()) < 0; // Ascending order. 242fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 243fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 244fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string string_value; 245fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk IPAddressNumber ip_address_number; 246fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}; 247fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 248fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monktemplate<typename STR> 249fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkbool RemoveCharsT(const STR& input, 250fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk const typename STR::value_type remove_chars[], 251fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk STR* output) { 252fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk bool removed = false; 253fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk size_t found; 254fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 255fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk *output = input; 256fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 257fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk found = output->find_first_of(remove_chars); 258fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk while (found != STR::npos) { 259fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk removed = true; 260fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk output->replace(found, 1, STR()); 261fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk found = output->find_first_of(remove_chars, found); 262fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 263fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 264fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return removed; 265fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 266fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 267fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkbool RemoveChars(const std::string& input, 268fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk const char remove_chars[], 269fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string* output) { 270fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return RemoveCharsT(input, remove_chars, output); 271fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 272fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 273fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Handler for "sortIpAddressList(IpAddressList)". |ip_address_list| is a 274fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// semi-colon delimited string containing IP addresses. 275fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// |sorted_ip_address_list| is the resulting list of sorted semi-colon delimited 276fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// IP addresses or an empty string if unable to sort the IP address list. 277fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Returns 'true' if the sorting was successful, and 'false' if the input was an 278fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// empty string, a string of separators (";" in this case), or if any of the IP 279fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// addresses in the input list failed to parse. 280fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkbool SortIpAddressList(const std::string& ip_address_list, 281fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string* sorted_ip_address_list) { 282fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk sorted_ip_address_list->clear(); 283fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 284fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Strip all whitespace (mimics IE behavior). 285fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string cleaned_ip_address_list; 286fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk RemoveChars(ip_address_list, " \t", &cleaned_ip_address_list); 287fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (cleaned_ip_address_list.empty()) 288fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return false; 289fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 290fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Split-up IP addresses and store them in a vector. 291fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::vector<IPAddress> ip_vector; 292fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk IPAddressNumber ip_num; 293fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk char *tok_list = strtok((char *)cleaned_ip_address_list.c_str(), ";"); 294fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk while (tok_list != NULL) { 295fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!ParseIPLiteralToNumber(tok_list, &ip_num)) 296fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return false; 297fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk ip_vector.push_back(IPAddress(tok_list, ip_num)); 29886b75a5f88eda8b47d1e34e26dfc0210aec09367Jason Monk tok_list = strtok(NULL, ";"); 299fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 300fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 301fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (ip_vector.empty()) // Can happen if we have something like 302fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return false; // sortIpAddressList(";") or sortIpAddressList("; ;") 303fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 304fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Sort lists according to ascending numeric value. 305fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (ip_vector.size() > 1) 306fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::stable_sort(ip_vector.begin(), ip_vector.end()); 307fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 308fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Return a semi-colon delimited list of sorted addresses (IPv6 followed by 309fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // IPv4). 310fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk for (size_t i = 0; i < ip_vector.size(); ++i) { 311fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (i > 0) 312fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk *sorted_ip_address_list += ";"; 313fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk *sorted_ip_address_list += ip_vector[i].string_value; 314fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 315fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return true; 316fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 317fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 318fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 319fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// Handler for "isInNetEx(ip_address, ip_prefix)". |ip_address| is a string 320fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// containing an IPv4/IPv6 address, and |ip_prefix| is a string containg a 321fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// slash-delimited IP prefix with the top 'n' bits specified in the bit 322fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// field. This returns 'true' if the address is in the same subnet, and 323fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// 'false' otherwise. Also returns 'false' if the prefix is in an incorrect 324fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// format, or if an address and prefix of different types are used (e.g. IPv6 325fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// address and IPv4 prefix). 326fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkbool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) { 327fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk IPAddressNumber address; 328eafc0fa00299168e43ad7d42c545c18b12aa8f3eJason Monk std::string cleaned_ip_address; 329eafc0fa00299168e43ad7d42c545c18b12aa8f3eJason Monk if (RemoveChars(ip_address, " \t", &cleaned_ip_address)) 330eafc0fa00299168e43ad7d42c545c18b12aa8f3eJason Monk return false; 331fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!ParseIPLiteralToNumber(ip_address, &address)) 332fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return false; 333fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 334fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk IPAddressNumber prefix; 335fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk size_t prefix_length_in_bits; 336fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!ParseCIDRBlock(ip_prefix, &prefix, &prefix_length_in_bits)) 337fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return false; 338fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 339fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Both |address| and |prefix| must be of the same type (IPv4 or IPv6). 340fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (address.size() != prefix.size()) 341fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return false; 342fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 343fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return IPNumberMatchesPrefix(address, prefix, prefix_length_in_bits); 344fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 345fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 346fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} // namespace 347fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 348fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// ProxyResolverV8::Context --------------------------------------------------- 349fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 350fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkclass ProxyResolverV8::Context { 351fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk public: 352f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk explicit Context(ProxyResolverJSBindings* js_bindings, 353f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk ProxyErrorListener* error_listener) 354f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk : js_bindings_(js_bindings), error_listener_(error_listener) { 355fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 356fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 357fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk ~Context() { 358fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Locker locked; 359fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 360fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8_this_.Dispose(); 361fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8_context_.Dispose(); 362fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 363fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Run the V8 garbage collector. We do this to be sure the 364fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // ExternalStringResource objects we allocated get properly disposed. 365fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Otherwise when running the unit-tests they may get leaked. 366fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // See crbug.com/48145. 367fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk PurgeMemory(); 368fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 369fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 37040adcb542a80576ad761fcb7362b98e9afd754faJason Monk int ResolveProxy(const android::String16 url, const android::String16 host, 37140adcb542a80576ad761fcb7362b98e9afd754faJason Monk android::String16* results) { 372fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Locker locked; 373fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::HandleScope scope; 374fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 375fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Context::Scope function_scope(v8_context_); 376fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 377fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::Value> function; 378fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!GetFindProxyForURL(&function)) { 37940adcb542a80576ad761fcb7362b98e9afd754faJason Monk error_listener_->ErrorMessage( 38040adcb542a80576ad761fcb7362b98e9afd754faJason Monk android::String16("FindProxyForURL() is undefined")); 381fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ERR_PAC_SCRIPT_FAILED; 382fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 383fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 384fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Handle<v8::Value> argv[] = { 385f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk UTF16StringToV8String(url), 386f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk UTF16StringToV8String(host) }; 387fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 388fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::TryCatch try_catch; 389fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::Value> ret = v8::Function::Cast(*function)->Call( 390fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8_context_->Global(), 2, argv); 391fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 392fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (try_catch.HasCaught()) { 39340adcb542a80576ad761fcb7362b98e9afd754faJason Monk error_listener_->ErrorMessage( 39440adcb542a80576ad761fcb7362b98e9afd754faJason Monk V8StringToUTF16(try_catch.Message()->Get())); 395fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ERR_PAC_SCRIPT_FAILED; 396fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 397fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 398fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!ret->IsString()) { 39940adcb542a80576ad761fcb7362b98e9afd754faJason Monk error_listener_->ErrorMessage( 40040adcb542a80576ad761fcb7362b98e9afd754faJason Monk android::String16("FindProxyForURL() did not return a string.")); 401fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ERR_PAC_SCRIPT_FAILED; 402fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 403fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 404f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk *results = V8StringToUTF16(ret->ToString()); 405fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 406f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk if (!IsStringASCII(*results)) { 407fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // TODO: Rather than failing when a wide string is returned, we 408fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // could extend the parsing to handle IDNA hostnames by 409fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // converting them to ASCII punycode. 410fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // crbug.com/47234 41140adcb542a80576ad761fcb7362b98e9afd754faJason Monk error_listener_->ErrorMessage( 41240adcb542a80576ad761fcb7362b98e9afd754faJason Monk android::String16("FindProxyForURL() returned a non-ASCII string")); 413fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ERR_PAC_SCRIPT_FAILED; 414fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 415fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 416fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return OK; 417fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 418fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 419f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk int InitV8(const android::String16& pac_script) { 420fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Locker locked; 421fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::HandleScope scope; 422fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 423fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8_this_ = v8::Persistent<v8::External>::New(v8::External::New(this)); 424fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::ObjectTemplate> global_template = v8::ObjectTemplate::New(); 425fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 426fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Attach the javascript bindings. 427fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::FunctionTemplate> alert_template = 428fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::FunctionTemplate::New(&AlertCallback, v8_this_); 429fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk global_template->Set(ASCIILiteralToV8String("alert"), alert_template); 430fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 431fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::FunctionTemplate> my_ip_address_template = 432fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::FunctionTemplate::New(&MyIpAddressCallback, v8_this_); 433fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk global_template->Set(ASCIILiteralToV8String("myIpAddress"), 434fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk my_ip_address_template); 435fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 436fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::FunctionTemplate> dns_resolve_template = 437fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::FunctionTemplate::New(&DnsResolveCallback, v8_this_); 438fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk global_template->Set(ASCIILiteralToV8String("dnsResolve"), 439fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk dns_resolve_template); 440fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 441fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Microsoft's PAC extensions: 442fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 443fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::FunctionTemplate> dns_resolve_ex_template = 444fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::FunctionTemplate::New(&DnsResolveExCallback, v8_this_); 445fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk global_template->Set(ASCIILiteralToV8String("dnsResolveEx"), 446fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk dns_resolve_ex_template); 447fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 448fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::FunctionTemplate> my_ip_address_ex_template = 449fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::FunctionTemplate::New(&MyIpAddressExCallback, v8_this_); 450fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk global_template->Set(ASCIILiteralToV8String("myIpAddressEx"), 451fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk my_ip_address_ex_template); 452fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 453fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::FunctionTemplate> sort_ip_address_list_template = 454fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::FunctionTemplate::New(&SortIpAddressListCallback, v8_this_); 455fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk global_template->Set(ASCIILiteralToV8String("sortIpAddressList"), 456fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk sort_ip_address_list_template); 457fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 458fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::FunctionTemplate> is_in_net_ex_template = 459fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::FunctionTemplate::New(&IsInNetExCallback, v8_this_); 460fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk global_template->Set(ASCIILiteralToV8String("isInNetEx"), 461fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk is_in_net_ex_template); 462fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 463fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8_context_ = v8::Context::New(NULL, global_template); 464fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 465fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Context::Scope ctx(v8_context_); 466fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 467fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Add the PAC utility functions to the environment. 468fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // (This script should never fail, as it is a string literal!) 469fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Note that the two string literals are concatenated. 470fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk int rv = RunScript( 471fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk ASCIILiteralToV8String( 472fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk PROXY_RESOLVER_SCRIPT 473fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk PROXY_RESOLVER_SCRIPT_EX), 474fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk kPacUtilityResourceName); 475fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (rv != OK) { 476fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return rv; 477fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 478fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 479fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Add the user's PAC code to the environment. 480f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk rv = RunScript(UTF16StringToV8String(pac_script), kPacResourceName); 481fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (rv != OK) { 482fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return rv; 483fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 484fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 485fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // At a minimum, the FindProxyForURL() function must be defined for this 486fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // to be a legitimiate PAC script. 487fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::Value> function; 488fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!GetFindProxyForURL(&function)) 489fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ERR_PAC_SCRIPT_FAILED; 490fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 491fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return OK; 492fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 493fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 494fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk void PurgeMemory() { 495fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Locker locked; 496fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Repeatedly call the V8 idle notification until it returns true ("nothing 497fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // more to free"). Note that it makes more sense to do this than to 498fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // implement a new "delete everything" pass because object references make 499fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // it difficult to free everything possible in just one pass. 500fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk while (!v8::V8::IdleNotification()) 501fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk ; 502fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 503fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 504fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk private: 505fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk bool GetFindProxyForURL(v8::Local<v8::Value>* function) { 506fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk *function = v8_context_->Global()->Get( 507fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk ASCIILiteralToV8String("FindProxyForURL")); 508fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return (*function)->IsFunction(); 509fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 510fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 511fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Handle an exception thrown by V8. 512fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk void HandleError(v8::Handle<v8::Message> message) { 513fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (message.IsEmpty()) 514fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return; 515f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk error_listener_->ErrorMessage(V8StringToUTF16(message->Get())); 516fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 517fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 518fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Compiles and runs |script| in the current V8 context. 519fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Returns OK on success, otherwise an error code. 520fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk int RunScript(v8::Handle<v8::String> script, const char* script_name) { 521fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::TryCatch try_catch; 522fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 523fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Compile the script. 524fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::ScriptOrigin origin = 525fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::ScriptOrigin(ASCIILiteralToV8String(script_name)); 526fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Local<v8::Script> code = v8::Script::Compile(script, &origin); 527fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 528fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Execute. 529fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!code.IsEmpty()) 530fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk code->Run(); 531fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 532fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Check for errors. 533fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (try_catch.HasCaught()) { 534fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk HandleError(try_catch.Message()); 535fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ERR_PAC_SCRIPT_FAILED; 536fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 537fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 538fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return OK; 539fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 540fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 541fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // V8 callback for when "alert()" is invoked by the PAC script. 542fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static v8::Handle<v8::Value> AlertCallback(const v8::Arguments& args) { 543fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk Context* context = 544fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 545fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 546fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Like firefox we assume "undefined" if no argument was specified, and 547fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // disregard any arguments beyond the first. 548f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk android::String16 message; 549fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (args.Length() == 0) { 550fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string undef = "undefined"; 551f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk android::String8 undef8(undef.c_str()); 552f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk android::String16 wundef(undef8); 553fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk message = wundef; 554fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } else { 555fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!V8ObjectToUTF16String(args[0], &message)) 556fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return v8::Undefined(); // toString() threw an exception. 557fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 558fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 559f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk context->error_listener_->AlertMessage(message); 560fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return v8::Undefined(); 561fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 562fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 563fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // V8 callback for when "myIpAddress()" is invoked by the PAC script. 564fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static v8::Handle<v8::Value> MyIpAddressCallback(const v8::Arguments& args) { 565fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk Context* context = 566fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 567fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 568fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string result; 569fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk bool success; 570fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 571fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk { 572fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Unlocker unlocker; 573fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 574fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // We shouldn't be called with any arguments, but will not complain if 575fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // we are. 576fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk success = context->js_bindings_->MyIpAddress(&result); 577fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 578fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 579fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!success) 580fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ASCIILiteralToV8String("127.0.0.1"); 581fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ASCIIStringToV8String(result); 582fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 583fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 584fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // V8 callback for when "myIpAddressEx()" is invoked by the PAC script. 585fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static v8::Handle<v8::Value> MyIpAddressExCallback( 586fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk const v8::Arguments& args) { 587fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk Context* context = 588fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 589fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 590fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string ip_address_list; 591fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk bool success; 592fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 593fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk { 594fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Unlocker unlocker; 595fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 596fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // We shouldn't be called with any arguments, but will not complain if 597fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // we are. 598fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk success = context->js_bindings_->MyIpAddressEx(&ip_address_list); 599fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 600fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 601fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!success) 602fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk ip_address_list = std::string(); 603fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ASCIIStringToV8String(ip_address_list); 604fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 605fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 606fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // V8 callback for when "dnsResolve()" is invoked by the PAC script. 607fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static v8::Handle<v8::Value> DnsResolveCallback(const v8::Arguments& args) { 608fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk Context* context = 609fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 610fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 611fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // We need at least one string argument. 612fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string hostname; 613fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!GetHostnameArgument(args, &hostname)) 614fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return v8::Null(); 615fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 616fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string ip_address; 617fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk bool success; 618fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 619fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk { 620fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Unlocker unlocker; 621fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk success = context->js_bindings_->DnsResolve(hostname, &ip_address); 622fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 623fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 624fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return success ? ASCIIStringToV8String(ip_address) : v8::Null(); 625fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 626fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 627fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // V8 callback for when "dnsResolveEx()" is invoked by the PAC script. 628fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static v8::Handle<v8::Value> DnsResolveExCallback(const v8::Arguments& args) { 629fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk Context* context = 630fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static_cast<Context*>(v8::External::Cast(*args.Data())->Value()); 631fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 632fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // We need at least one string argument. 633fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string hostname; 634fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!GetHostnameArgument(args, &hostname)) 635fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return v8::Undefined(); 636fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 637fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string ip_address_list; 638fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk bool success; 639fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 640fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk { 641fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Unlocker unlocker; 642fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk success = context->js_bindings_->DnsResolveEx(hostname, &ip_address_list); 643fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 644fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 645fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!success) 646fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk ip_address_list = std::string(); 647fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 648fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ASCIIStringToV8String(ip_address_list); 649fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 650fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 651fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // V8 callback for when "sortIpAddressList()" is invoked by the PAC script. 652fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static v8::Handle<v8::Value> SortIpAddressListCallback( 653fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk const v8::Arguments& args) { 654fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // We need at least one string argument. 655fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (args.Length() == 0 || args[0].IsEmpty() || !args[0]->IsString()) 656fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return v8::Null(); 657fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 658fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string ip_address_list = V8StringToUTF8(args[0]->ToString()); 659fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string sorted_ip_address_list; 660fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk bool success = SortIpAddressList(ip_address_list, &sorted_ip_address_list); 661fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (!success) 662fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return v8::False(); 663fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ASCIIStringToV8String(sorted_ip_address_list); 664fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 665fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 666fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // V8 callback for when "isInNetEx()" is invoked by the PAC script. 667fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk static v8::Handle<v8::Value> IsInNetExCallback(const v8::Arguments& args) { 668fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // We need at least 2 string arguments. 669fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (args.Length() < 2 || args[0].IsEmpty() || !args[0]->IsString() || 670fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk args[1].IsEmpty() || !args[1]->IsString()) 671fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return v8::Null(); 672fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 673fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string ip_address = V8StringToUTF8(args[0]->ToString()); 674fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk std::string ip_prefix = V8StringToUTF8(args[1]->ToString()); 675fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return IsInNetEx(ip_address, ip_prefix) ? v8::True() : v8::False(); 676fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 677fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 678fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk ProxyResolverJSBindings* js_bindings_; 679f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk ProxyErrorListener* error_listener_; 680fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Persistent<v8::External> v8_this_; 681fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk v8::Persistent<v8::Context> v8_context_; 682fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk}; 683fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 684fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk// ProxyResolverV8 ------------------------------------------------------------ 685fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 686fc93418c483ce474a1f4888b50f92574a1b81be3Jason MonkProxyResolverV8::ProxyResolverV8( 687f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk ProxyResolverJSBindings* custom_js_bindings, 688f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk ProxyErrorListener* error_listener) 689f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk : context_(NULL), js_bindings_(custom_js_bindings), 690f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk error_listener_(error_listener) { 691f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk 692fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 693fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 694fc93418c483ce474a1f4888b50f92574a1b81be3Jason MonkProxyResolverV8::~ProxyResolverV8() { 695c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk if (context_ != NULL) { 696c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk delete context_; 697c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk context_ = NULL; 698c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk } 699c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk if (js_bindings_ != NULL) { 700c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk delete js_bindings_; 701c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk } 702fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 703fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 704f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monkint ProxyResolverV8::GetProxyForURL(const android::String16 spec, const android::String16 host, 705f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk android::String16* results) { 706fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // If the V8 instance has not been initialized (either because 707fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // SetPacScript() wasn't called yet, or because it failed. 708fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (context_ == NULL) 709fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ERR_FAILED; 710fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 711fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Otherwise call into V8. 712fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk int rv = context_->ResolveProxy(spec, host, results); 713fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 714fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return rv; 715fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 716fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 717fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monkvoid ProxyResolverV8::PurgeMemory() { 718fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk context_->PurgeMemory(); 719fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 720fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 72140adcb542a80576ad761fcb7362b98e9afd754faJason Monkint ProxyResolverV8::SetPacScript(const android::String16& script_data) { 722fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (context_ != NULL) { 723fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk delete context_; 724c06a8d69b50384113df4a17824c68bbfce7fb578Jason Monk context_ = NULL; 725fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 726f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk if (script_data.size() == 0) 727fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return ERR_PAC_SCRIPT_FAILED; 728fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 729fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk // Try parsing the PAC script. 730f5cf6e34aa6c6b061eb6f33f2f82c95177e16648Jason Monk context_ = new Context(js_bindings_, error_listener_); 731fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk int rv; 732fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if ((rv = context_->InitV8(script_data)) != OK) { 733fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk context_ = NULL; 734fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk } 735fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk if (rv != OK) 736fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk context_ = NULL; 737fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk return rv; 738fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} 739fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk 740fc93418c483ce474a1f4888b50f92574a1b81be3Jason Monk} // namespace net 741