Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(470)

Unified Diff: net/proxy/proxy_resolver_v8_tracing.cc

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/proxy/proxy_resolver_v8_tracing.h ('k') | net/proxy/proxy_resolver_v8_tracing_unittest.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/proxy/proxy_resolver_v8_tracing.cc
diff --git a/net/proxy/proxy_resolver_v8_tracing.cc b/net/proxy/proxy_resolver_v8_tracing.cc
deleted file mode 100644
index c498f749bb6e8163a2dab165a7cf88c9dea0ddee..0000000000000000000000000000000000000000
--- a/net/proxy/proxy_resolver_v8_tracing.cc
+++ /dev/null
@@ -1,1016 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "net/proxy/proxy_resolver_v8_tracing.h"
-
-#include "base/bind.h"
-#include "base/message_loop/message_loop_proxy.h"
-#include "base/profiler/scoped_tracker.h"
-#include "base/strings/stringprintf.h"
-#include "base/synchronization/cancellation_flag.h"
-#include "base/synchronization/waitable_event.h"
-#include "base/threading/thread.h"
-#include "base/threading/thread_restrictions.h"
-#include "base/values.h"
-#include "net/base/address_list.h"
-#include "net/base/net_errors.h"
-#include "net/base/net_log.h"
-#include "net/dns/host_resolver.h"
-#include "net/proxy/proxy_info.h"
-#include "net/proxy/proxy_resolver_error_observer.h"
-#include "net/proxy/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 net {
-
-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 = 20;
-
-// 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 = 2048;
-
-// Returns event parameters for a PAC error message (line number + message).
-base::Value* NetLogErrorCallback(int line_number,
- const base::string16* message,
- NetLog::LogLevel /* log_level */) {
- base::DictionaryValue* dict = new base::DictionaryValue();
- dict->SetInteger("line_number", line_number);
- dict->SetString("message", *message);
- return dict;
-}
-
-} // namespace
-
-// The Job class is responsible for executing GetProxyForURL() and
-// SetPacScript(), 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 ProxyResolverV8Tracing that
-// spawned it. Destruction might happen on either the origin thread or the
-// worker thread.
-class ProxyResolverV8Tracing::Job
- : public base::RefCountedThreadSafe<ProxyResolverV8Tracing::Job>,
- public ProxyResolverV8::JSBindings {
- public:
- // |parent| is non-owned. It is the ProxyResolverV8Tracing that spawned this
- // Job, and must oulive it.
- explicit Job(ProxyResolverV8Tracing* parent);
-
- // Called from origin thread.
- void StartSetPacScript(
- const scoped_refptr<ProxyResolverScriptData>& script_data,
- const CompletionCallback& callback);
-
- // Called from origin thread.
- void StartGetProxyForURL(const GURL& url,
- ProxyInfo* results,
- const BoundNetLog& net_log,
- const CompletionCallback& callback);
-
- // Called from origin thread.
- void Cancel();
-
- // Called from origin thread.
- LoadState GetLoadState() const;
-
- private:
- typedef std::map<std::string, std::string> DnsCache;
- friend class base::RefCountedThreadSafe<ProxyResolverV8Tracing::Job>;
-
- enum Operation {
- SET_PAC_SCRIPT,
- GET_PROXY_FOR_URL,
- };
-
- struct AlertOrError {
- bool is_alert;
- int line_number;
- base::string16 message;
- };
-
- ~Job() override;
-
- void CheckIsOnWorkerThread() const;
- void CheckIsOnOriginThread() const;
-
- void SetCallback(const CompletionCallback& callback);
- void ReleaseCallback();
-
- ProxyResolverV8* v8_resolver();
- base::MessageLoop* worker_loop();
- HostResolver* host_resolver();
- ProxyResolverErrorObserver* error_observer();
- NetLog* net_log();
-
- // Invokes the user's callback.
- void NotifyCaller(int result);
- void NotifyCallerOnOriginLoop(int result);
-
- void Start(Operation op, bool blocking_dns,
- const CompletionCallback& callback);
-
- void ExecuteBlocking();
- void ExecuteNonBlocking();
- int ExecuteProxyResolver();
-
- // Implementation of ProxyResolverv8::JSBindings
- bool ResolveDns(const std::string& host,
- ResolveDnsOperation op,
- std::string* output,
- bool* terminate) override;
- void Alert(const base::string16& message) override;
- void OnError(int line_number, const base::string16& error) override;
-
- bool ResolveDnsBlocking(const std::string& host,
- ResolveDnsOperation op,
- std::string* output);
-
- bool ResolveDnsNonBlocking(const std::string& host,
- ResolveDnsOperation op,
- std::string* output,
- bool* terminate);
-
- bool PostDnsOperationAndWait(const std::string& host,
- ResolveDnsOperation op,
- bool* completed_synchronously)
- WARN_UNUSED_RESULT;
-
- void DoDnsOperation();
- void OnDnsOperationComplete(int result);
-
- void ScheduleRestartWithBlockingDns();
-
- bool GetDnsFromLocalCache(const std::string& host, ResolveDnsOperation op,
- std::string* output, bool* return_value);
-
- void SaveDnsToLocalCache(const std::string& host, ResolveDnsOperation op,
- int net_error, const net::AddressList& addresses);
-
- // Builds a RequestInfo to service the specified PAC DNS operation.
- static HostResolver::RequestInfo MakeDnsRequestInfo(const std::string& host,
- ResolveDnsOperation op);
-
- // Makes a key for looking up |host, op| in |dns_cache_|. Strings are used for
- // convenience, to avoid defining custom comparators.
- static std::string MakeDnsCacheKey(const std::string& host,
- ResolveDnsOperation op);
-
- void HandleAlertOrError(bool is_alert, int line_number,
- const base::string16& message);
- void DispatchBufferedAlertsAndErrors();
- void DispatchAlertOrError(bool is_alert, int line_number,
- const base::string16& message);
-
- void LogEventToCurrentRequestAndGlobally(
- NetLog::EventType type,
- const NetLog::ParametersCallback& parameters_callback);
-
- // The thread which called into ProxyResolverV8Tracing, and on which the
- // completion callback is expected to run.
- scoped_refptr<base::MessageLoopProxy> origin_loop_;
-
- // The ProxyResolverV8Tracing which spawned this Job.
- // Initialized on origin thread and then accessed from both threads.
- ProxyResolverV8Tracing* parent_;
-
- // The callback to run (on the origin thread) when the Job finishes.
- // Should only be accessed from origin thread.
- CompletionCallback callback_;
-
- // Flag to indicate whether the request has been cancelled.
- base::CancellationFlag cancelled_;
-
- // The operation that this Job is running.
- // Initialized on origin thread and then accessed from both threads.
- Operation operation_;
-
- // The DNS mode for this Job.
- // Initialized on origin thread, mutated on worker thread, and accessed
- // by both the origin thread and worker thread.
- bool blocking_dns_;
-
- // Used to block the worker thread on a DNS operation taking place on the
- // origin thread.
- base::WaitableEvent event_;
-
- // Map of DNS operations completed so far. Written into on the origin thread
- // and read on the worker thread.
- DnsCache dns_cache_;
-
- // The job holds a reference to itself to ensure that it remains alive until
- // either completion or cancellation.
- scoped_refptr<Job> owned_self_reference_;
-
- // -------------------------------------------------------
- // State specific to SET_PAC_SCRIPT.
- // -------------------------------------------------------
-
- scoped_refptr<ProxyResolverScriptData> script_data_;
-
- // -------------------------------------------------------
- // State specific to GET_PROXY_FOR_URL.
- // -------------------------------------------------------
-
- ProxyInfo* user_results_; // Owned by caller, lives on origin thread.
- GURL url_;
- ProxyInfo results_;
- BoundNetLog bound_net_log_;
-
- // ---------------------------------------------------------------------------
- // State for ExecuteNonBlocking()
- // ---------------------------------------------------------------------------
- // These variables are used exclusively on the worker thread and are only
- // meaningful when executing inside of ExecuteNonBlocking().
-
- // Whether this execution was abandoned due to a missing DNS dependency.
- bool abandoned_;
-
- // Number of calls made to ResolveDns() by this execution.
- int num_dns_;
-
- // Sequence of calls made to Alert() or OnError() by this execution.
- std::vector<AlertOrError> alerts_and_errors_;
- size_t alerts_and_errors_byte_cost_; // Approximate byte cost of the above.
-
- // Number of calls made to ResolveDns() by the PREVIOUS execution.
- int last_num_dns_;
-
- // Whether the current execution needs to be restarted in blocking mode.
- bool should_restart_with_blocking_dns_;
-
- // ---------------------------------------------------------------------------
- // State for pending DNS request.
- // ---------------------------------------------------------------------------
-
- // Handle to the outstanding request in the HostResolver, or NULL.
- // This is mutated and used on the origin thread, however it may be read by
- // the worker thread for some DCHECKS().
- HostResolver::RequestHandle pending_dns_;
-
- // Indicates if the outstanding DNS request completed synchronously. Written
- // on the origin thread, and read by the worker thread.
- bool pending_dns_completed_synchronously_;
-
- // These are the inputs to DoDnsOperation(). Written on the worker thread,
- // read by the origin thread.
- std::string pending_dns_host_;
- ResolveDnsOperation pending_dns_op_;
-
- // This contains the resolved address list that DoDnsOperation() fills in.
- // Used exclusively on the origin thread.
- AddressList pending_dns_addresses_;
-};
-
-ProxyResolverV8Tracing::Job::Job(ProxyResolverV8Tracing* parent)
- : origin_loop_(base::MessageLoopProxy::current()),
- parent_(parent),
- event_(true, false),
- last_num_dns_(0),
- pending_dns_(NULL) {
- CheckIsOnOriginThread();
-}
-
-void ProxyResolverV8Tracing::Job::StartSetPacScript(
- const scoped_refptr<ProxyResolverScriptData>& script_data,
- const CompletionCallback& callback) {
- CheckIsOnOriginThread();
-
- script_data_ = script_data;
-
- // Script initialization uses blocking DNS since there isn't any
- // advantage to using non-blocking mode here. That is because the
- // parent ProxyService can't submit any ProxyResolve requests until
- // initialization has completed successfully!
- Start(SET_PAC_SCRIPT, true /*blocking*/, callback);
-}
-
-void ProxyResolverV8Tracing::Job::StartGetProxyForURL(
- const GURL& url,
- ProxyInfo* results,
- const BoundNetLog& net_log,
- const CompletionCallback& callback) {
- CheckIsOnOriginThread();
-
- url_ = url;
- user_results_ = results;
- bound_net_log_ = net_log;
-
- Start(GET_PROXY_FOR_URL, false /*non-blocking*/, callback);
-}
-
-void ProxyResolverV8Tracing::Job::Cancel() {
- CheckIsOnOriginThread();
-
- // There are several possibilities to consider for cancellation:
- // (a) The job has been posted to the worker thread, however script execution
- // has not yet started.
- // (b) The script is executing on the worker thread.
- // (c) The script is executing on the worker thread, however is blocked inside
- // of dnsResolve() waiting for a response from the origin thread.
- // (d) Nothing is running on the worker thread, however the host resolver has
- // a pending DNS request which upon completion will restart the script
- // execution.
- // (e) The worker thread has a pending task to restart execution, which was
- // posted after the DNS dependency was resolved and saved to local cache.
- // (f) The script execution completed entirely, and posted a task to the
- // origin thread to notify the caller.
- //
- // |cancelled_| is read on both the origin thread and worker thread. The
- // code that runs on the worker thread is littered with checks on
- // |cancelled_| to break out early.
- cancelled_.Set();
-
- ReleaseCallback();
-
- if (pending_dns_) {
- host_resolver()->CancelRequest(pending_dns_);
- pending_dns_ = NULL;
- }
-
- // The worker thread might be blocked waiting for DNS.
- event_.Signal();
-
- owned_self_reference_ = NULL;
-}
-
-LoadState ProxyResolverV8Tracing::Job::GetLoadState() const {
- CheckIsOnOriginThread();
-
- if (pending_dns_)
- return LOAD_STATE_RESOLVING_HOST_IN_PROXY_SCRIPT;
-
- return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
-}
-
-ProxyResolverV8Tracing::Job::~Job() {
- DCHECK(!pending_dns_);
- DCHECK(callback_.is_null());
-}
-
-void ProxyResolverV8Tracing::Job::CheckIsOnWorkerThread() const {
- DCHECK_EQ(base::MessageLoop::current(), parent_->thread_->message_loop());
-}
-
-void ProxyResolverV8Tracing::Job::CheckIsOnOriginThread() const {
- DCHECK(origin_loop_->BelongsToCurrentThread());
-}
-
-void ProxyResolverV8Tracing::Job::SetCallback(
- const CompletionCallback& callback) {
- CheckIsOnOriginThread();
- DCHECK(callback_.is_null());
- parent_->num_outstanding_callbacks_++;
- callback_ = callback;
-}
-
-void ProxyResolverV8Tracing::Job::ReleaseCallback() {
- CheckIsOnOriginThread();
- DCHECK(!callback_.is_null());
- CHECK_GT(parent_->num_outstanding_callbacks_, 0);
- parent_->num_outstanding_callbacks_--;
- callback_.Reset();
-
- // For good measure, clear this other user-owned pointer.
- user_results_ = NULL;
-}
-
-ProxyResolverV8* ProxyResolverV8Tracing::Job::v8_resolver() {
- return parent_->v8_resolver_.get();
-}
-
-base::MessageLoop* ProxyResolverV8Tracing::Job::worker_loop() {
- return parent_->thread_->message_loop();
-}
-
-HostResolver* ProxyResolverV8Tracing::Job::host_resolver() {
- return parent_->host_resolver_;
-}
-
-ProxyResolverErrorObserver* ProxyResolverV8Tracing::Job::error_observer() {
- return parent_->error_observer_.get();
-}
-
-NetLog* ProxyResolverV8Tracing::Job::net_log() {
- return parent_->net_log_;
-}
-
-void ProxyResolverV8Tracing::Job::NotifyCaller(int result) {
- CheckIsOnWorkerThread();
-
- origin_loop_->PostTask(
- FROM_HERE,
- base::Bind(&Job::NotifyCallerOnOriginLoop, this, result));
-}
-
-void ProxyResolverV8Tracing::Job::NotifyCallerOnOriginLoop(int result) {
- CheckIsOnOriginThread();
-
- if (cancelled_.IsSet())
- return;
-
- DCHECK(!callback_.is_null());
- DCHECK(!pending_dns_);
-
- if (operation_ == GET_PROXY_FOR_URL) {
- *user_results_ = results_;
- }
-
- // There is only ever 1 outstanding SET_PAC_SCRIPT job. It needs to be
- // tracked to support cancellation.
- if (operation_ == SET_PAC_SCRIPT) {
- DCHECK_EQ(parent_->set_pac_script_job_.get(), this);
- parent_->set_pac_script_job_ = NULL;
- }
-
- CompletionCallback callback = callback_;
- ReleaseCallback();
- callback.Run(result);
-
- owned_self_reference_ = NULL;
-}
-
-void ProxyResolverV8Tracing::Job::Start(Operation op, bool blocking_dns,
- const CompletionCallback& callback) {
- CheckIsOnOriginThread();
-
- operation_ = op;
- blocking_dns_ = blocking_dns;
- SetCallback(callback);
-
- owned_self_reference_ = this;
-
- worker_loop()->PostTask(FROM_HERE,
- blocking_dns_ ? base::Bind(&Job::ExecuteBlocking, this) :
- base::Bind(&Job::ExecuteNonBlocking, this));
-}
-
-void ProxyResolverV8Tracing::Job::ExecuteBlocking() {
- CheckIsOnWorkerThread();
- DCHECK(blocking_dns_);
-
- if (cancelled_.IsSet())
- return;
-
- NotifyCaller(ExecuteProxyResolver());
-}
-
-void ProxyResolverV8Tracing::Job::ExecuteNonBlocking() {
- CheckIsOnWorkerThread();
- DCHECK(!blocking_dns_);
-
- if (cancelled_.IsSet())
- return;
-
- // Reset state for the current execution.
- abandoned_ = false;
- num_dns_ = 0;
- alerts_and_errors_.clear();
- alerts_and_errors_byte_cost_ = 0;
- should_restart_with_blocking_dns_ = false;
-
- int result = ExecuteProxyResolver();
-
- if (should_restart_with_blocking_dns_) {
- DCHECK(!blocking_dns_);
- DCHECK(abandoned_);
- blocking_dns_ = true;
- ExecuteBlocking();
- return;
- }
-
- if (abandoned_)
- return;
-
- DispatchBufferedAlertsAndErrors();
- NotifyCaller(result);
-}
-
-int ProxyResolverV8Tracing::Job::ExecuteProxyResolver() {
- JSBindings* prev_bindings = v8_resolver()->js_bindings();
- v8_resolver()->set_js_bindings(this);
-
- int result = ERR_UNEXPECTED; // Initialized to silence warnings.
-
- switch (operation_) {
- case SET_PAC_SCRIPT:
- result = v8_resolver()->SetPacScript(
- script_data_, CompletionCallback());
- break;
- case GET_PROXY_FOR_URL:
- result = v8_resolver()->GetProxyForURL(
- url_,
- // Important: Do not write directly into |user_results_|, since if the
- // request were to be cancelled from the origin thread, must guarantee
- // that |user_results_| is not accessed anymore.
- &results_,
- CompletionCallback(),
- NULL,
- bound_net_log_);
- break;
- }
-
- v8_resolver()->set_js_bindings(prev_bindings);
-
- return result;
-}
-
-bool ProxyResolverV8Tracing::Job::ResolveDns(const std::string& host,
- ResolveDnsOperation op,
- std::string* output,
- bool* terminate) {
- if (cancelled_.IsSet()) {
- *terminate = true;
- return false;
- }
-
- if ((op == DNS_RESOLVE || op == DNS_RESOLVE_EX) && host.empty()) {
- // a DNS resolve with an empty hostname is considered an error.
- return false;
- }
-
- return blocking_dns_ ?
- ResolveDnsBlocking(host, op, output) :
- ResolveDnsNonBlocking(host, op, output, terminate);
-}
-
-void ProxyResolverV8Tracing::Job::Alert(const base::string16& message) {
- HandleAlertOrError(true, -1, message);
-}
-
-void ProxyResolverV8Tracing::Job::OnError(int line_number,
- const base::string16& error) {
- HandleAlertOrError(false, line_number, error);
-}
-
-bool ProxyResolverV8Tracing::Job::ResolveDnsBlocking(const std::string& host,
- ResolveDnsOperation op,
- std::string* output) {
- CheckIsOnWorkerThread();
-
- // Check if the DNS result for this host has already been cached.
- bool rv;
- if (GetDnsFromLocalCache(host, op, output, &rv)) {
- // Yay, cache hit!
- return rv;
- }
-
- if (dns_cache_.size() >= kMaxUniqueResolveDnsPerExec) {
- // Safety net for scripts with unexpectedly many DNS calls.
- // We will continue running to completion, but will fail every
- // subsequent DNS request.
- return false;
- }
-
- if (!PostDnsOperationAndWait(host, op, NULL))
- return false; // Was cancelled.
-
- CHECK(GetDnsFromLocalCache(host, op, output, &rv));
- return rv;
-}
-
-bool ProxyResolverV8Tracing::Job::ResolveDnsNonBlocking(const std::string& host,
- ResolveDnsOperation op,
- std::string* output,
- bool* terminate) {
- CheckIsOnWorkerThread();
-
- if (abandoned_) {
- // If this execution was already abandoned can fail right away. Only 1 DNS
- // dependency will be traced at a time (for more predictable outcomes).
- return false;
- }
-
- num_dns_ += 1;
-
- // Check if the DNS result for this host has already been cached.
- bool rv;
- if (GetDnsFromLocalCache(host, op, output, &rv)) {
- // Yay, cache hit!
- return rv;
- }
-
- if (num_dns_ <= last_num_dns_) {
- // The sequence of DNS operations is different from last time!
- ScheduleRestartWithBlockingDns();
- *terminate = true;
- return false;
- }
-
- if (dns_cache_.size() >= kMaxUniqueResolveDnsPerExec) {
- // Safety net for scripts with unexpectedly many DNS calls.
- return false;
- }
-
- DCHECK(!should_restart_with_blocking_dns_);
-
- bool completed_synchronously;
- if (!PostDnsOperationAndWait(host, op, &completed_synchronously))
- return false; // Was cancelled.
-
- if (completed_synchronously) {
- CHECK(GetDnsFromLocalCache(host, op, output, &rv));
- return rv;
- }
-
- // Otherwise if the result was not in the cache, then a DNS request has
- // been started. Abandon this invocation of FindProxyForURL(), it will be
- // restarted once the DNS request completes.
- abandoned_ = true;
- *terminate = true;
- last_num_dns_ = num_dns_;
- return false;
-}
-
-bool ProxyResolverV8Tracing::Job::PostDnsOperationAndWait(
- const std::string& host, ResolveDnsOperation op,
- bool* completed_synchronously) {
-
- // Post the DNS request to the origin thread.
- DCHECK(!pending_dns_);
- pending_dns_host_ = host;
- pending_dns_op_ = op;
- origin_loop_->PostTask(FROM_HERE, base::Bind(&Job::DoDnsOperation, this));
-
- event_.Wait();
- event_.Reset();
-
- if (cancelled_.IsSet())
- return false;
-
- if (completed_synchronously)
- *completed_synchronously = pending_dns_completed_synchronously_;
-
- return true;
-}
-
-void ProxyResolverV8Tracing::Job::DoDnsOperation() {
- CheckIsOnOriginThread();
- DCHECK(!pending_dns_);
-
- if (cancelled_.IsSet())
- return;
-
- HostResolver::RequestHandle dns_request = NULL;
- int result = host_resolver()->Resolve(
- MakeDnsRequestInfo(pending_dns_host_, pending_dns_op_),
- DEFAULT_PRIORITY,
- &pending_dns_addresses_,
- base::Bind(&Job::OnDnsOperationComplete, this),
- &dns_request,
- bound_net_log_);
-
- pending_dns_completed_synchronously_ = result != ERR_IO_PENDING;
-
- // Check if the request was cancelled as a side-effect of calling into the
- // HostResolver. This isn't the ordinary execution flow, however it is
- // exercised by unit-tests.
- if (cancelled_.IsSet()) {
- if (!pending_dns_completed_synchronously_)
- host_resolver()->CancelRequest(dns_request);
- return;
- }
-
- if (pending_dns_completed_synchronously_) {
- OnDnsOperationComplete(result);
- } else {
- DCHECK(dns_request);
- pending_dns_ = dns_request;
- // OnDnsOperationComplete() will be called by host resolver on completion.
- }
-
- if (!blocking_dns_) {
- // The worker thread always blocks waiting to see if the result can be
- // serviced from cache before restarting.
- event_.Signal();
- }
-}
-
-void ProxyResolverV8Tracing::Job::OnDnsOperationComplete(int result) {
- // TODO(vadimt): Remove ScopedTracker below once crbug.com/436634 is fixed.
- tracked_objects::ScopedTracker tracking_profile(
- FROM_HERE_WITH_EXPLICIT_FUNCTION(
- "436634 ProxyResolverV8Tracing::Job::OnDnsOperationComplete"));
-
- CheckIsOnOriginThread();
-
- DCHECK(!cancelled_.IsSet());
- DCHECK(pending_dns_completed_synchronously_ == (pending_dns_ == NULL));
-
- SaveDnsToLocalCache(pending_dns_host_, pending_dns_op_, result,
- pending_dns_addresses_);
- pending_dns_ = NULL;
-
- if (blocking_dns_) {
- event_.Signal();
- return;
- }
-
- if (!blocking_dns_ && !pending_dns_completed_synchronously_) {
- // Restart. This time it should make more progress due to having
- // cached items.
- worker_loop()->PostTask(FROM_HERE,
- base::Bind(&Job::ExecuteNonBlocking, this));
- }
-}
-
-void ProxyResolverV8Tracing::Job::ScheduleRestartWithBlockingDns() {
- CheckIsOnWorkerThread();
-
- DCHECK(!should_restart_with_blocking_dns_);
- DCHECK(!abandoned_);
- DCHECK(!blocking_dns_);
-
- abandoned_ = true;
-
- // The restart will happen after ExecuteNonBlocking() finishes.
- should_restart_with_blocking_dns_ = true;
-}
-
-bool ProxyResolverV8Tracing::Job::GetDnsFromLocalCache(
- const std::string& host,
- ResolveDnsOperation op,
- std::string* output,
- bool* return_value) {
- CheckIsOnWorkerThread();
-
- DnsCache::const_iterator it = dns_cache_.find(MakeDnsCacheKey(host, op));
- if (it == dns_cache_.end())
- return false;
-
- *output = it->second;
- *return_value = !it->second.empty();
- return true;
-}
-
-void ProxyResolverV8Tracing::Job::SaveDnsToLocalCache(
- const std::string& host,
- ResolveDnsOperation op,
- int net_error,
- const net::AddressList& addresses) {
- CheckIsOnOriginThread();
-
- // Serialize the result into a string to save to the cache.
- std::string cache_value;
- if (net_error != OK) {
- cache_value = std::string();
- } else if (op == DNS_RESOLVE || op == MY_IP_ADDRESS) {
- // dnsResolve() and myIpAddress() are expected to return a single IP
- // address.
- cache_value = addresses.front().ToStringWithoutPort();
- } else {
- // The *Ex versions are expected to return a semi-colon separated list.
- for (AddressList::const_iterator iter = addresses.begin();
- iter != addresses.end(); ++iter) {
- if (!cache_value.empty())
- cache_value += ";";
- cache_value += iter->ToStringWithoutPort();
- }
- }
-
- dns_cache_[MakeDnsCacheKey(host, op)] = cache_value;
-}
-
-// static
-HostResolver::RequestInfo ProxyResolverV8Tracing::Job::MakeDnsRequestInfo(
- const std::string& host, ResolveDnsOperation op) {
- HostPortPair host_port = HostPortPair(host, 80);
- if (op == MY_IP_ADDRESS || op == MY_IP_ADDRESS_EX) {
- host_port.set_host(GetHostName());
- }
-
- HostResolver::RequestInfo info(host_port);
- // Flag myIpAddress requests.
- if (op == MY_IP_ADDRESS || op == MY_IP_ADDRESS_EX) {
- // TODO: Provide a RequestInfo construction mechanism that does not
- // require a hostname and sets is_my_ip_address to true instead of this.
- info.set_is_my_ip_address(true);
- }
- // The non-ex flavors are limited to IPv4 results.
- if (op == MY_IP_ADDRESS || op == DNS_RESOLVE) {
- info.set_address_family(ADDRESS_FAMILY_IPV4);
- }
-
- return info;
-}
-
-std::string ProxyResolverV8Tracing::Job::MakeDnsCacheKey(
- const std::string& host, ResolveDnsOperation op) {
- return base::StringPrintf("%d:%s", op, host.c_str());
-}
-
-void ProxyResolverV8Tracing::Job::HandleAlertOrError(
- bool is_alert,
- int line_number,
- const base::string16& message) {
- CheckIsOnWorkerThread();
-
- if (cancelled_.IsSet())
- return;
-
- if (blocking_dns_) {
- // In blocking DNS mode the events can be dispatched immediately.
- DispatchAlertOrError(is_alert, line_number, message);
- return;
- }
-
- // Otherwise in nonblocking mode, buffer all the messages until
- // the end.
-
- if (abandoned_)
- return;
-
- alerts_and_errors_byte_cost_ += sizeof(AlertOrError) + message.size() * 2;
-
- // If there have been lots of messages, enqueing could be expensive on
- // memory. Consider a script which does megabytes worth of alerts().
- // Avoid this by falling back to blocking mode.
- if (alerts_and_errors_byte_cost_ > kMaxAlertsAndErrorsBytes) {
- ScheduleRestartWithBlockingDns();
- return;
- }
-
- AlertOrError entry = {is_alert, line_number, message};
- alerts_and_errors_.push_back(entry);
-}
-
-void ProxyResolverV8Tracing::Job::DispatchBufferedAlertsAndErrors() {
- CheckIsOnWorkerThread();
- DCHECK(!blocking_dns_);
- DCHECK(!abandoned_);
-
- for (size_t i = 0; i < alerts_and_errors_.size(); ++i) {
- const AlertOrError& x = alerts_and_errors_[i];
- DispatchAlertOrError(x.is_alert, x.line_number, x.message);
- }
-}
-
-void ProxyResolverV8Tracing::Job::DispatchAlertOrError(
- bool is_alert, int line_number, const base::string16& message) {
- CheckIsOnWorkerThread();
-
- // Note that the handling of cancellation is racy with regard to
- // alerts/errors. The request might get cancelled shortly after this
- // check! (There is no lock being held to guarantee otherwise).
- //
- // If this happens, then some information will get written to the NetLog
- // needlessly, however the NetLog will still be alive so it shouldn't cause
- // problems.
- if (cancelled_.IsSet())
- return;
-
- if (is_alert) {
- // -------------------
- // alert
- // -------------------
- VLOG(1) << "PAC-alert: " << message;
-
- // Send to the NetLog.
- LogEventToCurrentRequestAndGlobally(
- NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
- NetLog::StringCallback("message", &message));
- } else {
- // -------------------
- // error
- // -------------------
- if (line_number == -1)
- VLOG(1) << "PAC-error: " << message;
- else
- VLOG(1) << "PAC-error: " << "line: " << line_number << ": " << message;
-
- // Send the error to the NetLog.
- LogEventToCurrentRequestAndGlobally(
- NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
- base::Bind(&NetLogErrorCallback, line_number, &message));
-
- if (error_observer())
- error_observer()->OnPACScriptError(line_number, message);
- }
-}
-
-void ProxyResolverV8Tracing::Job::LogEventToCurrentRequestAndGlobally(
- NetLog::EventType type,
- const NetLog::ParametersCallback& parameters_callback) {
- CheckIsOnWorkerThread();
- bound_net_log_.AddEvent(type, parameters_callback);
-
- // Emit to the global NetLog event stream.
- if (net_log())
- net_log()->AddGlobalEntry(type, parameters_callback);
-}
-
-ProxyResolverV8Tracing::ProxyResolverV8Tracing(
- HostResolver* host_resolver,
- ProxyResolverErrorObserver* error_observer,
- NetLog* net_log)
- : ProxyResolver(true /*expects_pac_bytes*/),
- host_resolver_(host_resolver),
- error_observer_(error_observer),
- net_log_(net_log),
- num_outstanding_callbacks_(0) {
- DCHECK(host_resolver);
- // Start up the thread.
- thread_.reset(new base::Thread("Proxy resolver"));
- base::Thread::Options options;
- options.timer_slack = base::TIMER_SLACK_MAXIMUM;
- CHECK(thread_->StartWithOptions(options));
-
- v8_resolver_.reset(new ProxyResolverV8);
-}
-
-ProxyResolverV8Tracing::~ProxyResolverV8Tracing() {
- // Note, all requests should have been cancelled.
- CHECK(!set_pac_script_job_.get());
- CHECK_EQ(0, num_outstanding_callbacks_);
-
- // Join the worker thread. See http://crbug.com/69710. Note that we call
- // Stop() here instead of simply clearing thread_ since there may be pending
- // callbacks on the worker thread which want to dereference thread_.
- base::ThreadRestrictions::ScopedAllowIO allow_io;
- thread_->Stop();
-}
-
-int ProxyResolverV8Tracing::GetProxyForURL(const GURL& url,
- ProxyInfo* results,
- const CompletionCallback& callback,
- RequestHandle* request,
- const BoundNetLog& net_log) {
- DCHECK(CalledOnValidThread());
- DCHECK(!callback.is_null());
- DCHECK(!set_pac_script_job_.get());
-
- scoped_refptr<Job> job = new Job(this);
-
- if (request)
- *request = job.get();
-
- job->StartGetProxyForURL(url, results, net_log, callback);
- return ERR_IO_PENDING;
-}
-
-void ProxyResolverV8Tracing::CancelRequest(RequestHandle request) {
- Job* job = reinterpret_cast<Job*>(request);
- job->Cancel();
-}
-
-LoadState ProxyResolverV8Tracing::GetLoadState(RequestHandle request) const {
- Job* job = reinterpret_cast<Job*>(request);
- return job->GetLoadState();
-}
-
-void ProxyResolverV8Tracing::CancelSetPacScript() {
- DCHECK(set_pac_script_job_.get());
- set_pac_script_job_->Cancel();
- set_pac_script_job_ = NULL;
-}
-
-int ProxyResolverV8Tracing::SetPacScript(
- const scoped_refptr<ProxyResolverScriptData>& script_data,
- const CompletionCallback& callback) {
- DCHECK(CalledOnValidThread());
- DCHECK(!callback.is_null());
-
- // Note that there should not be any outstanding (non-cancelled) Jobs when
- // setting the PAC script (ProxyService should guarantee this). If there are,
- // then they might complete in strange ways after the new script is set.
- DCHECK(!set_pac_script_job_.get());
- CHECK_EQ(0, num_outstanding_callbacks_);
-
- set_pac_script_job_ = new Job(this);
- set_pac_script_job_->StartSetPacScript(script_data, callback);
-
- return ERR_IO_PENDING;
-}
-
-} // namespace net
« no previous file with comments | « net/proxy/proxy_resolver_v8_tracing.h ('k') | net/proxy/proxy_resolver_v8_tracing_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698