Home | History | Annotate | Download | only in proxy
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_WIN_H_
      6 #define NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_WIN_H_
      7 
      8 #include <set>
      9 #include <string>
     10 
     11 #include "base/memory/ref_counted.h"
     12 #include "base/memory/scoped_vector.h"
     13 #include "base/message_loop/message_loop_proxy.h"
     14 #include "base/threading/non_thread_safe.h"
     15 #include "base/time/time.h"
     16 #include "base/timer/timer.h"
     17 #include "net/proxy/dhcp_proxy_script_fetcher.h"
     18 
     19 namespace net {
     20 
     21 class DhcpProxyScriptAdapterFetcher;
     22 class URLRequestContext;
     23 
     24 // Windows-specific implementation.
     25 class NET_EXPORT_PRIVATE DhcpProxyScriptFetcherWin
     26     : public DhcpProxyScriptFetcher,
     27       public base::SupportsWeakPtr<DhcpProxyScriptFetcherWin>,
     28       NON_EXPORTED_BASE(public base::NonThreadSafe) {
     29  public:
     30   // Creates a DhcpProxyScriptFetcherWin that issues requests through
     31   // |url_request_context|. |url_request_context| must remain valid for
     32   // the lifetime of DhcpProxyScriptFetcherWin.
     33   explicit DhcpProxyScriptFetcherWin(URLRequestContext* url_request_context);
     34   virtual ~DhcpProxyScriptFetcherWin();
     35 
     36   // DhcpProxyScriptFetcher implementation.
     37   int Fetch(base::string16* utf16_text,
     38             const net::CompletionCallback& callback) OVERRIDE;
     39   void Cancel() OVERRIDE;
     40   const GURL& GetPacURL() const OVERRIDE;
     41   std::string GetFetcherName() const OVERRIDE;
     42 
     43   // Sets |adapter_names| to contain the name of each network adapter on
     44   // this machine that has DHCP enabled and is not a loop-back adapter. Returns
     45   // false on error.
     46   static bool GetCandidateAdapterNames(std::set<std::string>* adapter_names);
     47 
     48  protected:
     49   int num_pending_fetchers() const;
     50 
     51   URLRequestContext* url_request_context() const;
     52 
     53   // This inner class encapsulate work done on a worker pool thread.
     54   // The class calls GetCandidateAdapterNames, which can take a couple of
     55   // hundred milliseconds.
     56   class NET_EXPORT_PRIVATE AdapterQuery
     57       : public base::RefCountedThreadSafe<AdapterQuery> {
     58    public:
     59     AdapterQuery();
     60     virtual ~AdapterQuery();
     61 
     62     // This is the method that runs on the worker pool thread.
     63     void GetCandidateAdapterNames();
     64 
     65     // This set is valid after GetCandidateAdapterNames has
     66     // been run. Its lifetime is scoped by this object.
     67     const std::set<std::string>& adapter_names() const;
     68 
     69    protected:
     70     // Virtual method introduced to allow unit testing.
     71     virtual bool ImplGetCandidateAdapterNames(
     72         std::set<std::string>* adapter_names);
     73 
     74    private:
     75     // This is constructed on the originating thread, then used on the
     76     // worker thread, then used again on the originating thread only when
     77     // the task has completed on the worker thread. No locking required.
     78     std::set<std::string> adapter_names_;
     79 
     80     DISALLOW_COPY_AND_ASSIGN(AdapterQuery);
     81   };
     82 
     83   // Virtual methods introduced to allow unit testing.
     84   virtual DhcpProxyScriptAdapterFetcher* ImplCreateAdapterFetcher();
     85   virtual AdapterQuery* ImplCreateAdapterQuery();
     86   virtual base::TimeDelta ImplGetMaxWait();
     87   virtual void ImplOnGetCandidateAdapterNamesDone() {}
     88 
     89  private:
     90   // Event/state transition handlers
     91   void CancelImpl();
     92   void OnGetCandidateAdapterNamesDone(scoped_refptr<AdapterQuery> query);
     93   void OnFetcherDone(int result);
     94   void OnWaitTimer();
     95   void TransitionToDone();
     96 
     97   // This is the outer state machine for fetching PAC configuration from
     98   // DHCP.  It relies for sub-states on the state machine of the
     99   // DhcpProxyScriptAdapterFetcher class.
    100   //
    101   // The goal of the implementation is to the following work in parallel
    102   // for all network adapters that are using DHCP:
    103   // a) Try to get the PAC URL configured in DHCP;
    104   // b) If one is configured, try to fetch the PAC URL.
    105   // c) Once this is done for all adapters, or a timeout has passed after
    106   //    it has completed for the fastest adapter, return the PAC file
    107   //    available for the most preferred network adapter, if any.
    108   //
    109   // The state machine goes from START->WAIT_ADAPTERS when it starts a
    110   // worker thread to get the list of adapters with DHCP enabled.
    111   // It then goes from WAIT_ADAPTERS->NO_RESULTS when it creates
    112   // and starts an DhcpProxyScriptAdapterFetcher for each adapter.  It goes
    113   // from NO_RESULTS->SOME_RESULTS when it gets the first result; at this
    114   // point a wait timer is started.  It goes from SOME_RESULTS->DONE in
    115   // two cases: All results are known, or the wait timer expired.  A call
    116   // to Cancel() will also go straight to DONE from any state.  Any
    117   // way the DONE state is entered, we will at that point cancel any
    118   // outstanding work and return the best known PAC script or the empty
    119   // string.
    120   //
    121   // The state machine is reset for each Fetch(), a call to which is
    122   // only valid in states START and DONE, as only one Fetch() is
    123   // allowed to be outstanding at any given time.
    124   enum State {
    125     STATE_START,
    126     STATE_WAIT_ADAPTERS,
    127     STATE_NO_RESULTS,
    128     STATE_SOME_RESULTS,
    129     STATE_DONE,
    130   };
    131 
    132   // Current state of this state machine.
    133   State state_;
    134 
    135   // Vector, in Windows' network adapter preference order, of
    136   // DhcpProxyScriptAdapterFetcher objects that are or were attempting
    137   // to fetch a PAC file based on DHCP configuration.
    138   typedef ScopedVector<DhcpProxyScriptAdapterFetcher> FetcherVector;
    139   FetcherVector fetchers_;
    140 
    141   // Number of fetchers we are waiting for.
    142   int num_pending_fetchers_;
    143 
    144   // Lets our client know we're done. Not valid in states START or DONE.
    145   net::CompletionCallback callback_;
    146 
    147   // Pointer to string we will write results to. Not valid in states
    148   // START and DONE.
    149   base::string16* destination_string_;
    150 
    151   // PAC URL retrieved from DHCP, if any. Valid only in state STATE_DONE.
    152   GURL pac_url_;
    153 
    154   base::OneShotTimer<DhcpProxyScriptFetcherWin> wait_timer_;
    155 
    156   URLRequestContext* const url_request_context_;
    157 
    158   // NULL or the AdapterQuery currently in flight.
    159   scoped_refptr<AdapterQuery> last_query_;
    160 
    161   // Time |Fetch()| was last called, 0 if never.
    162   base::TimeTicks fetch_start_time_;
    163 
    164   DISALLOW_IMPLICIT_CONSTRUCTORS(DhcpProxyScriptFetcherWin);
    165 };
    166 
    167 }  // namespace net
    168 
    169 #endif  // NET_PROXY_DHCP_PROXY_SCRIPT_FETCHER_WIN_H_
    170