1 // Copyright 2017 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 #include "chrome/browser/net/proxy_config_monitor.h"
6
7 #include <utility>
8
9 #include "base/strings/utf_string_conversions.h"
10 #include "build/build_config.h"
11 #include "chrome/browser/browser_process.h"
12 #include "chrome/browser/net/proxy_service_factory.h"
13 #include "chrome/browser/profiles/profile.h"
14 #include "components/proxy_config/pref_proxy_config_tracker_impl.h"
15 #include "content/public/browser/browser_thread.h"
16 #include "mojo/public/cpp/bindings/pending_remote.h"
17 #include "services/network/public/mojom/network_context.mojom.h"
18
19 #if defined(OS_CHROMEOS)
20 #include "chrome/browser/chromeos/profiles/profile_helper.h"
21 #endif // defined(OS_CHROMEOS)
22
23 #if BUILDFLAG(ENABLE_EXTENSIONS)
24 #include "chrome/browser/extensions/api/proxy/proxy_api.h"
25 #endif
26
27 using content::BrowserThread;
28
ProxyConfigMonitor(Profile * profile)29 ProxyConfigMonitor::ProxyConfigMonitor(Profile* profile) {
30 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
31 DCHECK(profile);
32
33 #if BUILDFLAG(ENABLE_EXTENSIONS)
34 profile_ = profile;
35 #endif
36
37 // If this is the ChromeOS sign-in profile, just create the tracker from global
38 // state.
39 #if defined(OS_CHROMEOS)
40 if (chromeos::ProfileHelper::IsSigninProfile(profile)) {
41 pref_proxy_config_tracker_ =
42 ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
43 g_browser_process->local_state());
44 }
45 #endif // defined(OS_CHROMEOS)
46
47 if (!pref_proxy_config_tracker_) {
48 pref_proxy_config_tracker_ =
49 ProxyServiceFactory::CreatePrefProxyConfigTrackerOfProfile(
50 profile->GetPrefs(), g_browser_process->local_state());
51 }
52
53 proxy_config_service_ = ProxyServiceFactory::CreateProxyConfigService(
54 pref_proxy_config_tracker_.get());
55
56 proxy_config_service_->AddObserver(this);
57 }
58
ProxyConfigMonitor(PrefService * local_state)59 ProxyConfigMonitor::ProxyConfigMonitor(PrefService* local_state) {
60 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
61 !BrowserThread::IsThreadInitialized(BrowserThread::UI));
62
63 pref_proxy_config_tracker_ =
64 ProxyServiceFactory::CreatePrefProxyConfigTrackerOfLocalState(
65 local_state);
66
67 proxy_config_service_ = ProxyServiceFactory::CreateProxyConfigService(
68 pref_proxy_config_tracker_.get());
69
70 proxy_config_service_->AddObserver(this);
71 }
72
~ProxyConfigMonitor()73 ProxyConfigMonitor::~ProxyConfigMonitor() {
74 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
75 !BrowserThread::IsThreadInitialized(BrowserThread::UI));
76 proxy_config_service_->RemoveObserver(this);
77 pref_proxy_config_tracker_->DetachFromPrefService();
78 }
79
AddToNetworkContextParams(network::mojom::NetworkContextParams * network_context_params)80 void ProxyConfigMonitor::AddToNetworkContextParams(
81 network::mojom::NetworkContextParams* network_context_params) {
82 mojo::PendingRemote<network::mojom::ProxyConfigClient> proxy_config_client;
83 network_context_params->proxy_config_client_receiver =
84 proxy_config_client.InitWithNewPipeAndPassReceiver();
85 proxy_config_client_set_.Add(std::move(proxy_config_client));
86
87 poller_receiver_set_.Add(this,
88 network_context_params->proxy_config_poller_client
89 .InitWithNewPipeAndPassReceiver());
90
91 #if BUILDFLAG(ENABLE_EXTENSIONS)
92 error_receiver_set_.Add(this, network_context_params->proxy_error_client
93 .InitWithNewPipeAndPassReceiver());
94 #endif
95
96 net::ProxyConfigWithAnnotation proxy_config;
97 net::ProxyConfigService::ConfigAvailability availability =
98 proxy_config_service_->GetLatestProxyConfig(&proxy_config);
99 if (availability != net::ProxyConfigService::CONFIG_PENDING)
100 network_context_params->initial_proxy_config = proxy_config;
101 }
102
FlushForTesting()103 void ProxyConfigMonitor::FlushForTesting() {
104 proxy_config_client_set_.FlushForTesting();
105 }
106
OnProxyConfigChanged(const net::ProxyConfigWithAnnotation & config,net::ProxyConfigService::ConfigAvailability availability)107 void ProxyConfigMonitor::OnProxyConfigChanged(
108 const net::ProxyConfigWithAnnotation& config,
109 net::ProxyConfigService::ConfigAvailability availability) {
110 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
111 !BrowserThread::IsThreadInitialized(BrowserThread::UI));
112 for (const auto& proxy_config_client : proxy_config_client_set_) {
113 switch (availability) {
114 case net::ProxyConfigService::CONFIG_VALID:
115 proxy_config_client->OnProxyConfigUpdated(config);
116 break;
117 case net::ProxyConfigService::CONFIG_UNSET:
118 proxy_config_client->OnProxyConfigUpdated(
119 net::ProxyConfigWithAnnotation::CreateDirect());
120 break;
121 case net::ProxyConfigService::CONFIG_PENDING:
122 NOTREACHED();
123 break;
124 }
125 }
126 }
127
OnLazyProxyConfigPoll()128 void ProxyConfigMonitor::OnLazyProxyConfigPoll() {
129 proxy_config_service_->OnLazyPoll();
130 }
131
132 #if BUILDFLAG(ENABLE_EXTENSIONS)
OnPACScriptError(int32_t line_number,const std::string & details)133 void ProxyConfigMonitor::OnPACScriptError(int32_t line_number,
134 const std::string& details) {
135 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
136 extensions::ProxyEventRouter::GetInstance()->OnPACScriptError(
137 g_browser_process->extension_event_router_forwarder(), profile_,
138 line_number, base::UTF8ToUTF16(details));
139 }
140
OnRequestMaybeFailedDueToProxySettings(int32_t net_error)141 void ProxyConfigMonitor::OnRequestMaybeFailedDueToProxySettings(
142 int32_t net_error) {
143 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI) ||
144 !BrowserThread::IsThreadInitialized(BrowserThread::UI));
145
146 if (net_error >= 0) {
147 // If the error is obviously wrong, don't dispatch it to extensions. If the
148 // PAC executor process is compromised, then |net_error| could be attacker
149 // controlled.
150 return;
151 }
152
153 extensions::ProxyEventRouter::GetInstance()->OnProxyError(
154 g_browser_process->extension_event_router_forwarder(), profile_,
155 net_error);
156 }
157 #endif
158