• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "chrome/browser/chromeos/proxy_config_service_impl.h"
6 
7 #include <ostream>
8 
9 #include "base/logging.h"
10 #include "base/string_util.h"
11 #include "base/task.h"
12 #include "chrome/browser/chromeos/cros/cros_library.h"
13 #include "chrome/browser/chromeos/cros_settings_names.h"
14 #include "chrome/browser/policy/proto/chrome_device_policy.pb.h"
15 #include "chrome/browser/prefs/proxy_prefs.h"
16 #include "content/browser/browser_thread.h"
17 
18 namespace em = enterprise_management;
19 
20 namespace chromeos {
21 
22 namespace {
23 
SourceToString(ProxyConfigServiceImpl::ProxyConfig::Source source)24 const char* SourceToString(ProxyConfigServiceImpl::ProxyConfig::Source source) {
25   switch (source) {
26     case ProxyConfigServiceImpl::ProxyConfig::SOURCE_NONE:
27       return "SOURCE_NONE";
28     case ProxyConfigServiceImpl::ProxyConfig::SOURCE_POLICY:
29       return "SOURCE_POLICY";
30     case ProxyConfigServiceImpl::ProxyConfig::SOURCE_OWNER:
31       return "SOURCE_OWNER";
32   }
33   NOTREACHED() << "Unrecognized source type";
34   return "";
35 }
36 
operator <<(std::ostream & out,const ProxyConfigServiceImpl::ProxyConfig::ManualProxy & proxy)37 std::ostream& operator<<(std::ostream& out,
38     const ProxyConfigServiceImpl::ProxyConfig::ManualProxy& proxy) {
39   out << "  " << SourceToString(proxy.source) << "\n"
40       << "  server: " << (proxy.server.is_valid() ? proxy.server.ToURI() : "")
41       << "\n";
42   return out;
43 }
44 
operator <<(std::ostream & out,const ProxyConfigServiceImpl::ProxyConfig & config)45 std::ostream& operator<<(std::ostream& out,
46     const ProxyConfigServiceImpl::ProxyConfig& config) {
47   switch (config.mode) {
48     case ProxyConfigServiceImpl::ProxyConfig::MODE_DIRECT:
49       out << "Direct connection:\n  "
50           << SourceToString(config.automatic_proxy.source) << "\n";
51       break;
52     case ProxyConfigServiceImpl::ProxyConfig::MODE_AUTO_DETECT:
53       out << "Auto detection:\n  "
54           << SourceToString(config.automatic_proxy.source) << "\n";
55       break;
56     case ProxyConfigServiceImpl::ProxyConfig::MODE_PAC_SCRIPT:
57       out << "Custom PAC script:\n  "
58           << SourceToString(config.automatic_proxy.source)
59           << "\n  PAC: " << config.automatic_proxy.pac_url << "\n";
60       break;
61     case ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY:
62       out << "Single proxy:\n" << config.single_proxy;
63       break;
64     case ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME:
65       out << "HTTP proxy: " << config.http_proxy;
66       out << "HTTPS proxy: " << config.https_proxy;
67       out << "FTP proxy: " << config.ftp_proxy;
68       out << "SOCKS proxy: " << config.socks_proxy;
69       break;
70     default:
71       NOTREACHED() << "Unrecognized proxy config mode";
72       break;
73   }
74   if (config.mode == ProxyConfigServiceImpl::ProxyConfig::MODE_SINGLE_PROXY ||
75       config.mode ==
76           ProxyConfigServiceImpl::ProxyConfig::MODE_PROXY_PER_SCHEME) {
77     out << "Bypass list: ";
78     if (config.bypass_rules.rules().empty()) {
79       out << "[None]";
80     } else {
81       const net::ProxyBypassRules& bypass_rules = config.bypass_rules;
82       net::ProxyBypassRules::RuleList::const_iterator it;
83       for (it = bypass_rules.rules().begin();
84            it != bypass_rules.rules().end(); ++it) {
85         out << "\n    " << (*it)->ToString();
86       }
87     }
88   }
89   return out;
90 }
91 
ProxyConfigToString(const ProxyConfigServiceImpl::ProxyConfig & proxy_config)92 std::string ProxyConfigToString(
93     const ProxyConfigServiceImpl::ProxyConfig& proxy_config) {
94   std::ostringstream stream;
95   stream << proxy_config;
96   return stream.str();
97 }
98 
99 }  // namespace
100 
101 //---------- ProxyConfigServiceImpl::ProxyConfig::Setting methods --------------
102 
CanBeWrittenByUser(bool user_is_owner)103 bool ProxyConfigServiceImpl::ProxyConfig::Setting::CanBeWrittenByUser(
104     bool user_is_owner) {
105   // Setting can only be written by user if user is owner and setting is not
106   // from policy.
107   return user_is_owner && source != ProxyConfig::SOURCE_POLICY;
108 }
109 
110 //----------- ProxyConfigServiceImpl::ProxyConfig: public methods --------------
111 
ToNetProxyConfig(net::ProxyConfig * net_config)112 void ProxyConfigServiceImpl::ProxyConfig::ToNetProxyConfig(
113     net::ProxyConfig* net_config) {
114   switch (mode) {
115     case MODE_DIRECT:
116       *net_config = net::ProxyConfig::CreateDirect();
117       break;
118     case MODE_AUTO_DETECT:
119       *net_config = net::ProxyConfig::CreateAutoDetect();
120       break;
121     case MODE_PAC_SCRIPT:
122       *net_config = net::ProxyConfig::CreateFromCustomPacURL(
123           automatic_proxy.pac_url);
124       break;
125     case MODE_SINGLE_PROXY:
126       *net_config = net::ProxyConfig();
127       net_config->proxy_rules().type =
128              net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY;
129       net_config->proxy_rules().single_proxy = single_proxy.server;
130       net_config->proxy_rules().bypass_rules = bypass_rules;
131       break;
132     case MODE_PROXY_PER_SCHEME:
133       *net_config = net::ProxyConfig();
134       net_config->proxy_rules().type =
135           net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME;
136       net_config->proxy_rules().proxy_for_http = http_proxy.server;
137       net_config->proxy_rules().proxy_for_https = https_proxy.server;
138       net_config->proxy_rules().proxy_for_ftp = ftp_proxy.server;
139       net_config->proxy_rules().fallback_proxy = socks_proxy.server;
140       net_config->proxy_rules().bypass_rules = bypass_rules;
141       break;
142     default:
143       NOTREACHED() << "Unrecognized proxy config mode";
144       break;
145   }
146 }
147 
CanBeWrittenByUser(bool user_is_owner,const std::string & scheme)148 bool ProxyConfigServiceImpl::ProxyConfig::CanBeWrittenByUser(
149     bool user_is_owner, const std::string& scheme) {
150   // Setting can only be written by user if user is owner and setting is not
151   // from policy.
152   Setting* setting = NULL;
153   switch (mode) {
154     case MODE_DIRECT:
155     case MODE_AUTO_DETECT:
156     case MODE_PAC_SCRIPT:
157       setting = &automatic_proxy;
158       break;
159     case MODE_SINGLE_PROXY:
160       setting = &single_proxy;
161       break;
162     case MODE_PROXY_PER_SCHEME:
163       setting = MapSchemeToProxy(scheme);
164       break;
165     default:
166       break;
167   }
168   if (!setting) {
169     NOTREACHED() << "Unrecognized proxy config mode";
170     return false;
171   }
172   return setting->CanBeWrittenByUser(user_is_owner);
173 }
174 
175 ProxyConfigServiceImpl::ProxyConfig::ManualProxy*
MapSchemeToProxy(const std::string & scheme)176     ProxyConfigServiceImpl::ProxyConfig::MapSchemeToProxy(
177         const std::string& scheme) {
178   if (scheme == "http")
179     return &http_proxy;
180   if (scheme == "https")
181     return &https_proxy;
182   if (scheme == "ftp")
183     return &ftp_proxy;
184   if (scheme == "socks")
185     return &socks_proxy;
186   NOTREACHED() << "Invalid scheme: " << scheme;
187   return NULL;
188 }
189 
Serialize(std::string * output)190 bool ProxyConfigServiceImpl::ProxyConfig::Serialize(std::string* output) {
191   em::DeviceProxySettingsProto proxy_proto;
192   switch (mode) {
193     case MODE_DIRECT: {
194       proxy_proto.set_proxy_mode(ProxyPrefs::kDirectProxyModeName);
195       break;
196     }
197     case MODE_AUTO_DETECT: {
198       proxy_proto.set_proxy_mode(ProxyPrefs::kAutoDetectProxyModeName);
199       break;
200     }
201     case MODE_PAC_SCRIPT: {
202       proxy_proto.set_proxy_mode(ProxyPrefs::kPacScriptProxyModeName);
203       if (!automatic_proxy.pac_url.is_empty())
204         proxy_proto.set_proxy_pac_url(automatic_proxy.pac_url.spec());
205       break;
206     }
207     case MODE_SINGLE_PROXY: {
208       proxy_proto.set_proxy_mode(ProxyPrefs::kFixedServersProxyModeName);
209       if (single_proxy.server.is_valid())
210         proxy_proto.set_proxy_server(single_proxy.server.ToURI());
211       break;
212     }
213     case MODE_PROXY_PER_SCHEME: {
214       proxy_proto.set_proxy_mode(ProxyPrefs::kFixedServersProxyModeName);
215       std::string spec;
216       EncodeAndAppendProxyServer("http", http_proxy.server, &spec);
217       EncodeAndAppendProxyServer("https", https_proxy.server, &spec);
218       EncodeAndAppendProxyServer("ftp", ftp_proxy.server, &spec);
219       EncodeAndAppendProxyServer("socks", socks_proxy.server, &spec);
220       if (!spec.empty())
221         proxy_proto.set_proxy_server(spec);
222       break;
223     }
224     default: {
225       NOTREACHED() << "Unrecognized proxy config mode";
226       break;
227     }
228   }
229   proxy_proto.set_proxy_bypass_list(bypass_rules.ToString());
230   return proxy_proto.SerializeToString(output);
231 }
232 
Deserialize(const std::string & input)233 bool ProxyConfigServiceImpl::ProxyConfig::Deserialize(
234     const std::string& input) {
235   em::DeviceProxySettingsProto proxy_proto;
236   if (!proxy_proto.ParseFromString(input))
237     return false;
238 
239   const std::string& mode_string(proxy_proto.proxy_mode());
240   if (mode_string == ProxyPrefs::kDirectProxyModeName) {
241     mode = MODE_DIRECT;
242   } else if (mode_string == ProxyPrefs::kAutoDetectProxyModeName) {
243     mode = MODE_AUTO_DETECT;
244   } else if (mode_string == ProxyPrefs::kPacScriptProxyModeName) {
245     mode = MODE_PAC_SCRIPT;
246     if (proxy_proto.has_proxy_pac_url())
247       automatic_proxy.pac_url = GURL(proxy_proto.proxy_pac_url());
248   } else if (mode_string == ProxyPrefs::kFixedServersProxyModeName) {
249     net::ProxyConfig::ProxyRules rules;
250     rules.ParseFromString(proxy_proto.proxy_server());
251     switch (rules.type) {
252       case net::ProxyConfig::ProxyRules::TYPE_NO_RULES:
253         return false;
254       case net::ProxyConfig::ProxyRules::TYPE_SINGLE_PROXY:
255         if (!rules.single_proxy.is_valid())
256           return false;
257         mode = MODE_SINGLE_PROXY;
258         single_proxy.server = rules.single_proxy;
259         break;
260       case net::ProxyConfig::ProxyRules::TYPE_PROXY_PER_SCHEME:
261         // Make sure we have valid server for at least one of the protocols.
262         if (!rules.proxy_for_http.is_valid() &&
263             !rules.proxy_for_https.is_valid() &&
264             !rules.proxy_for_ftp.is_valid() &&
265             !rules.fallback_proxy.is_valid()) {
266           return false;
267         }
268         mode = MODE_PROXY_PER_SCHEME;
269         if (rules.proxy_for_http.is_valid())
270           http_proxy.server = rules.proxy_for_http;
271         if (rules.proxy_for_https.is_valid())
272           https_proxy.server = rules.proxy_for_https;
273         if (rules.proxy_for_ftp.is_valid())
274           ftp_proxy.server = rules.proxy_for_ftp;
275         if (rules.fallback_proxy.is_valid())
276           socks_proxy.server = rules.fallback_proxy;
277         break;
278     }
279   } else {
280     NOTREACHED() << "Unrecognized proxy config mode";
281     return false;
282   }
283 
284   if (proxy_proto.has_proxy_bypass_list())
285     bypass_rules.ParseFromString(proxy_proto.proxy_bypass_list());
286 
287   return true;
288 }
289 
ToString() const290 std::string ProxyConfigServiceImpl::ProxyConfig::ToString() const {
291   return ProxyConfigToString(*this);
292 }
293 
294 //----------- ProxyConfigServiceImpl::ProxyConfig: private methods -------------
295 
296 // static
EncodeAndAppendProxyServer(const std::string & scheme,const net::ProxyServer & server,std::string * spec)297 void ProxyConfigServiceImpl::ProxyConfig::EncodeAndAppendProxyServer(
298     const std::string& scheme,
299     const net::ProxyServer& server,
300     std::string* spec) {
301   if (!server.is_valid())
302     return;
303 
304   if (!spec->empty())
305     *spec += ';';
306 
307   if (!scheme.empty()) {
308     *spec += scheme;
309     *spec += "=";
310   }
311   *spec += server.ToURI();
312 }
313 
314 //------------------- ProxyConfigServiceImpl: public methods -------------------
315 
ProxyConfigServiceImpl()316 ProxyConfigServiceImpl::ProxyConfigServiceImpl()
317     : can_post_task_(false),
318       config_availability_(net::ProxyConfigService::CONFIG_PENDING),
319       persist_to_device_(true),
320       persist_to_device_pending_(false) {
321   // Start async fetch of proxy config from settings persisted on device.
322   // TODO(kuan): retrieve config from policy and owner and merge them
323   bool use_default = true;
324   if (CrosLibrary::Get()->EnsureLoaded()) {
325     retrieve_property_op_ = SignedSettings::CreateRetrievePropertyOp(
326         kSettingProxyEverywhere, this);
327     if (retrieve_property_op_) {
328       retrieve_property_op_->Execute();
329       VLOG(1) << "Start retrieving proxy setting from device";
330       use_default = false;
331     } else {
332       VLOG(1) << "Fail to retrieve proxy setting from device";
333     }
334   }
335   if (use_default)
336     config_availability_ = net::ProxyConfigService::CONFIG_UNSET;
337   can_post_task_ = true;
338 }
339 
ProxyConfigServiceImpl(const ProxyConfig & init_config)340 ProxyConfigServiceImpl::ProxyConfigServiceImpl(const ProxyConfig& init_config)
341     : can_post_task_(true),
342       config_availability_(net::ProxyConfigService::CONFIG_VALID),
343       persist_to_device_(false),
344       persist_to_device_pending_(false) {
345   reference_config_ = init_config;
346   // Update the IO-accessible copy in |cached_config_| as well.
347   cached_config_ = reference_config_;
348 }
349 
~ProxyConfigServiceImpl()350 ProxyConfigServiceImpl::~ProxyConfigServiceImpl() {
351 }
352 
UIGetProxyConfig(ProxyConfig * config)353 void ProxyConfigServiceImpl::UIGetProxyConfig(ProxyConfig* config) {
354   // Should be called from UI thread.
355   CheckCurrentlyOnUIThread();
356   // Simply returns the copy on the UI thread.
357   *config = reference_config_;
358 }
359 
UISetProxyConfigToDirect()360 bool ProxyConfigServiceImpl::UISetProxyConfigToDirect() {
361   // Should be called from UI thread.
362   CheckCurrentlyOnUIThread();
363   reference_config_.mode = ProxyConfig::MODE_DIRECT;
364   OnUISetProxyConfig(persist_to_device_);
365   return true;
366 }
367 
UISetProxyConfigToAutoDetect()368 bool ProxyConfigServiceImpl::UISetProxyConfigToAutoDetect() {
369   // Should be called from UI thread.
370   CheckCurrentlyOnUIThread();
371   reference_config_.mode = ProxyConfig::MODE_AUTO_DETECT;
372   OnUISetProxyConfig(persist_to_device_);
373   return true;
374 }
375 
UISetProxyConfigToPACScript(const GURL & pac_url)376 bool ProxyConfigServiceImpl::UISetProxyConfigToPACScript(const GURL& pac_url) {
377   // Should be called from UI thread.
378   CheckCurrentlyOnUIThread();
379   reference_config_.mode = ProxyConfig::MODE_PAC_SCRIPT;
380   reference_config_.automatic_proxy.pac_url = pac_url;
381   OnUISetProxyConfig(persist_to_device_);
382   return true;
383 }
384 
UISetProxyConfigToSingleProxy(const net::ProxyServer & server)385 bool ProxyConfigServiceImpl::UISetProxyConfigToSingleProxy(
386     const net::ProxyServer& server) {
387   // Should be called from UI thread.
388   CheckCurrentlyOnUIThread();
389   reference_config_.mode = ProxyConfig::MODE_SINGLE_PROXY;
390   reference_config_.single_proxy.server = server;
391   OnUISetProxyConfig(persist_to_device_);
392   return true;
393 }
394 
UISetProxyConfigToProxyPerScheme(const std::string & scheme,const net::ProxyServer & server)395 bool ProxyConfigServiceImpl::UISetProxyConfigToProxyPerScheme(
396     const std::string& scheme, const net::ProxyServer& server) {
397   // Should be called from UI thread.
398   CheckCurrentlyOnUIThread();
399   ProxyConfig::ManualProxy* proxy = reference_config_.MapSchemeToProxy(scheme);
400   if (!proxy) {
401     NOTREACHED() << "Cannot set proxy: invalid scheme [" << scheme << "]";
402     return false;
403   }
404   reference_config_.mode = ProxyConfig::MODE_PROXY_PER_SCHEME;
405   proxy->server = server;
406   OnUISetProxyConfig(persist_to_device_);
407   return true;
408 }
409 
UISetProxyConfigBypassRules(const net::ProxyBypassRules & bypass_rules)410 bool ProxyConfigServiceImpl::UISetProxyConfigBypassRules(
411     const net::ProxyBypassRules& bypass_rules) {
412   // Should be called from UI thread.
413   CheckCurrentlyOnUIThread();
414   DCHECK(reference_config_.mode == ProxyConfig::MODE_SINGLE_PROXY ||
415          reference_config_.mode == ProxyConfig::MODE_PROXY_PER_SCHEME);
416   if (reference_config_.mode != ProxyConfig::MODE_SINGLE_PROXY &&
417       reference_config_.mode != ProxyConfig::MODE_PROXY_PER_SCHEME) {
418     VLOG(1) << "Cannot set bypass rules for proxy mode ["
419              << reference_config_.mode << "]";
420     return false;
421   }
422   reference_config_.bypass_rules = bypass_rules;
423   OnUISetProxyConfig(persist_to_device_);
424   return true;
425 }
426 
AddObserver(net::ProxyConfigService::Observer * observer)427 void ProxyConfigServiceImpl::AddObserver(
428     net::ProxyConfigService::Observer* observer) {
429   // Should be called from IO thread.
430   CheckCurrentlyOnIOThread();
431   observers_.AddObserver(observer);
432 }
433 
RemoveObserver(net::ProxyConfigService::Observer * observer)434 void ProxyConfigServiceImpl::RemoveObserver(
435     net::ProxyConfigService::Observer* observer) {
436   // Should be called from IO thread.
437   CheckCurrentlyOnIOThread();
438   observers_.RemoveObserver(observer);
439 }
440 
441 net::ProxyConfigService::ConfigAvailability
IOGetProxyConfig(net::ProxyConfig * net_config)442     ProxyConfigServiceImpl::IOGetProxyConfig(net::ProxyConfig* net_config) {
443   // Should be called from IO thread.
444   CheckCurrentlyOnIOThread();
445   if (config_availability_ == net::ProxyConfigService::CONFIG_VALID)
446     cached_config_.ToNetProxyConfig(net_config);
447 
448   return config_availability_;
449 }
450 
OnSettingsOpCompleted(SignedSettings::ReturnCode code,bool value)451 void ProxyConfigServiceImpl::OnSettingsOpCompleted(
452     SignedSettings::ReturnCode code,
453     bool value) {
454   if (SignedSettings::SUCCESS == code)
455     VLOG(1) << "Stored proxy setting to device";
456   else
457     LOG(WARNING) << "Error storing proxy setting to device";
458   store_property_op_ = NULL;
459   if (persist_to_device_pending_)
460     PersistConfigToDevice();
461 }
462 
OnSettingsOpCompleted(SignedSettings::ReturnCode code,std::string value)463 void ProxyConfigServiceImpl::OnSettingsOpCompleted(
464     SignedSettings::ReturnCode code,
465     std::string value) {
466   retrieve_property_op_ = NULL;
467   if (SignedSettings::SUCCESS == code) {
468     VLOG(1) << "Retrieved proxy setting from device, value=[" << value << "]";
469     if (reference_config_.Deserialize(value)) {
470       IOSetProxyConfig(reference_config_,
471                        net::ProxyConfigService::CONFIG_VALID);
472       return;
473     } else {
474       LOG(WARNING) << "Error deserializing device's proxy setting";
475     }
476   } else {
477     LOG(WARNING) << "Error retrieving proxy setting from device";
478   }
479 
480   // Update the configuration state on the IO thread.
481   IOSetProxyConfig(reference_config_, net::ProxyConfigService::CONFIG_UNSET);
482 }
483 
484 //------------------ ProxyConfigServiceImpl: private methods -------------------
485 
PersistConfigToDevice()486 void ProxyConfigServiceImpl::PersistConfigToDevice() {
487   DCHECK(!store_property_op_);
488   persist_to_device_pending_ = false;
489   std::string value;
490   if (!reference_config_.Serialize(&value)) {
491     LOG(WARNING) << "Error serializing proxy config";
492     return;
493   }
494   store_property_op_ = SignedSettings::CreateStorePropertyOp(
495       kSettingProxyEverywhere, value, this);
496   store_property_op_->Execute();
497   VLOG(1) << "Start storing proxy setting to device, value=" << value;
498 }
499 
OnUISetProxyConfig(bool persist_to_device)500 void ProxyConfigServiceImpl::OnUISetProxyConfig(bool persist_to_device) {
501   IOSetProxyConfig(reference_config_, net::ProxyConfigService::CONFIG_VALID);
502   if (persist_to_device && CrosLibrary::Get()->EnsureLoaded()) {
503     if (store_property_op_) {
504       persist_to_device_pending_ = true;
505       VLOG(1) << "Pending persisting proxy setting to device";
506     } else {
507       PersistConfigToDevice();
508     }
509   }
510 }
511 
IOSetProxyConfig(const ProxyConfig & new_config,net::ProxyConfigService::ConfigAvailability new_availability)512 void ProxyConfigServiceImpl::IOSetProxyConfig(
513     const ProxyConfig& new_config,
514     net::ProxyConfigService::ConfigAvailability new_availability) {
515   if (!BrowserThread::CurrentlyOn(BrowserThread::IO) && can_post_task_) {
516     // Posts a task to IO thread with the new config, so it can update
517     // |cached_config_|.
518     Task* task = NewRunnableMethod(this,
519                                    &ProxyConfigServiceImpl::IOSetProxyConfig,
520                                    new_config,
521                                    new_availability);
522     if (!BrowserThread::PostTask(BrowserThread::IO, FROM_HERE, task))
523       VLOG(1) << "Couldn't post task to IO thread to set new proxy config";
524     return;
525   }
526 
527   // Now guaranteed to be on the correct thread.
528   VLOG(1) << "Proxy configuration changed";
529   cached_config_ = new_config;
530   config_availability_ = new_availability;
531   // Notify observers of new proxy config.
532   net::ProxyConfig net_config;
533   cached_config_.ToNetProxyConfig(&net_config);
534   FOR_EACH_OBSERVER(net::ProxyConfigService::Observer, observers_,
535                     OnProxyConfigChanged(net_config, config_availability_));
536 }
537 
CheckCurrentlyOnIOThread()538 void ProxyConfigServiceImpl::CheckCurrentlyOnIOThread() {
539   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::IO));
540 }
541 
CheckCurrentlyOnUIThread()542 void ProxyConfigServiceImpl::CheckCurrentlyOnUIThread() {
543   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
544 }
545 
546 }  // namespace chromeos
547