chromium/services/proxy_resolver/proxy_resolver_v8.cc

// Copyright 2012 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "services/proxy_resolver/proxy_resolver_v8.h"

#include <algorithm>
#include <cstdio>
#include <memory>
#include <utility>

#include "base/auto_reset.h"
#include "base/check_op.h"
#include "base/compiler_specific.h"
#include "base/debug/leak_annotations.h"
#include "base/lazy_instance.h"
#include "base/memory/raw_ptr.h"
#include "base/notreached.h"
#include "base/numerics/safe_conversions.h"
#include "base/strings/string_tokenizer.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
#include "base/task/single_thread_task_runner.h"
#include "gin/array_buffer.h"
#include "gin/converter.h"
#include "gin/public/isolate_holder.h"
#include "gin/v8_initializer.h"
#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/proxy_resolution/pac_file_data.h"
#include "net/proxy_resolution/proxy_info.h"
#include "services/proxy_resolver/pac_js_library.h"
#include "tools/v8_context_snapshot/buildflags.h"
#include "url/gurl.h"
#include "url/url_canon.h"
#include "v8/include/v8.h"

// Notes on the javascript environment:
//
// For the majority of the PAC utility functions, we use the same code
// as Firefox. See the javascript library that pac_js_library.h pulls in.
//
// In addition, we implement a subset of Microsoft's extensions to PAC.
// - myIpAddressEx()
// - dnsResolveEx()
// - isResolvableEx()
// - isInNetEx()
// - sortIpAddressList()
//
// It is worth noting that the original PAC specification does not describe
// the return values on failure. Consequently, there are compatibility
// differences between browsers on what to return on failure, which are
// illustrated below:
//
// --------------------+-------------+-------------------+--------------
//                     | Firefox3    | InternetExplorer8 |  --> Us <---
// --------------------+-------------+-------------------+--------------
// myIpAddress()       | "127.0.0.1" |  ???              |  "127.0.0.1"
// dnsResolve()        | null        |  false            |  null
// myIpAddressEx()     | N/A         |  ""               |  ""
// sortIpAddressList() | N/A         |  false            |  false
// dnsResolveEx()      | N/A         |  ""               |  ""
// isInNetEx()         | N/A         |  false            |  false
// --------------------+-------------+-------------------+--------------
//
// TODO(eroman): The cell above reading ??? means I didn't test it.
//
// Another difference is in how dnsResolve() and myIpAddress() are
// implemented -- whether they should restrict to IPv4 results, or
// include both IPv4 and IPv6. The following table illustrates the
// differences:
//
// --------------------+-------------+-------------------+--------------
//                     | Firefox3    | InternetExplorer8 |  --> Us <---
// --------------------+-------------+-------------------+--------------
// myIpAddress()       | IPv4/IPv6   |  IPv4             |  IPv4/IPv6
// dnsResolve()        | IPv4/IPv6   |  IPv4             |  IPv4
// isResolvable()      | IPv4/IPv6   |  IPv4             |  IPv4
// myIpAddressEx()     | N/A         |  IPv4/IPv6        |  IPv4/IPv6
// dnsResolveEx()      | N/A         |  IPv4/IPv6        |  IPv4/IPv6
// sortIpAddressList() | N/A         |  IPv4/IPv6        |  IPv4/IPv6
// isResolvableEx()    | N/A         |  IPv4/IPv6        |  IPv4/IPv6
// isInNetEx()         | N/A         |  IPv4/IPv6        |  IPv4/IPv6
// -----------------+-------------+-------------------+--------------

