1// Copyright (c) 2011 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 CHROME_BROWSER_NET_PREF_PROXY_CONFIG_SERVICE_H_
6#define CHROME_BROWSER_NET_PREF_PROXY_CONFIG_SERVICE_H_
7#pragma once
8
9#include "base/basictypes.h"
10#include "base/memory/ref_counted.h"
11#include "base/memory/scoped_ptr.h"
12#include "base/observer_list.h"
13#include "chrome/browser/prefs/proxy_config_dictionary.h"
14#include "content/common/notification_observer.h"
15#include "net/proxy/proxy_config.h"
16#include "net/proxy/proxy_config_service.h"
17
18class PrefService;
19class PrefSetObserver;
20
21// A helper class that tracks proxy preferences. It translates the configuration
22// to net::ProxyConfig and proxies the result over to the IO thread for
23// PrefProxyConfigService to use.
24class PrefProxyConfigTracker
25    : public base::RefCountedThreadSafe<PrefProxyConfigTracker>,
26      public NotificationObserver {
27 public:
28  // Observer interface used to send out notifications on the IO thread about
29  // changes to the proxy configuration.
30  class Observer {
31   public:
32    virtual ~Observer() {}
33    virtual void OnPrefProxyConfigChanged() = 0;
34  };
35
36  // Return codes for GetProxyConfig.
37  enum ConfigState {
38    // Configuration is valid and present.
39    CONFIG_PRESENT,
40    // There is a fallback configuration present.
41    CONFIG_FALLBACK,
42    // Configuration is known to be not set.
43    CONFIG_UNSET,
44  };
45
46  explicit PrefProxyConfigTracker(PrefService* pref_service);
47
48  // Observer manipulation is only valid on the IO thread.
49  void AddObserver(Observer* observer);
50  void RemoveObserver(Observer* observer);
51
52  // Get the proxy configuration currently defined by preferences. Status is
53  // indicated in the return value. Writes the configuration to |config| unless
54  // the return value is CONFIG_UNSET, in which case |config| is not touched.
55  ConfigState GetProxyConfig(net::ProxyConfig* config);
56
57  // Notifies the tracker that the pref service passed upon construction is
58  // about to go away. This must be called from the UI thread.
59  void DetachFromPrefService();
60
61 private:
62  friend class base::RefCountedThreadSafe<PrefProxyConfigTracker>;
63  virtual ~PrefProxyConfigTracker();
64
65  // NotificationObserver implementation:
66  virtual void Observe(NotificationType type,
67                       const NotificationSource& source,
68                       const NotificationDetails& details);
69
70  // Install a new configuration. This is invoked on the IO thread to update
71  // the internal state after handling a pref change on the UI thread.
72  // |config_state| indicates the new state we're switching to, and |config| is
73  // the new preference-based proxy configuration if |config_state| is different
74  // from CONFIG_UNSET.
75  void InstallProxyConfig(const net::ProxyConfig& config, ConfigState state);
76
77  // Creates a proxy configuration from proxy-related preferences. Configuration
78  // is stored in |config| and the return value indicates whether the
79  // configuration is valid.
80  ConfigState ReadPrefConfig(net::ProxyConfig* config);
81
82  // Converts a ProxyConfigDictionary to net::ProxyConfig representation.
83  // Returns true if the data from in the dictionary is valid, false otherwise.
84  static bool PrefConfigToNetConfig(const ProxyConfigDictionary& proxy_dict,
85                                    net::ProxyConfig* config);
86
87  // Configuration as defined by prefs. Only to be accessed from the IO thread
88  // (except for construction).
89  net::ProxyConfig pref_config_;
90
91  // Tracks configuration state. |pref_config_| is valid only if |config_state_|
92  // is not CONFIG_UNSET.
93  ConfigState config_state_;
94
95  // List of observers, accessed exclusively from the IO thread.
96  ObserverList<Observer, true> observers_;
97
98  // Pref-related members that should only be accessed from the UI thread.
99  PrefService* pref_service_;
100  scoped_ptr<PrefSetObserver> proxy_prefs_observer_;
101
102  DISALLOW_COPY_AND_ASSIGN(PrefProxyConfigTracker);
103};
104
105// A net::ProxyConfigService implementation that applies preference proxy
106// settings as overrides to the proxy configuration determined by a baseline
107// delegate ProxyConfigService.
108class PrefProxyConfigService
109    : public net::ProxyConfigService,
110      public net::ProxyConfigService::Observer,
111      public PrefProxyConfigTracker::Observer {
112 public:
113  // Takes ownership of the passed |base_service|.
114  PrefProxyConfigService(PrefProxyConfigTracker* tracker,
115                         net::ProxyConfigService* base_service);
116  virtual ~PrefProxyConfigService();
117
118  // ProxyConfigService implementation:
119  virtual void AddObserver(net::ProxyConfigService::Observer* observer);
120  virtual void RemoveObserver(net::ProxyConfigService::Observer* observer);
121  virtual ConfigAvailability GetLatestProxyConfig(net::ProxyConfig* config);
122  virtual void OnLazyPoll();
123
124  static void RegisterPrefs(PrefService* user_prefs);
125
126 private:
127  // ProxyConfigService::Observer implementation:
128  virtual void OnProxyConfigChanged(const net::ProxyConfig& config,
129                                    ConfigAvailability availability);
130
131  // PrefProxyConfigTracker::Observer implementation:
132  virtual void OnPrefProxyConfigChanged();
133
134  // Makes sure that the observer registrations with the base service and the
135  // tracker object are set up.
136  void RegisterObservers();
137
138  scoped_ptr<net::ProxyConfigService> base_service_;
139  ObserverList<net::ProxyConfigService::Observer, true> observers_;
140  scoped_refptr<PrefProxyConfigTracker> pref_config_tracker_;
141
142  // Indicates whether the base service and tracker registrations are done.
143  bool registered_observers_;
144
145  DISALLOW_COPY_AND_ASSIGN(PrefProxyConfigService);
146};
147
148#endif  // CHROME_BROWSER_NET_PREF_PROXY_CONFIG_SERVICE_H_
149