chromium/services/proxy_resolver/proxy_resolver_v8_tracing.cc

// Copyright 2013 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_tracing.h"

#include <map>
#include <memory>
#include <set>
#include <string>
#include <utility>
#include <vector>

#include "base/functional/bind.h"
#include "base/memory/raw_ptr.h"
#include "base/strings/stringprintf.h"
#include "base/synchronization/atomic_flag.h"
#include "base/synchronization/waitable_event.h"
#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread.h"
#include "base/threading/thread_checker.h"
#include "base/threading/thread_restrictions.h"
#include "base/trace_event/trace_event.h"
#include "net/base/ip_address.h"
#include "net/base/net_errors.h"
#include "net/base/network_anonymization_key.h"
#include "net/base/network_interfaces.h"
#include "net/base/trace_constants.h"
#include "net/log/net_log_with_source.h"
#include "net/proxy_resolution/proxy_info.h"
#include "net/proxy_resolution/proxy_resolve_dns_operation.h"
#include "net/proxy_resolution/proxy_resolver_error_observer.h"
#include "services/proxy_resolver/proxy_host_resolver.h"
#include "services/proxy_resolver/proxy_resolver_v8.h"

// The intent of this class is explained in the design document:
// https://docs.google.com/a/chromium.org/document/d/16Ij5OcVnR3s0MH4Z5XkhI9VTPoMJdaBn9rKreAmGOdE/edit
//
// In a nutshell, PAC scripts are Javascript programs and may depend on
// network I/O, by calling functions like dnsResolve().
//
// This is problematic since functions such as dnsResolve() will block the
// Javascript execution until the DNS result is availble, thereby stalling the
// PAC thread, which hurts the ability to process parallel proxy resolves.
// An obvious solution is to simply start more PAC threads, however this scales
// poorly, which hurts the ability to process parallel proxy resolves.
//
// The solution in ProxyResolverV8Tracing is to model PAC scripts as being
// deterministic, and depending only on the inputted URL. When the script
// issues a dnsResolve() for a yet unresolved hostname, the Javascript
// execution is "aborted", and then re-started once the DNS result is
// known.
namespace proxy_resolver {

class ScopedAllowThreadJoinForProxyResolverV8Tracing
    : public base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope {};

namespace {

// Upper bound on how many *unique* DNS resolves a PAC script is allowed
// to make. This is a failsafe both for scripts that do a ridiculous
// number of DNS resolves, as well as scripts which are misbehaving
// under the tracing optimization. It is not expected to hit this normally.
const size_t kMaxUniqueResolveDnsPerExec =;

// Approximate number of bytes to use for buffering alerts() and errors.
// This is a failsafe in case repeated executions of the script causes
// too much memory bloat. It is not expected for well behaved scripts to
// hit this. (In fact normal scripts should not even have alerts() or errors).
const size_t kMaxAlertsAndErrorsBytes =;

// The Job class is responsible for executing GetProxyForURL() and
// creating ProxyResolverV8 instances, since both of these operations share
// similar code.
//
// The DNS for these operations can operate in either blocking or
// non-blocking mode. Blocking mode is used as a fallback when the PAC script
// seems to be misbehaving under the tracing optimization.
//
// Note that this class runs on both the origin thread and a worker
// thread. Most methods are expected to be used exclusively on one thread
// or the other.
//
// The lifetime of Jobs does not exceed that of the ProxyResolverV8TracingImpl
// that spawned it. Destruction might happen on either the origin thread or the
// worker thread.
class Job : public base::RefCountedThreadSafe<Job>,
            public ProxyResolverV8::JSBindings {};

class ProxyResolverV8TracingImpl : public ProxyResolverV8Tracing {};

Job::Job(const Job::Params* params,
         std::unique_ptr<ProxyResolverV8Tracing::Bindings> bindings)
    :{}

void Job::StartCreateV8Resolver(
    const scoped_refptr<net::PacFileData>& script_data,
    std::unique_ptr<ProxyResolverV8>* resolver,
    net::CompletionOnceCallback callback) {}

void Job::StartGetProxyForURL(
    const GURL& url,
    const net::NetworkAnonymizationKey& network_anonymization_key,
    net::ProxyInfo* results,
    net::CompletionOnceCallback callback) {}

void Job::Cancel() {}

net::LoadState Job::GetLoadState() const {}

Job::~Job() {}

void Job::CheckIsOnWorkerThread() const {}

void Job::CheckIsOnOriginThread() const {}

void Job::SetCallback(net::CompletionOnceCallback callback) {}

void Job::ReleaseCallback() {}

ProxyResolverV8* Job::v8_resolver() {}

const scoped_refptr<base::SingleThreadTaskRunner>& Job::worker_task_runner() {}

ProxyHostResolver* Job::host_resolver() {}

void Job::NotifyCaller(int result) {}

void Job::NotifyCallerOnOriginLoop(int result) {}

void Job::Start(Operation op,
                bool blocking_dns,
                net::CompletionOnceCallback callback) {}

void Job::ExecuteBlocking() {}

void Job::ExecuteNonBlocking() {}

int Job::ExecuteProxyResolver() {}

bool Job::ResolveDns(const std::string& host,
                     net::ProxyResolveDnsOperation op,
                     std::string* output,
                     bool* terminate) {}

void Job::Alert(const std::u16string& message) {}

void Job::OnError(int line_number, const std::u16string& error) {}

bool Job::ResolveDnsBlocking(const std::string& host,
                             net::ProxyResolveDnsOperation op,
                             std::string* output) {}

bool Job::ResolveDnsNonBlocking(const std::string& host,
                                net::ProxyResolveDnsOperation op,
                                std::string* output,
                                bool* terminate) {}

bool Job::PostDnsOperationAndWait(const std::string& host,
                                  net::ProxyResolveDnsOperation op,
                                  bool* completed_synchronously) {}

void Job::DoDnsOperation() {}

void Job::OnDnsOperationComplete(int result) {}

void Job::ScheduleRestartWithBlockingDns() {}

bool Job::GetDnsFromLocalCache(const std::string& host,
                               net::ProxyResolveDnsOperation op,
                               std::string* output,
                               bool* return_value) {}

void Job::SaveDnsToLocalCache(const std::string& host,
                              net::ProxyResolveDnsOperation op,
                              int net_error,
                              const std::vector<net::IPAddress>& addresses) {}

std::string Job::MakeDnsCacheKey(const std::string& host,
                                 net::ProxyResolveDnsOperation op) {}

void Job::HandleAlertOrError(bool is_alert,
                             int line_number,
                             const std::u16string& message) {}

void Job::DispatchBufferedAlertsAndErrors() {}

void Job::DispatchAlertOrErrorOnOriginThread(bool is_alert,
                                             int line_number,
                                             const std::u16string& message) {}

ProxyResolverV8TracingImpl::ProxyResolverV8TracingImpl(
    std::unique_ptr<base::Thread> thread,
    std::unique_ptr<ProxyResolverV8> resolver,
    std::unique_ptr<Job::Params> job_params)
    :{}

ProxyResolverV8TracingImpl::~ProxyResolverV8TracingImpl() {}

ProxyResolverV8TracingImpl::RequestImpl::RequestImpl(scoped_refptr<Job> job)
    :{}

ProxyResolverV8TracingImpl::RequestImpl::~RequestImpl() {}

net::LoadState ProxyResolverV8TracingImpl::RequestImpl::GetLoadState() {}

void ProxyResolverV8TracingImpl::GetProxyForURL(
    const GURL& url,
    const net::NetworkAnonymizationKey& network_anonymization_key,
    net::ProxyInfo* results,
    net::CompletionOnceCallback callback,
    std::unique_ptr<net::ProxyResolver::Request>* request,
    std::unique_ptr<Bindings> bindings) {}

class ProxyResolverV8TracingFactoryImpl : public ProxyResolverV8TracingFactory {};

class ProxyResolverV8TracingFactoryImpl::CreateJob
    : public net::ProxyResolverFactory::Request {};

ProxyResolverV8TracingFactoryImpl::ProxyResolverV8TracingFactoryImpl() =
    default;

ProxyResolverV8TracingFactoryImpl::~ProxyResolverV8TracingFactoryImpl() {}

void ProxyResolverV8TracingFactoryImpl::CreateProxyResolverV8Tracing(
    const scoped_refptr<net::PacFileData>& pac_script,
    std::unique_ptr<ProxyResolverV8Tracing::Bindings> bindings,
    std::unique_ptr<ProxyResolverV8Tracing>* resolver,
    net::CompletionOnceCallback callback,
    std::unique_ptr<net::ProxyResolverFactory::Request>* request) {}

void ProxyResolverV8TracingFactoryImpl::RemoveJob(
    ProxyResolverV8TracingFactoryImpl::CreateJob* job) {}

}  // namespace

// static
std::unique_ptr<ProxyResolverV8TracingFactory>
ProxyResolverV8TracingFactory::Create() {}

}  // namespace proxy_resolver