namespace proxy_resolver {

namespace {

// Pseudo-name for the PAC script.
const char kPacResourceName[] =;
// Pseudo-name for the PAC utility script.
const char kPacUtilityResourceName[] =;

// External string wrapper so V8 can access the UTF16 string wrapped by
// net::PacFileData.
class V8ExternalStringFromScriptData
    : public v8::String::ExternalStringResource {};

// External string wrapper so V8 can access a string literal.
class V8ExternalASCIILiteral
    : public v8::String::ExternalOneByteStringResource {};

// When creating a v8::String from a C++ string we have two choices: create
// a copy, or create a wrapper that shares the same underlying storage.
// For small strings it is better to just make a copy, whereas for large
// strings there are savings by sharing the storage. This number identifies
// the cutoff length for when to start wrapping rather than creating copies.
const size_t kMaxStringBytesForCopy =;

// Converts a V8 String to a UTF8 std::string. Returns false if `Value` is empty
// or not a string.
bool V8StringToUtf8(v8::Isolate* isolate,
                    v8::Local<v8::Value> v8_value,
                    std::string& out) {}

// Converts a V8 String to a UTF16 std::u16string. Returns false if `v8_value`
// is empty or not a string.
bool V8StringToUtf16(v8::Isolate* isolate,
                     v8::Local<v8::Value> v8_value,
                     std::u16string& out) {}

// Converts an ASCII std::string to a V8 string.
v8::Local<v8::String> ASCIIStringToV8String(v8::Isolate* isolate,
                                            const std::string& s) {}

// Converts a UTF16 std::u16string (wrapped by a net::PacFileData) to a
// V8 string.
v8::Local<v8::String> ScriptDataToV8String(
    v8::Isolate* isolate,
    const scoped_refptr<net::PacFileData>& s) {}

// Converts an ASCII string literal to a V8 string.
v8::Local<v8::String> ASCIILiteralToV8String(v8::Isolate* isolate,
                                             const char* ascii) {}

// Stringizes a V8 object by calling its toString() method. Returns true
// on success. This may fail if the toString() throws an exception.
bool V8ObjectToUTF16String(v8::Local<v8::Value> object,
                           std::u16string* utf16_result,
                           v8::Isolate* isolate) {}

// Extracts an hostname argument from |args|. On success returns true
// and fills |*hostname| with the result.
bool GetHostnameArgument(const v8::FunctionCallbackInfo<v8::Value>& args,
                         std::string* hostname) {}

// Wrapper around an IP address that stores the original string as well as a
// corresponding parsed net::IPAddress.

// This struct is used as a helper for sorting IP address strings - the IP
// literal is parsed just once and used as the sorting key, while also
// preserving the original IP literal string.
struct IPAddressSortingEntry {};

// Handler for "sortIpAddressList(IpAddressList)". |ip_address_list| is a
// semi-colon delimited string containing IP addresses.
// |sorted_ip_address_list| is the resulting list of sorted semi-colon delimited
// IP addresses or an empty string if unable to sort the IP address list.
// Returns 'true' if the sorting was successful, and 'false' if the input was an
// empty string, a string of separators (";" in this case), or if any of the IP
// addresses in the input list failed to parse.
bool SortIpAddressList(const std::string& ip_address_list,
                       std::string* sorted_ip_address_list) {}

// Handler for "isInNetEx(ip_address, ip_prefix)". |ip_address| is a string
// containing an IPv4/IPv6 address, and |ip_prefix| is a string containg a
// slash-delimited IP prefix with the top 'n' bits specified in the bit
// field. This returns 'true' if the address is in the same subnet, and
// 'false' otherwise. Also returns 'false' if the prefix is in an incorrect
// format. If the address types of |ip_address| and |ip_prefix| don't match,
// will promote the IPv4 literal to an IPv4 mapped IPv6 literal and
// proceed with the comparison.
bool IsInNetEx(const std::string& ip_address, const std::string& ip_prefix) {}

// Consider only single component domains like 'foo' as plain host names.
bool IsPlainHostName(const std::string& hostname_utf8) {}

// All instances of ProxyResolverV8 share the same v8::Isolate. This isolate is
// created lazily the first time it is needed and lives until process shutdown.
// This creation might happen from any thread, as ProxyResolverV8 is typically
// run in a threadpool.
//
// TODO(eroman): The lazily created isolate is never freed. Instead it should be
// disposed once there are no longer any ProxyResolverV8 referencing it.
class SharedIsolateFactory {};

base::LazyInstance<SharedIsolateFactory>::Leaky g_isolate_factory =;

}  // namespace

// ProxyResolverV8::Context ---------------------------------------------------

class ProxyResolverV8::Context {};

// ProxyResolverV8 ------------------------------------------------------------

ProxyResolverV8::ProxyResolverV8(std::unique_ptr<Context> context)
    :{}

ProxyResolverV8::~ProxyResolverV8() = default;

int ProxyResolverV8::GetProxyForURL(const GURL& query_url,
                                    net::ProxyInfo* results,
                                    ProxyResolverV8::JSBindings* bindings) {}

// static
int ProxyResolverV8::Create(const scoped_refptr<net::PacFileData>& script_data,
                            ProxyResolverV8::JSBindings* js_bindings,
                            std::unique_ptr<ProxyResolverV8>* resolver) {}

// static
size_t ProxyResolverV8::GetTotalHeapSize() {}

// static
size_t ProxyResolverV8::GetUsedHeapSize() {}

}  // namespace proxy_resolver