12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2013 The Chromium Authors. All rights reserved.
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/proxy/proxy_resolver_v8_tracing.h"
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/bind.h"
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "base/message_loop/message_loop_proxy.h"
95e3f23d412006dc4db4e659864679f29341e113fTorne (Richard Coles)#include "base/strings/stringprintf.h"
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/cancellation_flag.h"
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/synchronization/waitable_event.h"
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread.h"
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/threading/thread_restrictions.h"
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/values.h"
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/address_list.h"
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_errors.h"
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/base/net_log.h"
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/dns/host_resolver.h"
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/proxy/proxy_info.h"
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/proxy/proxy_resolver_error_observer.h"
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/proxy/proxy_resolver_v8.h"
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The intent of this class is explained in the design document:
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// https://docs.google.com/a/chromium.org/document/d/16Ij5OcVnR3s0MH4Z5XkhI9VTPoMJdaBn9rKreAmGOdE/edit
252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// In a nutshell, PAC scripts are Javascript programs and may depend on
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// network I/O, by calling functions like dnsResolve().
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is problematic since functions such as dnsResolve() will block the
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Javascript execution until the DNS result is availble, thereby stalling the
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// PAC thread, which hurts the ability to process parallel proxy resolves.
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// An obvious solution is to simply start more PAC threads, however this scales
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// poorly, which hurts the ability to process parallel proxy resolves.
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The solution in ProxyResolverV8Tracing is to model PAC scripts as being
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// deterministic, and depending only on the inputted URL. When the script
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// issues a dnsResolve() for a yet unresolved hostname, the Javascript
382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// execution is "aborted", and then re-started once the DNS result is
392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// known.
402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace net {
412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace {
432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Upper bound on how many *unique* DNS resolves a PAC script is allowed
452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// to make. This is a failsafe both for scripts that do a ridiculous
462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// number of DNS resolves, as well as scripts which are misbehaving
472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// under the tracing optimization. It is not expected to hit this normally.
482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kMaxUniqueResolveDnsPerExec = 20;
492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Approximate number of bytes to use for buffering alerts() and errors.
512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// This is a failsafe in case repeated executions of the script causes
522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// too much memory bloat. It is not expected for well behaved scripts to
532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// hit this. (In fact normal scripts should not even have alerts() or errors).
542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kMaxAlertsAndErrorsBytes = 2048;
552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Returns event parameters for a PAC error message (line number + message).
572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)base::Value* NetLogErrorCallback(int line_number,
58c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                 const base::string16* message,
592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                 NetLog::LogLevel /* log_level */) {
602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::DictionaryValue* dict = new base::DictionaryValue();
612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetInteger("line_number", line_number);
622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dict->SetString("message", *message);
632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return dict;
642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace
672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The Job class is responsible for executing GetProxyForURL() and
692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// SetPacScript(), since both of these operations share similar code.
702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The DNS for these operations can operate in either blocking or
722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// non-blocking mode. Blocking mode is used as a fallback when the PAC script
732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// seems to be misbehaving under the tracing optimization.
742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Note that this class runs on both the origin thread and a worker
762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// thread. Most methods are expected to be used exclusively on one thread
772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// or the other.
782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)//
792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The lifetime of Jobs does not exceed that of the ProxyResolverV8Tracing that
802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// spawned it. Destruction might happen on either the origin thread or the
812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// worker thread.
822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)class ProxyResolverV8Tracing::Job
832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : public base::RefCountedThreadSafe<ProxyResolverV8Tracing::Job>,
842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      public ProxyResolverV8::JSBindings {
852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) public:
862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |parent| is non-owned. It is the ProxyResolverV8Tracing that spawned this
872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Job, and must oulive it.
882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  explicit Job(ProxyResolverV8Tracing* parent);
892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called from origin thread.
912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void StartSetPacScript(
922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const scoped_refptr<ProxyResolverScriptData>& script_data,
932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const CompletionCallback& callback);
942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called from origin thread.
962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void StartGetProxyForURL(const GURL& url,
972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           ProxyInfo* results,
982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const BoundNetLog& net_log,
992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           const CompletionCallback& callback);
1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called from origin thread.
1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Cancel();
1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Called from origin thread.
1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  LoadState GetLoadState() const;
1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) private:
1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  typedef std::map<std::string, std::string> DnsCache;
1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  friend class base::RefCountedThreadSafe<ProxyResolverV8Tracing::Job>;
1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  enum Operation {
1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    SET_PAC_SCRIPT,
1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    GET_PROXY_FOR_URL,
1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  struct AlertOrError {
1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool is_alert;
1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int line_number;
119c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    base::string16 message;
1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  };
1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual ~Job();
1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CheckIsOnWorkerThread() const;
1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void CheckIsOnOriginThread() const;
1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SetCallback(const CompletionCallback& callback);
1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ReleaseCallback();
1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyResolverV8* v8_resolver();
13190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  base::MessageLoop* worker_loop();
1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HostResolver* host_resolver();
1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyResolverErrorObserver* error_observer();
1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NetLog* net_log();
1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Invokes the user's callback.
1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void NotifyCaller(int result);
1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void NotifyCallerOnOriginLoop(int result);
1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void Start(Operation op, bool blocking_dns,
1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)             const CompletionCallback& callback);
1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ExecuteBlocking();
1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ExecuteNonBlocking();
1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int ExecuteProxyResolver();
1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Implementation of ProxyResolverv8::JSBindings
1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  virtual bool ResolveDns(const std::string& host,
1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          ResolveDnsOperation op,
1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          std::string* output,
1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          bool* terminate) OVERRIDE;
152c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void Alert(const base::string16& message) OVERRIDE;
153c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)  virtual void OnError(int line_number, const base::string16& error) OVERRIDE;
1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ResolveDnsBlocking(const std::string& host,
1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          ResolveDnsOperation op,
1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                          std::string* output);
1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool ResolveDnsNonBlocking(const std::string& host,
1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             ResolveDnsOperation op,
1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             std::string* output,
1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                             bool* terminate);
1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool PostDnsOperationAndWait(const std::string& host,
1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               ResolveDnsOperation op,
1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               bool* completed_synchronously)
1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                               WARN_UNUSED_RESULT;
1682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DoDnsOperation();
1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void OnDnsOperationComplete(int result);
1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void ScheduleRestartWithBlockingDns();
1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool GetDnsFromLocalCache(const std::string& host, ResolveDnsOperation op,
1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            std::string* output, bool* return_value);
1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void SaveDnsToLocalCache(const std::string& host, ResolveDnsOperation op,
1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                           int net_error, const net::AddressList& addresses);
1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Builds a RequestInfo to service the specified PAC DNS operation.
1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static HostResolver::RequestInfo MakeDnsRequestInfo(const std::string& host,
1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                      ResolveDnsOperation op);
1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Makes a key for looking up |host, op| in |dns_cache_|. Strings are used for
1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // convenience, to avoid defining custom comparators.
1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  static std::string MakeDnsCacheKey(const std::string& host,
1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                     ResolveDnsOperation op);
1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void HandleAlertOrError(bool is_alert, int line_number,
190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                          const base::string16& message);
1912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DispatchBufferedAlertsAndErrors();
1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void DispatchAlertOrError(bool is_alert, int line_number,
193c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                            const base::string16& message);
1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  void LogEventToCurrentRequestAndGlobally(
1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      NetLog::EventType type,
1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      const NetLog::ParametersCallback& parameters_callback);
1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The thread which called into ProxyResolverV8Tracing, and on which the
2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // completion callback is expected to run.
2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<base::MessageLoopProxy> origin_loop_;
2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The ProxyResolverV8Tracing which spawned this Job.
2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Initialized on origin thread and then accessed from both threads.
2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyResolverV8Tracing* parent_;
2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The callback to run (on the origin thread) when the Job finishes.
2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Should only be accessed from origin thread.
2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CompletionCallback callback_;
2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Flag to indicate whether the request has been cancelled.
2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::CancellationFlag cancelled_;
2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The operation that this Job is running.
2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Initialized on origin thread and then accessed from both threads.
2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Operation operation_;
2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The DNS mode for this Job.
2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Initialized on origin thread, mutated on worker thread, and accessed
2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // by both the origin thread and worker thread.
2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool blocking_dns_;
2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Used to block the worker thread on a DNS operation taking place on the
2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // origin thread.
2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::WaitableEvent event_;
2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Map of DNS operations completed so far. Written into on the origin thread
2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // and read on the worker thread.
2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DnsCache dns_cache_;
2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The job holds a reference to itself to ensure that it remains alive until
2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // either completion or cancellation.
2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<Job> owned_self_reference_;
2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // -------------------------------------------------------
2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // State specific to SET_PAC_SCRIPT.
2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // -------------------------------------------------------
2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<ProxyResolverScriptData> script_data_;
2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // -------------------------------------------------------
2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // State specific to GET_PROXY_FOR_URL.
2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // -------------------------------------------------------
2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyInfo* user_results_;  // Owned by caller, lives on origin thread.
2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  GURL url_;
2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ProxyInfo results_;
2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  BoundNetLog bound_net_log_;
2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ---------------------------------------------------------------------------
2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // State for ExecuteNonBlocking()
2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ---------------------------------------------------------------------------
2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // These variables are used exclusively on the worker thread and are only
2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // meaningful when executing inside of ExecuteNonBlocking().
2552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Whether this execution was abandoned due to a missing DNS dependency.
2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool abandoned_;
2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Number of calls made to ResolveDns() by this execution.
2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int num_dns_;
2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Sequence of calls made to Alert() or OnError() by this execution.
2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::vector<AlertOrError> alerts_and_errors_;
2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  size_t alerts_and_errors_byte_cost_;  // Approximate byte cost of the above.
2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Number of calls made to ResolveDns() by the PREVIOUS execution.
2672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int last_num_dns_;
2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Whether the current execution needs to be restarted in blocking mode.
2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool should_restart_with_blocking_dns_;
2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ---------------------------------------------------------------------------
2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // State for pending DNS request.
2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // ---------------------------------------------------------------------------
2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Handle to the outstanding request in the HostResolver, or NULL.
2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This is mutated and used on the origin thread, however it may be read by
2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the worker thread for some DCHECKS().
2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HostResolver::RequestHandle pending_dns_;
2802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Indicates if the outstanding DNS request completed synchronously. Written
2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // on the origin thread, and read by the worker thread.
2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool pending_dns_completed_synchronously_;
2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // These are the inputs to DoDnsOperation(). Written on the worker thread,
2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // read by the origin thread.
2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string pending_dns_host_;
2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ResolveDnsOperation pending_dns_op_;
2892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // This contains the resolved address list that DoDnsOperation() fills in.
2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Used exclusively on the origin thread.
2922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AddressList pending_dns_addresses_;
2932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)};
2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProxyResolverV8Tracing::Job::Job(ProxyResolverV8Tracing* parent)
2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : origin_loop_(base::MessageLoopProxy::current()),
2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      parent_(parent),
2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      event_(true, false),
2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      last_num_dns_(0),
3001320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci      pending_dns_(NULL) {
3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::StartSetPacScript(
3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const scoped_refptr<ProxyResolverScriptData>& script_data,
3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CompletionCallback& callback) {
3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  script_data_ = script_data;
3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Script initialization uses blocking DNS since there isn't any
3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // advantage to using non-blocking mode here. That is because the
3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // parent ProxyService can't submit any ProxyResolve requests until
3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // initialization has completed successfully!
3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Start(SET_PAC_SCRIPT, true /*blocking*/, callback);
3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::StartGetProxyForURL(
3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const GURL& url,
3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProxyInfo* results,
3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const BoundNetLog& net_log,
3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CompletionCallback& callback) {
3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  url_ = url;
3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  user_results_ = results;
3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bound_net_log_ = net_log;
3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Start(GET_PROXY_FOR_URL, false /*non-blocking*/, callback);
3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::Cancel() {
3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There are several possibilities to consider for cancellation:
3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (a) The job has been posted to the worker thread, however script execution
3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     has not yet started.
3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (b) The script is executing on the worker thread.
3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (c) The script is executing on the worker thread, however is blocked inside
3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     of dnsResolve() waiting for a response from the origin thread.
3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (d) Nothing is running on the worker thread, however the host resolver has
3422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     a pending DNS request which upon completion will restart the script
3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     execution.
3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (e) The worker thread has a pending task to restart execution, which was
3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     posted after the DNS dependency was resolved and saved to local cache.
3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // (f) The script execution completed entirely, and posted a task to the
3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //     origin thread to notify the caller.
3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |cancelled_| is read on both the origin thread and worker thread. The
3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // code that runs on the worker thread is littered with checks on
3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // |cancelled_| to break out early.
3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  cancelled_.Set();
3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseCallback();
3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pending_dns_) {
3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    host_resolver()->CancelRequest(pending_dns_);
3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_dns_ = NULL;
3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The worker thread might be blocked waiting for DNS.
3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event_.Signal();
3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  owned_self_reference_ = NULL;
3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LoadState ProxyResolverV8Tracing::Job::GetLoadState() const {
3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pending_dns_)
3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return LOAD_STATE_RESOLVING_HOST_IN_PROXY_SCRIPT;
3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return LOAD_STATE_RESOLVING_PROXY_FOR_URL;
3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProxyResolverV8Tracing::Job::~Job() {
3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!pending_dns_);
3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(callback_.is_null());
3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::CheckIsOnWorkerThread() const {
38290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)  DCHECK_EQ(base::MessageLoop::current(), parent_->thread_->message_loop());
3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::CheckIsOnOriginThread() const {
3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(origin_loop_->BelongsToCurrentThread());
3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::SetCallback(
3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CompletionCallback& callback) {
3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(callback_.is_null());
3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  parent_->num_outstanding_callbacks_++;
3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_ = callback;
3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::ReleaseCallback() {
3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback_.is_null());
4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_GT(parent_->num_outstanding_callbacks_, 0);
4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  parent_->num_outstanding_callbacks_--;
4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback_.Reset();
4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // For good measure, clear this other user-owned pointer.
4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  user_results_ = NULL;
4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProxyResolverV8* ProxyResolverV8Tracing::Job::v8_resolver() {
4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return parent_->v8_resolver_.get();
4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
412868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)base::MessageLoop* ProxyResolverV8Tracing::Job::worker_loop() {
4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return parent_->thread_->message_loop();
4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HostResolver* ProxyResolverV8Tracing::Job::host_resolver() {
4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return parent_->host_resolver_;
4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProxyResolverErrorObserver* ProxyResolverV8Tracing::Job::error_observer() {
4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return parent_->error_observer_.get();
4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)NetLog* ProxyResolverV8Tracing::Job::net_log() {
4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return parent_->net_log_;
4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::NotifyCaller(int result) {
4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnWorkerThread();
4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  origin_loop_->PostTask(
4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      FROM_HERE,
4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Job::NotifyCallerOnOriginLoop, this, result));
4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::NotifyCallerOnOriginLoop(int result) {
4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cancelled_.IsSet())
4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback_.is_null());
4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!pending_dns_);
4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (operation_ == GET_PROXY_FOR_URL) {
4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *user_results_ = results_;
4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // There is only ever 1 outstanding SET_PAC_SCRIPT job. It needs to be
4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // tracked to support cancellation.
4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (operation_ == SET_PAC_SCRIPT) {
4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK_EQ(parent_->set_pac_script_job_.get(), this);
4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    parent_->set_pac_script_job_ = NULL;
4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CompletionCallback callback = callback_;
4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  ReleaseCallback();
4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  callback.Run(result);
4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  owned_self_reference_ = NULL;
4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::Start(Operation op, bool blocking_dns,
4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                        const CompletionCallback& callback) {
4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  operation_ = op;
4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  blocking_dns_ = blocking_dns;
4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SetCallback(callback);
4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  owned_self_reference_ = this;
4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  worker_loop()->PostTask(FROM_HERE,
4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      blocking_dns_ ? base::Bind(&Job::ExecuteBlocking, this) :
4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      base::Bind(&Job::ExecuteNonBlocking, this));
4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::ExecuteBlocking() {
4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnWorkerThread();
4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(blocking_dns_);
4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cancelled_.IsSet())
4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyCaller(ExecuteProxyResolver());
4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::ExecuteNonBlocking() {
4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnWorkerThread();
4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!blocking_dns_);
4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cancelled_.IsSet())
4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Reset state for the current execution.
4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  abandoned_ = false;
4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  num_dns_ = 0;
4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  alerts_and_errors_.clear();
4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  alerts_and_errors_byte_cost_ = 0;
5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  should_restart_with_blocking_dns_ = false;
5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int result = ExecuteProxyResolver();
5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (should_restart_with_blocking_dns_) {
5052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(!blocking_dns_);
5062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(abandoned_);
5072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    blocking_dns_ = true;
5082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ExecuteBlocking();
5092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (abandoned_)
5132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
5142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DispatchBufferedAlertsAndErrors();
5162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  NotifyCaller(result);
5172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int ProxyResolverV8Tracing::Job::ExecuteProxyResolver() {
5202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  JSBindings* prev_bindings = v8_resolver()->js_bindings();
5212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8_resolver()->set_js_bindings(this);
5222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int result = ERR_UNEXPECTED;  // Initialized to silence warnings.
5242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  switch (operation_) {
5262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case SET_PAC_SCRIPT:
5272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result = v8_resolver()->SetPacScript(
5282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)          script_data_, CompletionCallback());
5292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
5302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    case GET_PROXY_FOR_URL:
5312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      result = v8_resolver()->GetProxyForURL(
5322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        url_,
5332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // Important: Do not write directly into |user_results_|, since if the
5342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // request were to be cancelled from the origin thread, must guarantee
5352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        // that |user_results_| is not accessed anymore.
5362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        &results_,
5372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        CompletionCallback(),
5382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        NULL,
5392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        bound_net_log_);
5402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      break;
5412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8_resolver()->set_js_bindings(prev_bindings);
5442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return result;
5462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ProxyResolverV8Tracing::Job::ResolveDns(const std::string& host,
5492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             ResolveDnsOperation op,
5502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             std::string* output,
5512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                             bool* terminate) {
5522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cancelled_.IsSet()) {
5532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *terminate = true;
5542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
5552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if ((op == DNS_RESOLVE || op == DNS_RESOLVE_EX) && host.empty()) {
5582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // a DNS resolve with an empty hostname is considered an error.
5592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
5602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return blocking_dns_ ?
5632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ResolveDnsBlocking(host, op, output) :
5642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      ResolveDnsNonBlocking(host, op, output, terminate);
5652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
567c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ProxyResolverV8Tracing::Job::Alert(const base::string16& message) {
5682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HandleAlertOrError(true, -1, message);
5692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::OnError(int line_number,
572c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)                                          const base::string16& error) {
5732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HandleAlertOrError(false, line_number, error);
5742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
5752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ProxyResolverV8Tracing::Job::ResolveDnsBlocking(const std::string& host,
5772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                     ResolveDnsOperation op,
5782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                     std::string* output) {
5792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnWorkerThread();
5802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check if the DNS result for this host has already been cached.
5822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool rv;
5832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (GetDnsFromLocalCache(host, op, output, &rv)) {
5842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Yay, cache hit!
5852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
5862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dns_cache_.size() >= kMaxUniqueResolveDnsPerExec) {
5892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Safety net for scripts with unexpectedly many DNS calls.
5902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // We will continue running to completion, but will fail every
5912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // subsequent DNS request.
5922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
5932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
5942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!PostDnsOperationAndWait(host, op, NULL))
5962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;  // Was cancelled.
5972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
5982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK(GetDnsFromLocalCache(host, op, output, &rv));
5992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return rv;
6002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ProxyResolverV8Tracing::Job::ResolveDnsNonBlocking(const std::string& host,
6032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                        ResolveDnsOperation op,
6042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                        std::string* output,
6052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                                        bool* terminate) {
6062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnWorkerThread();
6072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (abandoned_) {
6092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // If this execution was already abandoned can fail right away. Only 1 DNS
6102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // dependency will be traced at a time (for more predictable outcomes).
6112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
6122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  num_dns_ += 1;
6152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check if the DNS result for this host has already been cached.
6172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool rv;
6182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (GetDnsFromLocalCache(host, op, output, &rv)) {
6192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Yay, cache hit!
6202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
6212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (num_dns_ <= last_num_dns_) {
6242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The sequence of DNS operations is different from last time!
6252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScheduleRestartWithBlockingDns();
6262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *terminate = true;
6272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
6282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (dns_cache_.size() >= kMaxUniqueResolveDnsPerExec) {
6312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Safety net for scripts with unexpectedly many DNS calls.
6322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
6332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!should_restart_with_blocking_dns_);
6362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bool completed_synchronously;
6382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!PostDnsOperationAndWait(host, op, &completed_synchronously))
6392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;  // Was cancelled.
6402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (completed_synchronously) {
6422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    CHECK(GetDnsFromLocalCache(host, op, output, &rv));
6432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return rv;
6442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
6452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Otherwise if the result was not in the cache, then a DNS request has
6472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // been started. Abandon this invocation of FindProxyForURL(), it will be
6482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // restarted once the DNS request completes.
6492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  abandoned_ = true;
6502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *terminate = true;
6512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  last_num_dns_ = num_dns_;
6522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return false;
6532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ProxyResolverV8Tracing::Job::PostDnsOperationAndWait(
6562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& host, ResolveDnsOperation op,
6572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool* completed_synchronously) {
6582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Post the DNS request to the origin thread.
6602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!pending_dns_);
6612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_dns_host_ = host;
6622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_dns_op_ = op;
6632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  origin_loop_->PostTask(FROM_HERE, base::Bind(&Job::DoDnsOperation, this));
6642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event_.Wait();
6662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  event_.Reset();
6672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cancelled_.IsSet())
6692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
6702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (completed_synchronously)
6722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *completed_synchronously = pending_dns_completed_synchronously_;
6732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
6752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
6762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::DoDnsOperation() {
6782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
6792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!pending_dns_);
6802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cancelled_.IsSet())
6822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
6832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HostResolver::RequestHandle dns_request = NULL;
6852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  int result = host_resolver()->Resolve(
6862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      MakeDnsRequestInfo(pending_dns_host_, pending_dns_op_),
6873551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)      DEFAULT_PRIORITY,
6882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &pending_dns_addresses_,
6892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      base::Bind(&Job::OnDnsOperationComplete, this),
6902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      &dns_request,
6912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      bound_net_log_);
6922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_dns_completed_synchronously_ = result != ERR_IO_PENDING;
6942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
6952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Check if the request was cancelled as a side-effect of calling into the
6962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // HostResolver. This isn't the ordinary execution flow, however it is
6972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // exercised by unit-tests.
6982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cancelled_.IsSet()) {
6992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (!pending_dns_completed_synchronously_)
7002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_resolver()->CancelRequest(dns_request);
7012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (pending_dns_completed_synchronously_) {
7052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    OnDnsOperationComplete(result);
7062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
7072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DCHECK(dns_request);
7082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    pending_dns_ = dns_request;
7092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // OnDnsOperationComplete() will be called by host resolver on completion.
7102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!blocking_dns_) {
7132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The worker thread always blocks waiting to see if the result can be
7142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // serviced from cache before restarting.
7152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event_.Signal();
7162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::OnDnsOperationComplete(int result) {
7202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
7212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!cancelled_.IsSet());
7232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(pending_dns_completed_synchronously_ == (pending_dns_ == NULL));
7242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  SaveDnsToLocalCache(pending_dns_host_, pending_dns_op_, result,
7262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                      pending_dns_addresses_);
7272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  pending_dns_ = NULL;
7282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (blocking_dns_) {
7302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    event_.Signal();
7312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
7322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (!blocking_dns_ && !pending_dns_completed_synchronously_) {
7352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Restart. This time it should make more progress due to having
7362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // cached items.
7372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    worker_loop()->PostTask(FROM_HERE,
7382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                            base::Bind(&Job::ExecuteNonBlocking, this));
7392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::ScheduleRestartWithBlockingDns() {
7432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnWorkerThread();
7442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!should_restart_with_blocking_dns_);
7462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!abandoned_);
7472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!blocking_dns_);
7482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  abandoned_ = true;
7502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The restart will happen after ExecuteNonBlocking() finishes.
7522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  should_restart_with_blocking_dns_ = true;
7532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool ProxyResolverV8Tracing::Job::GetDnsFromLocalCache(
7562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& host,
7572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ResolveDnsOperation op,
7582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    std::string* output,
7592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    bool* return_value) {
7602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnWorkerThread();
7612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DnsCache::const_iterator it = dns_cache_.find(MakeDnsCacheKey(host, op));
7632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (it == dns_cache_.end())
7642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return false;
7652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *output = it->second;
7672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  *return_value = !it->second.empty();
7682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return true;
7692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::SaveDnsToLocalCache(
7722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& host,
7732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ResolveDnsOperation op,
7742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    int net_error,
7752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const net::AddressList& addresses) {
7762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnOriginThread();
7772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Serialize the result into a string to save to the cache.
7792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  std::string cache_value;
7802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (net_error != OK) {
7812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cache_value = std::string();
7822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else if (op == DNS_RESOLVE || op == MY_IP_ADDRESS) {
7832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // dnsResolve() and myIpAddress() are expected to return a single IP
7842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // address.
7852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    cache_value = addresses.front().ToStringWithoutPort();
7862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
7872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // The *Ex versions are expected to return a semi-colon separated list.
7882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    for (AddressList::const_iterator iter = addresses.begin();
7892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)         iter != addresses.end(); ++iter) {
7902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      if (!cache_value.empty())
7912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        cache_value += ";";
7922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      cache_value += iter->ToStringWithoutPort();
7932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    }
7942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
7952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  dns_cache_[MakeDnsCacheKey(host, op)] = cache_value;
7972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
7982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
7992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static
8002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)HostResolver::RequestInfo ProxyResolverV8Tracing::Job::MakeDnsRequestInfo(
8012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& host, ResolveDnsOperation op) {
8022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HostPortPair host_port = HostPortPair(host, 80);
8032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (op == MY_IP_ADDRESS || op == MY_IP_ADDRESS_EX) {
8042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    host_port.set_host(GetHostName());
8052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  HostResolver::RequestInfo info(host_port);
808116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  // Flag myIpAddress requests.
809116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  if (op == MY_IP_ADDRESS || op == MY_IP_ADDRESS_EX) {
810116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // TODO: Provide a RequestInfo construction mechanism that does not
811116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    // require a hostname and sets is_my_ip_address to true instead of this.
812116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch    info.set_is_my_ip_address(true);
813116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  }
8142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // The non-ex flavors are limited to IPv4 results.
8152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (op == MY_IP_ADDRESS || op == DNS_RESOLVE) {
8162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    info.set_address_family(ADDRESS_FAMILY_IPV4);
8172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return info;
8202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)std::string ProxyResolverV8Tracing::Job::MakeDnsCacheKey(
8232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const std::string& host, ResolveDnsOperation op) {
8242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return base::StringPrintf("%d:%s", op, host.c_str());
8252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
827c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void ProxyResolverV8Tracing::Job::HandleAlertOrError(
828c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool is_alert,
829c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    int line_number,
830c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    const base::string16& message) {
8312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnWorkerThread();
8322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cancelled_.IsSet())
8342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (blocking_dns_) {
8372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // In blocking DNS mode the events can be dispatched immediately.
8382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DispatchAlertOrError(is_alert, line_number, message);
8392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Otherwise in nonblocking mode, buffer all the messages until
8432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // the end.
8442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (abandoned_)
8462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  alerts_and_errors_byte_cost_ += sizeof(AlertOrError) + message.size() * 2;
8492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If there have been lots of messages, enqueing could be expensive on
8512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // memory. Consider a script which does megabytes worth of alerts().
8522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Avoid this by falling back to blocking mode.
8532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (alerts_and_errors_byte_cost_ > kMaxAlertsAndErrorsBytes) {
8542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ScheduleRestartWithBlockingDns();
8552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  AlertOrError entry = {is_alert, line_number, message};
8592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  alerts_and_errors_.push_back(entry);
8602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::DispatchBufferedAlertsAndErrors() {
8632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnWorkerThread();
8642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!blocking_dns_);
8652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!abandoned_);
8662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  for (size_t i = 0; i < alerts_and_errors_.size(); ++i) {
8682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const AlertOrError& x = alerts_and_errors_[i];
8692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    DispatchAlertOrError(x.is_alert, x.line_number, x.message);
8702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
8712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
8722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::DispatchAlertOrError(
874c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)    bool is_alert, int line_number, const base::string16& message) {
8752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnWorkerThread();
8762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note that the handling of cancellation is racy with regard to
8782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // alerts/errors. The request might get cancelled shortly after this
8792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // check! (There is no lock being held to guarantee otherwise).
8802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  //
8812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // If this happens, then some information will get written to the NetLog
8822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // needlessly, however the NetLog will still be alive so it shouldn't cause
8832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // problems.
8842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (cancelled_.IsSet())
8852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    return;
8862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (is_alert) {
8882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // -------------------
8892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // alert
8902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // -------------------
8912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    VLOG(1) << "PAC-alert: " << message;
8922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
8932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Send to the NetLog.
8942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LogEventToCurrentRequestAndGlobally(
8952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        NetLog::TYPE_PAC_JAVASCRIPT_ALERT,
8962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        NetLog::StringCallback("message", &message));
8972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  } else {
8982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // -------------------
8992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // error
9002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // -------------------
9012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (line_number == -1)
9022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VLOG(1) << "PAC-error: " << message;
9032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    else
9042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      VLOG(1) << "PAC-error: " << "line: " << line_number << ": " << message;
9052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    // Send the error to the NetLog.
9072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    LogEventToCurrentRequestAndGlobally(
9082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        NetLog::TYPE_PAC_JAVASCRIPT_ERROR,
9092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)        base::Bind(&NetLogErrorCallback, line_number, &message));
9102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    if (error_observer())
9122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_observer()->OnPACScriptError(line_number, message);
9132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  }
9142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::Job::LogEventToCurrentRequestAndGlobally(
9172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NetLog::EventType type,
9182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const NetLog::ParametersCallback& parameters_callback) {
9192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CheckIsOnWorkerThread();
9202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  bound_net_log_.AddEvent(type, parameters_callback);
9212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Emit to the global NetLog event stream.
9232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (net_log())
9242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    net_log()->AddGlobalEntry(type, parameters_callback);
9252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProxyResolverV8Tracing::ProxyResolverV8Tracing(
9282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    HostResolver* host_resolver,
9292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    ProxyResolverErrorObserver* error_observer,
9302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    NetLog* net_log)
9312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    : ProxyResolver(true /*expects_pac_bytes*/),
9322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      host_resolver_(host_resolver),
9332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      error_observer_(error_observer),
9342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      net_log_(net_log),
9352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)      num_outstanding_callbacks_(0) {
9362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(host_resolver);
9372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Start up the thread.
9382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thread_.reset(new base::Thread("Proxy resolver"));
939116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  base::Thread::Options options;
940116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  options.timer_slack = base::TIMER_SLACK_MAXIMUM;
941116680a4aac90f2aa7413d9095a592090648e557Ben Murdoch  CHECK(thread_->StartWithOptions(options));
9422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  v8_resolver_.reset(new ProxyResolverV8);
9442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)ProxyResolverV8Tracing::~ProxyResolverV8Tracing() {
9472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note, all requests should have been cancelled.
948868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  CHECK(!set_pac_script_job_.get());
9492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_EQ(0, num_outstanding_callbacks_);
9502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Join the worker thread. See http://crbug.com/69710. Note that we call
9522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Stop() here instead of simply clearing thread_ since there may be pending
9532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // callbacks on the worker thread which want to dereference thread_.
9542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  base::ThreadRestrictions::ScopedAllowIO allow_io;
9552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  thread_->Stop();
9562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int ProxyResolverV8Tracing::GetProxyForURL(const GURL& url,
9592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           ProxyInfo* results,
9602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           const CompletionCallback& callback,
9612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           RequestHandle* request,
9622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)                                           const BoundNetLog& net_log) {
9632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
9642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback.is_null());
965868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!set_pac_script_job_.get());
9662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  scoped_refptr<Job> job = new Job(this);
9682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  if (request)
9702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    *request = job.get();
9712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->StartGetProxyForURL(url, results, net_log, callback);
9732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ERR_IO_PENDING;
9742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::CancelRequest(RequestHandle request) {
9772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Job* job = reinterpret_cast<Job*>(request);
9782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  job->Cancel();
9792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)LoadState ProxyResolverV8Tracing::GetLoadState(RequestHandle request) const {
9822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  Job* job = reinterpret_cast<Job*>(request);
9832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return job->GetLoadState();
9842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void ProxyResolverV8Tracing::CancelSetPacScript() {
987868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(set_pac_script_job_.get());
9882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  set_pac_script_job_->Cancel();
9892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  set_pac_script_job_ = NULL;
9902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
9912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int ProxyResolverV8Tracing::SetPacScript(
9932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const scoped_refptr<ProxyResolverScriptData>& script_data,
9942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)    const CompletionCallback& callback) {
9952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(CalledOnValidThread());
9962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  DCHECK(!callback.is_null());
9972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
9982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // Note that there should not be any outstanding (non-cancelled) Jobs when
9992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // setting the PAC script (ProxyService should guarantee this). If there are,
10002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  // then they might complete in strange ways after the new script is set.
1001868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)  DCHECK(!set_pac_script_job_.get());
10022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  CHECK_EQ(0, num_outstanding_callbacks_);
10032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  set_pac_script_job_ = new Job(this);
10052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  set_pac_script_job_->StartSetPacScript(script_data, callback);
10062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)  return ERR_IO_PENDING;
10082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}
10092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
10102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}  // namespace net
1011