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