OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 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 | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/proxy/proxy_config_service_linux.h" | 5 #include "net/proxy/proxy_config_service_linux.h" |
6 | 6 |
7 #include <errno.h> | 7 #include <errno.h> |
8 #include <fcntl.h> | 8 #include <fcntl.h> |
9 #if defined(USE_GCONF) | 9 #if defined(USE_GCONF) |
10 #include <gconf/gconf-client.h> | 10 #include <gconf/gconf-client.h> |
(...skipping 12 matching lines...) Expand all Loading... |
23 | 23 |
24 #include <map> | 24 #include <map> |
25 | 25 |
26 #include "base/bind.h" | 26 #include "base/bind.h" |
27 #include "base/compiler_specific.h" | 27 #include "base/compiler_specific.h" |
28 #include "base/environment.h" | 28 #include "base/environment.h" |
29 #include "base/file_path.h" | 29 #include "base/file_path.h" |
30 #include "base/file_util.h" | 30 #include "base/file_util.h" |
31 #include "base/logging.h" | 31 #include "base/logging.h" |
32 #include "base/message_loop.h" | 32 #include "base/message_loop.h" |
| 33 #include "base/message_loop_proxy.h" |
33 #include "base/nix/xdg_util.h" | 34 #include "base/nix/xdg_util.h" |
34 #include "base/string_number_conversions.h" | 35 #include "base/string_number_conversions.h" |
35 #include "base/string_tokenizer.h" | 36 #include "base/string_tokenizer.h" |
36 #include "base/string_util.h" | 37 #include "base/string_util.h" |
37 #include "base/threading/thread_restrictions.h" | 38 #include "base/threading/thread_restrictions.h" |
38 #include "base/timer.h" | 39 #include "base/timer.h" |
39 #include "googleurl/src/url_canon.h" | 40 #include "googleurl/src/url_canon.h" |
40 #include "net/base/net_errors.h" | 41 #include "net/base/net_errors.h" |
41 #include "net/http/http_util.h" | 42 #include "net/http/http_util.h" |
42 #include "net/proxy/proxy_config.h" | 43 #include "net/proxy/proxy_config.h" |
(...skipping 162 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
205 } | 206 } |
206 | 207 |
207 virtual ~SettingGetterImplGConf() { | 208 virtual ~SettingGetterImplGConf() { |
208 // client_ should have been released before now, from | 209 // client_ should have been released before now, from |
209 // Delegate::OnDestroy(), while running on the UI thread. However | 210 // Delegate::OnDestroy(), while running on the UI thread. However |
210 // on exiting the process, it may happen that Delegate::OnDestroy() | 211 // on exiting the process, it may happen that Delegate::OnDestroy() |
211 // task is left pending on the glib loop after the loop was quit, | 212 // task is left pending on the glib loop after the loop was quit, |
212 // and pending tasks may then be deleted without being run. | 213 // and pending tasks may then be deleted without being run. |
213 if (client_) { | 214 if (client_) { |
214 // gconf client was not cleaned up. | 215 // gconf client was not cleaned up. |
215 if (MessageLoop::current() == loop_) { | 216 if (loop_->BelongsToCurrentThread()) { |
216 // We are on the UI thread so we can clean it safely. This is | 217 // We are on the UI thread so we can clean it safely. This is |
217 // the case at least for ui_tests running under Valgrind in | 218 // the case at least for ui_tests running under Valgrind in |
218 // bug 16076. | 219 // bug 16076. |
219 VLOG(1) << "~SettingGetterImplGConf: releasing gconf client"; | 220 VLOG(1) << "~SettingGetterImplGConf: releasing gconf client"; |
220 ShutDown(); | 221 ShutDown(); |
221 } else { | 222 } else { |
222 // This is very bad! We are deleting the setting getter but we're not on | 223 // This is very bad! We are deleting the setting getter but we're not on |
223 // the UI thread. This is not supposed to happen: the setting getter is | 224 // the UI thread. This is not supposed to happen: the setting getter is |
224 // owned by the proxy config service's delegate, which is supposed to be | 225 // owned by the proxy config service's delegate, which is supposed to be |
225 // destroyed on the UI thread only. We will get change notifications to | 226 // destroyed on the UI thread only. We will get change notifications to |
226 // a deleted object if we continue here, so fail now. | 227 // a deleted object if we continue here, so fail now. |
227 LOG(FATAL) << "~SettingGetterImplGConf: deleting on wrong thread!"; | 228 LOG(FATAL) << "~SettingGetterImplGConf: deleting on wrong thread!"; |
228 } | 229 } |
229 } | 230 } |
230 DCHECK(!client_); | 231 DCHECK(!client_); |
231 } | 232 } |
232 | 233 |
233 virtual bool Init(MessageLoop* glib_default_loop, | 234 virtual bool Init(base::MessageLoopProxy* glib_default_loop, |
234 MessageLoopForIO* file_loop) OVERRIDE { | 235 MessageLoopForIO* file_loop) OVERRIDE { |
235 DCHECK(MessageLoop::current() == glib_default_loop); | 236 DCHECK(glib_default_loop->BelongsToCurrentThread()); |
236 DCHECK(!client_); | 237 DCHECK(!client_); |
237 DCHECK(!loop_); | 238 DCHECK(!loop_); |
238 loop_ = glib_default_loop; | 239 loop_ = glib_default_loop; |
239 client_ = gconf_client_get_default(); | 240 client_ = gconf_client_get_default(); |
240 if (!client_) { | 241 if (!client_) { |
241 // It's not clear whether/when this can return NULL. | 242 // It's not clear whether/when this can return NULL. |
242 LOG(ERROR) << "Unable to create a gconf client"; | 243 LOG(ERROR) << "Unable to create a gconf client"; |
243 loop_ = NULL; | 244 loop_ = NULL; |
244 return false; | 245 return false; |
245 } | 246 } |
(...skipping 18 matching lines...) Expand all Loading... |
264 g_object_unref(client_); | 265 g_object_unref(client_); |
265 client_ = NULL; | 266 client_ = NULL; |
266 loop_ = NULL; | 267 loop_ = NULL; |
267 return false; | 268 return false; |
268 } | 269 } |
269 return true; | 270 return true; |
270 } | 271 } |
271 | 272 |
272 void ShutDown() { | 273 void ShutDown() { |
273 if (client_) { | 274 if (client_) { |
274 DCHECK(MessageLoop::current() == loop_); | 275 DCHECK(loop_->BelongsToCurrentThread()); |
275 // We must explicitly disable gconf notifications here, because the gconf | 276 // We must explicitly disable gconf notifications here, because the gconf |
276 // client will be shared between all setting getters, and they do not all | 277 // client will be shared between all setting getters, and they do not all |
277 // have the same lifetimes. (For instance, incognito sessions get their | 278 // have the same lifetimes. (For instance, incognito sessions get their |
278 // own, which is destroyed when the session ends.) | 279 // own, which is destroyed when the session ends.) |
279 gconf_client_notify_remove(client_, system_http_proxy_id_); | 280 gconf_client_notify_remove(client_, system_http_proxy_id_); |
280 gconf_client_notify_remove(client_, system_proxy_id_); | 281 gconf_client_notify_remove(client_, system_proxy_id_); |
281 gconf_client_remove_dir(client_, "/system/http_proxy", NULL); | 282 gconf_client_remove_dir(client_, "/system/http_proxy", NULL); |
282 gconf_client_remove_dir(client_, "/system/proxy", NULL); | 283 gconf_client_remove_dir(client_, "/system/proxy", NULL); |
283 g_object_unref(client_); | 284 g_object_unref(client_); |
284 client_ = NULL; | 285 client_ = NULL; |
285 loop_ = NULL; | 286 loop_ = NULL; |
286 } | 287 } |
287 } | 288 } |
288 | 289 |
289 bool SetUpNotifications(ProxyConfigServiceLinux::Delegate* delegate) { | 290 bool SetUpNotifications(ProxyConfigServiceLinux::Delegate* delegate) { |
290 DCHECK(client_); | 291 DCHECK(client_); |
291 DCHECK(MessageLoop::current() == loop_); | 292 DCHECK(loop_->BelongsToCurrentThread()); |
292 GError* error = NULL; | 293 GError* error = NULL; |
293 notify_delegate_ = delegate; | 294 notify_delegate_ = delegate; |
294 // We have to keep track of the IDs returned by gconf_client_notify_add() so | 295 // We have to keep track of the IDs returned by gconf_client_notify_add() so |
295 // that we can remove them in ShutDown(). (Otherwise, notifications will be | 296 // that we can remove them in ShutDown(). (Otherwise, notifications will be |
296 // delivered to this object after it is deleted, which is bad, m'kay?) | 297 // delivered to this object after it is deleted, which is bad, m'kay?) |
297 system_proxy_id_ = gconf_client_notify_add( | 298 system_proxy_id_ = gconf_client_notify_add( |
298 client_, "/system/proxy", | 299 client_, "/system/proxy", |
299 OnGConfChangeNotification, this, | 300 OnGConfChangeNotification, this, |
300 NULL, &error); | 301 NULL, &error); |
301 if (error == NULL) { | 302 if (error == NULL) { |
302 system_http_proxy_id_ = gconf_client_notify_add( | 303 system_http_proxy_id_ = gconf_client_notify_add( |
303 client_, "/system/http_proxy", | 304 client_, "/system/http_proxy", |
304 OnGConfChangeNotification, this, | 305 OnGConfChangeNotification, this, |
305 NULL, &error); | 306 NULL, &error); |
306 } | 307 } |
307 if (error != NULL) { | 308 if (error != NULL) { |
308 LOG(ERROR) << "Error requesting gconf notifications: " << error->message; | 309 LOG(ERROR) << "Error requesting gconf notifications: " << error->message; |
309 g_error_free(error); | 310 g_error_free(error); |
310 ShutDown(); | 311 ShutDown(); |
311 return false; | 312 return false; |
312 } | 313 } |
313 // Simulate a change to avoid possibly losing updates before this point. | 314 // Simulate a change to avoid possibly losing updates before this point. |
314 OnChangeNotification(); | 315 OnChangeNotification(); |
315 return true; | 316 return true; |
316 } | 317 } |
317 | 318 |
318 virtual MessageLoop* GetNotificationLoop() OVERRIDE { | 319 virtual base::MessageLoopProxy* GetNotificationLoop() OVERRIDE { |
319 return loop_; | 320 return loop_; |
320 } | 321 } |
321 | 322 |
322 virtual const char* GetDataSource() OVERRIDE { | 323 virtual const char* GetDataSource() OVERRIDE { |
323 return "gconf"; | 324 return "gconf"; |
324 } | 325 } |
325 | 326 |
326 virtual bool GetString(StringSetting key, std::string* result) OVERRIDE { | 327 virtual bool GetString(StringSetting key, std::string* result) OVERRIDE { |
327 switch (key) { | 328 switch (key) { |
328 case PROXY_MODE: | 329 case PROXY_MODE: |
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
378 return false; | 379 return false; |
379 } | 380 } |
380 | 381 |
381 virtual bool MatchHostsUsingSuffixMatching() OVERRIDE { | 382 virtual bool MatchHostsUsingSuffixMatching() OVERRIDE { |
382 return false; | 383 return false; |
383 } | 384 } |
384 | 385 |
385 private: | 386 private: |
386 bool GetStringByPath(const char* key, std::string* result) { | 387 bool GetStringByPath(const char* key, std::string* result) { |
387 DCHECK(client_); | 388 DCHECK(client_); |
388 DCHECK(MessageLoop::current() == loop_); | 389 DCHECK(loop_->BelongsToCurrentThread()); |
389 GError* error = NULL; | 390 GError* error = NULL; |
390 gchar* value = gconf_client_get_string(client_, key, &error); | 391 gchar* value = gconf_client_get_string(client_, key, &error); |
391 if (HandleGError(error, key)) | 392 if (HandleGError(error, key)) |
392 return false; | 393 return false; |
393 if (!value) | 394 if (!value) |
394 return false; | 395 return false; |
395 *result = value; | 396 *result = value; |
396 g_free(value); | 397 g_free(value); |
397 return true; | 398 return true; |
398 } | 399 } |
399 bool GetBoolByPath(const char* key, bool* result) { | 400 bool GetBoolByPath(const char* key, bool* result) { |
400 DCHECK(client_); | 401 DCHECK(client_); |
401 DCHECK(MessageLoop::current() == loop_); | 402 DCHECK(loop_->BelongsToCurrentThread()); |
402 GError* error = NULL; | 403 GError* error = NULL; |
403 // We want to distinguish unset values from values defaulting to | 404 // We want to distinguish unset values from values defaulting to |
404 // false. For that we need to use the type-generic | 405 // false. For that we need to use the type-generic |
405 // gconf_client_get() rather than gconf_client_get_bool(). | 406 // gconf_client_get() rather than gconf_client_get_bool(). |
406 GConfValue* gconf_value = gconf_client_get(client_, key, &error); | 407 GConfValue* gconf_value = gconf_client_get(client_, key, &error); |
407 if (HandleGError(error, key)) | 408 if (HandleGError(error, key)) |
408 return false; | 409 return false; |
409 if (!gconf_value) { | 410 if (!gconf_value) { |
410 // Unset. | 411 // Unset. |
411 return false; | 412 return false; |
412 } | 413 } |
413 if (gconf_value->type != GCONF_VALUE_BOOL) { | 414 if (gconf_value->type != GCONF_VALUE_BOOL) { |
414 gconf_value_free(gconf_value); | 415 gconf_value_free(gconf_value); |
415 return false; | 416 return false; |
416 } | 417 } |
417 gboolean bool_value = gconf_value_get_bool(gconf_value); | 418 gboolean bool_value = gconf_value_get_bool(gconf_value); |
418 *result = static_cast<bool>(bool_value); | 419 *result = static_cast<bool>(bool_value); |
419 gconf_value_free(gconf_value); | 420 gconf_value_free(gconf_value); |
420 return true; | 421 return true; |
421 } | 422 } |
422 bool GetIntByPath(const char* key, int* result) { | 423 bool GetIntByPath(const char* key, int* result) { |
423 DCHECK(client_); | 424 DCHECK(client_); |
424 DCHECK(MessageLoop::current() == loop_); | 425 DCHECK(loop_->BelongsToCurrentThread()); |
425 GError* error = NULL; | 426 GError* error = NULL; |
426 int value = gconf_client_get_int(client_, key, &error); | 427 int value = gconf_client_get_int(client_, key, &error); |
427 if (HandleGError(error, key)) | 428 if (HandleGError(error, key)) |
428 return false; | 429 return false; |
429 // We don't bother to distinguish an unset value because callers | 430 // We don't bother to distinguish an unset value because callers |
430 // don't care. 0 is returned if unset. | 431 // don't care. 0 is returned if unset. |
431 *result = value; | 432 *result = value; |
432 return true; | 433 return true; |
433 } | 434 } |
434 bool GetStringListByPath(const char* key, std::vector<std::string>* result) { | 435 bool GetStringListByPath(const char* key, std::vector<std::string>* result) { |
435 DCHECK(client_); | 436 DCHECK(client_); |
436 DCHECK(MessageLoop::current() == loop_); | 437 DCHECK(loop_->BelongsToCurrentThread()); |
437 GError* error = NULL; | 438 GError* error = NULL; |
438 GSList* list = gconf_client_get_list(client_, key, | 439 GSList* list = gconf_client_get_list(client_, key, |
439 GCONF_VALUE_STRING, &error); | 440 GCONF_VALUE_STRING, &error); |
440 if (HandleGError(error, key)) | 441 if (HandleGError(error, key)) |
441 return false; | 442 return false; |
442 if (!list) | 443 if (!list) |
443 return false; | 444 return false; |
444 for (GSList *it = list; it; it = it->next) { | 445 for (GSList *it = list; it; it = it->next) { |
445 result->push_back(static_cast<char*>(it->data)); | 446 result->push_back(static_cast<char*>(it->data)); |
446 g_free(it->data); | 447 g_free(it->data); |
447 } | 448 } |
448 g_slist_free(list); | 449 g_slist_free(list); |
449 return true; | 450 return true; |
450 } | 451 } |
451 | 452 |
452 // Logs and frees a glib error. Returns false if there was no error | 453 // Logs and frees a glib error. Returns false if there was no error |
453 // (error is NULL). | 454 // (error is NULL). |
454 bool HandleGError(GError* error, const char* key) { | 455 bool HandleGError(GError* error, const char* key) { |
455 if (error != NULL) { | 456 if (error != NULL) { |
456 LOG(ERROR) << "Error getting gconf value for " << key | 457 LOG(ERROR) << "Error getting gconf value for " << key |
457 << ": " << error->message; | 458 << ": " << error->message; |
458 g_error_free(error); | 459 g_error_free(error); |
459 return true; | 460 return true; |
460 } | 461 } |
461 return false; | 462 return false; |
462 } | 463 } |
463 | 464 |
464 // This is the callback from the debounce timer. | 465 // This is the callback from the debounce timer. |
465 void OnDebouncedNotification() { | 466 void OnDebouncedNotification() { |
466 DCHECK(MessageLoop::current() == loop_); | 467 DCHECK(loop_->BelongsToCurrentThread()); |
467 CHECK(notify_delegate_); | 468 CHECK(notify_delegate_); |
468 // Forward to a method on the proxy config service delegate object. | 469 // Forward to a method on the proxy config service delegate object. |
469 notify_delegate_->OnCheckProxyConfigSettings(); | 470 notify_delegate_->OnCheckProxyConfigSettings(); |
470 } | 471 } |
471 | 472 |
472 void OnChangeNotification() { | 473 void OnChangeNotification() { |
473 // We don't use Reset() because the timer may not yet be running. | 474 // We don't use Reset() because the timer may not yet be running. |
474 // (In that case Stop() is a no-op.) | 475 // (In that case Stop() is a no-op.) |
475 debounce_timer_.Stop(); | 476 debounce_timer_.Stop(); |
476 debounce_timer_.Start(FROM_HERE, | 477 debounce_timer_.Start(FROM_HERE, |
(...skipping 17 matching lines...) Expand all Loading... |
494 // will need in order to later call gconf_client_notify_remove(). | 495 // will need in order to later call gconf_client_notify_remove(). |
495 guint system_proxy_id_; | 496 guint system_proxy_id_; |
496 guint system_http_proxy_id_; | 497 guint system_http_proxy_id_; |
497 | 498 |
498 ProxyConfigServiceLinux::Delegate* notify_delegate_; | 499 ProxyConfigServiceLinux::Delegate* notify_delegate_; |
499 base::OneShotTimer<SettingGetterImplGConf> debounce_timer_; | 500 base::OneShotTimer<SettingGetterImplGConf> debounce_timer_; |
500 | 501 |
501 // Message loop of the thread that we make gconf calls on. It should | 502 // Message loop of the thread that we make gconf calls on. It should |
502 // be the UI thread and all our methods should be called on this | 503 // be the UI thread and all our methods should be called on this |
503 // thread. Only for assertions. | 504 // thread. Only for assertions. |
504 MessageLoop* loop_; | 505 scoped_refptr<base::MessageLoopProxy> loop_; |
505 | 506 |
506 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGConf); | 507 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGConf); |
507 }; | 508 }; |
508 #endif // defined(USE_GCONF) | 509 #endif // defined(USE_GCONF) |
509 | 510 |
510 #if defined(USE_GIO) | 511 #if defined(USE_GIO) |
511 // This setting getter uses gsettings, as used in most GNOME 3 desktops. | 512 // This setting getter uses gsettings, as used in most GNOME 3 desktops. |
512 class SettingGetterImplGSettings | 513 class SettingGetterImplGSettings |
513 : public ProxyConfigServiceLinux::SettingGetter { | 514 : public ProxyConfigServiceLinux::SettingGetter { |
514 public: | 515 public: |
(...skipping 19 matching lines...) Expand all Loading... |
534 | 535 |
535 virtual ~SettingGetterImplGSettings() { | 536 virtual ~SettingGetterImplGSettings() { |
536 // client_ should have been released before now, from | 537 // client_ should have been released before now, from |
537 // Delegate::OnDestroy(), while running on the UI thread. However | 538 // Delegate::OnDestroy(), while running on the UI thread. However |
538 // on exiting the process, it may happen that | 539 // on exiting the process, it may happen that |
539 // Delegate::OnDestroy() task is left pending on the glib loop | 540 // Delegate::OnDestroy() task is left pending on the glib loop |
540 // after the loop was quit, and pending tasks may then be deleted | 541 // after the loop was quit, and pending tasks may then be deleted |
541 // without being run. | 542 // without being run. |
542 if (client_) { | 543 if (client_) { |
543 // gconf client was not cleaned up. | 544 // gconf client was not cleaned up. |
544 if (MessageLoop::current() == loop_) { | 545 if (loop_->BelongsToCurrentThread()) { |
545 // We are on the UI thread so we can clean it safely. This is | 546 // We are on the UI thread so we can clean it safely. This is |
546 // the case at least for ui_tests running under Valgrind in | 547 // the case at least for ui_tests running under Valgrind in |
547 // bug 16076. | 548 // bug 16076. |
548 VLOG(1) << "~SettingGetterImplGSettings: releasing gsettings client"; | 549 VLOG(1) << "~SettingGetterImplGSettings: releasing gsettings client"; |
549 ShutDown(); | 550 ShutDown(); |
550 } else { | 551 } else { |
551 LOG(WARNING) << "~SettingGetterImplGSettings: leaking gsettings client"; | 552 LOG(WARNING) << "~SettingGetterImplGSettings: leaking gsettings client"; |
552 client_ = NULL; | 553 client_ = NULL; |
553 } | 554 } |
554 } | 555 } |
(...skipping 12 matching lines...) Expand all Loading... |
567 if (strcmp(schema_name, static_cast<const char*>(*schemas)) == 0) | 568 if (strcmp(schema_name, static_cast<const char*>(*schemas)) == 0) |
568 return true; | 569 return true; |
569 schemas++; | 570 schemas++; |
570 } | 571 } |
571 return false; | 572 return false; |
572 } | 573 } |
573 | 574 |
574 // LoadAndCheckVersion() must be called *before* Init()! | 575 // LoadAndCheckVersion() must be called *before* Init()! |
575 bool LoadAndCheckVersion(base::Environment* env); | 576 bool LoadAndCheckVersion(base::Environment* env); |
576 | 577 |
577 virtual bool Init(MessageLoop* glib_default_loop, | 578 virtual bool Init(base::MessageLoopProxy* glib_default_loop, |
578 MessageLoopForIO* file_loop) OVERRIDE { | 579 MessageLoopForIO* file_loop) OVERRIDE { |
579 DCHECK(MessageLoop::current() == glib_default_loop); | 580 DCHECK(glib_default_loop->BelongsToCurrentThread()); |
580 DCHECK(!client_); | 581 DCHECK(!client_); |
581 DCHECK(!loop_); | 582 DCHECK(!loop_); |
582 | 583 |
583 if (!SchemaExists("org.gnome.system.proxy") || | 584 if (!SchemaExists("org.gnome.system.proxy") || |
584 !(client_ = g_settings_new("org.gnome.system.proxy"))) { | 585 !(client_ = g_settings_new("org.gnome.system.proxy"))) { |
585 // It's not clear whether/when this can return NULL. | 586 // It's not clear whether/when this can return NULL. |
586 LOG(ERROR) << "Unable to create a gsettings client"; | 587 LOG(ERROR) << "Unable to create a gsettings client"; |
587 return false; | 588 return false; |
588 } | 589 } |
589 loop_ = glib_default_loop; | 590 loop_ = glib_default_loop; |
590 // We assume these all work if the above call worked. | 591 // We assume these all work if the above call worked. |
591 http_client_ = g_settings_get_child(client_, "http"); | 592 http_client_ = g_settings_get_child(client_, "http"); |
592 https_client_ = g_settings_get_child(client_, "https"); | 593 https_client_ = g_settings_get_child(client_, "https"); |
593 ftp_client_ = g_settings_get_child(client_, "ftp"); | 594 ftp_client_ = g_settings_get_child(client_, "ftp"); |
594 socks_client_ = g_settings_get_child(client_, "socks"); | 595 socks_client_ = g_settings_get_child(client_, "socks"); |
595 DCHECK(http_client_ && https_client_ && ftp_client_ && socks_client_); | 596 DCHECK(http_client_ && https_client_ && ftp_client_ && socks_client_); |
596 return true; | 597 return true; |
597 } | 598 } |
598 | 599 |
599 void ShutDown() { | 600 void ShutDown() { |
600 if (client_) { | 601 if (client_) { |
601 DCHECK(MessageLoop::current() == loop_); | 602 DCHECK(loop_->BelongsToCurrentThread()); |
602 // This also disables gsettings notifications. | 603 // This also disables gsettings notifications. |
603 g_object_unref(socks_client_); | 604 g_object_unref(socks_client_); |
604 g_object_unref(ftp_client_); | 605 g_object_unref(ftp_client_); |
605 g_object_unref(https_client_); | 606 g_object_unref(https_client_); |
606 g_object_unref(http_client_); | 607 g_object_unref(http_client_); |
607 g_object_unref(client_); | 608 g_object_unref(client_); |
608 // We only need to null client_ because it's the only one that we check. | 609 // We only need to null client_ because it's the only one that we check. |
609 client_ = NULL; | 610 client_ = NULL; |
610 loop_ = NULL; | 611 loop_ = NULL; |
611 } | 612 } |
612 } | 613 } |
613 | 614 |
614 bool SetUpNotifications(ProxyConfigServiceLinux::Delegate* delegate) { | 615 bool SetUpNotifications(ProxyConfigServiceLinux::Delegate* delegate) { |
615 DCHECK(client_); | 616 DCHECK(client_); |
616 DCHECK(MessageLoop::current() == loop_); | 617 DCHECK(loop_->BelongsToCurrentThread()); |
617 notify_delegate_ = delegate; | 618 notify_delegate_ = delegate; |
618 // We could watch for the change-event signal instead of changed, but | 619 // We could watch for the change-event signal instead of changed, but |
619 // since we have to watch more than one object, we'd still have to | 620 // since we have to watch more than one object, we'd still have to |
620 // debounce change notifications. This is conceptually simpler. | 621 // debounce change notifications. This is conceptually simpler. |
621 g_signal_connect(G_OBJECT(client_), "changed", | 622 g_signal_connect(G_OBJECT(client_), "changed", |
622 G_CALLBACK(OnGSettingsChangeNotification), this); | 623 G_CALLBACK(OnGSettingsChangeNotification), this); |
623 g_signal_connect(G_OBJECT(http_client_), "changed", | 624 g_signal_connect(G_OBJECT(http_client_), "changed", |
624 G_CALLBACK(OnGSettingsChangeNotification), this); | 625 G_CALLBACK(OnGSettingsChangeNotification), this); |
625 g_signal_connect(G_OBJECT(https_client_), "changed", | 626 g_signal_connect(G_OBJECT(https_client_), "changed", |
626 G_CALLBACK(OnGSettingsChangeNotification), this); | 627 G_CALLBACK(OnGSettingsChangeNotification), this); |
627 g_signal_connect(G_OBJECT(ftp_client_), "changed", | 628 g_signal_connect(G_OBJECT(ftp_client_), "changed", |
628 G_CALLBACK(OnGSettingsChangeNotification), this); | 629 G_CALLBACK(OnGSettingsChangeNotification), this); |
629 g_signal_connect(G_OBJECT(socks_client_), "changed", | 630 g_signal_connect(G_OBJECT(socks_client_), "changed", |
630 G_CALLBACK(OnGSettingsChangeNotification), this); | 631 G_CALLBACK(OnGSettingsChangeNotification), this); |
631 // Simulate a change to avoid possibly losing updates before this point. | 632 // Simulate a change to avoid possibly losing updates before this point. |
632 OnChangeNotification(); | 633 OnChangeNotification(); |
633 return true; | 634 return true; |
634 } | 635 } |
635 | 636 |
636 virtual MessageLoop* GetNotificationLoop() OVERRIDE { | 637 virtual base::MessageLoopProxy* GetNotificationLoop() OVERRIDE { |
637 return loop_; | 638 return loop_; |
638 } | 639 } |
639 | 640 |
640 virtual const char* GetDataSource() OVERRIDE { | 641 virtual const char* GetDataSource() OVERRIDE { |
641 return "gsettings"; | 642 return "gsettings"; |
642 } | 643 } |
643 | 644 |
644 virtual bool GetString(StringSetting key, std::string* result) OVERRIDE { | 645 virtual bool GetString(StringSetting key, std::string* result) OVERRIDE { |
645 DCHECK(client_); | 646 DCHECK(client_); |
646 switch (key) { | 647 switch (key) { |
(...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
737 if (error) { | 738 if (error) { |
738 VLOG(1) << "Unable to load symbol " << name << ": " << error; | 739 VLOG(1) << "Unable to load symbol " << name << ": " << error; |
739 return false; | 740 return false; |
740 } | 741 } |
741 return true; | 742 return true; |
742 } | 743 } |
743 #endif // defined(DLOPEN_GSETTINGS) | 744 #endif // defined(DLOPEN_GSETTINGS) |
744 | 745 |
745 bool GetStringByPath(GSettings* client, const char* key, | 746 bool GetStringByPath(GSettings* client, const char* key, |
746 std::string* result) { | 747 std::string* result) { |
747 DCHECK(MessageLoop::current() == loop_); | 748 DCHECK(loop_->BelongsToCurrentThread()); |
748 gchar* value = g_settings_get_string(client, key); | 749 gchar* value = g_settings_get_string(client, key); |
749 if (!value) | 750 if (!value) |
750 return false; | 751 return false; |
751 *result = value; | 752 *result = value; |
752 g_free(value); | 753 g_free(value); |
753 return true; | 754 return true; |
754 } | 755 } |
755 bool GetBoolByPath(GSettings* client, const char* key, bool* result) { | 756 bool GetBoolByPath(GSettings* client, const char* key, bool* result) { |
756 DCHECK(MessageLoop::current() == loop_); | 757 DCHECK(loop_->BelongsToCurrentThread()); |
757 *result = static_cast<bool>(g_settings_get_boolean(client, key)); | 758 *result = static_cast<bool>(g_settings_get_boolean(client, key)); |
758 return true; | 759 return true; |
759 } | 760 } |
760 bool GetIntByPath(GSettings* client, const char* key, int* result) { | 761 bool GetIntByPath(GSettings* client, const char* key, int* result) { |
761 DCHECK(MessageLoop::current() == loop_); | 762 DCHECK(loop_->BelongsToCurrentThread()); |
762 *result = g_settings_get_int(client, key); | 763 *result = g_settings_get_int(client, key); |
763 return true; | 764 return true; |
764 } | 765 } |
765 bool GetStringListByPath(GSettings* client, const char* key, | 766 bool GetStringListByPath(GSettings* client, const char* key, |
766 std::vector<std::string>* result) { | 767 std::vector<std::string>* result) { |
767 DCHECK(MessageLoop::current() == loop_); | 768 DCHECK(loop_->BelongsToCurrentThread()); |
768 gchar** list = g_settings_get_strv(client, key); | 769 gchar** list = g_settings_get_strv(client, key); |
769 if (!list) | 770 if (!list) |
770 return false; | 771 return false; |
771 for (size_t i = 0; list[i]; ++i) { | 772 for (size_t i = 0; list[i]; ++i) { |
772 result->push_back(static_cast<char*>(list[i])); | 773 result->push_back(static_cast<char*>(list[i])); |
773 g_free(list[i]); | 774 g_free(list[i]); |
774 } | 775 } |
775 g_free(list); | 776 g_free(list); |
776 return true; | 777 return true; |
777 } | 778 } |
778 | 779 |
779 // This is the callback from the debounce timer. | 780 // This is the callback from the debounce timer. |
780 void OnDebouncedNotification() { | 781 void OnDebouncedNotification() { |
781 DCHECK(MessageLoop::current() == loop_); | 782 DCHECK(loop_->BelongsToCurrentThread()); |
782 CHECK(notify_delegate_); | 783 CHECK(notify_delegate_); |
783 // Forward to a method on the proxy config service delegate object. | 784 // Forward to a method on the proxy config service delegate object. |
784 notify_delegate_->OnCheckProxyConfigSettings(); | 785 notify_delegate_->OnCheckProxyConfigSettings(); |
785 } | 786 } |
786 | 787 |
787 void OnChangeNotification() { | 788 void OnChangeNotification() { |
788 // We don't use Reset() because the timer may not yet be running. | 789 // We don't use Reset() because the timer may not yet be running. |
789 // (In that case Stop() is a no-op.) | 790 // (In that case Stop() is a no-op.) |
790 debounce_timer_.Stop(); | 791 debounce_timer_.Stop(); |
791 debounce_timer_.Start(FROM_HERE, | 792 debounce_timer_.Start(FROM_HERE, |
(...skipping 15 matching lines...) Expand all Loading... |
807 GSettings* http_client_; | 808 GSettings* http_client_; |
808 GSettings* https_client_; | 809 GSettings* https_client_; |
809 GSettings* ftp_client_; | 810 GSettings* ftp_client_; |
810 GSettings* socks_client_; | 811 GSettings* socks_client_; |
811 ProxyConfigServiceLinux::Delegate* notify_delegate_; | 812 ProxyConfigServiceLinux::Delegate* notify_delegate_; |
812 base::OneShotTimer<SettingGetterImplGSettings> debounce_timer_; | 813 base::OneShotTimer<SettingGetterImplGSettings> debounce_timer_; |
813 | 814 |
814 // Message loop of the thread that we make gsettings calls on. It should | 815 // Message loop of the thread that we make gsettings calls on. It should |
815 // be the UI thread and all our methods should be called on this | 816 // be the UI thread and all our methods should be called on this |
816 // thread. Only for assertions. | 817 // thread. Only for assertions. |
817 MessageLoop* loop_; | 818 scoped_refptr<base::MessageLoopProxy> loop_; |
818 | 819 |
819 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGSettings); | 820 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGSettings); |
820 }; | 821 }; |
821 | 822 |
822 bool SettingGetterImplGSettings::LoadAndCheckVersion( | 823 bool SettingGetterImplGSettings::LoadAndCheckVersion( |
823 base::Environment* env) { | 824 base::Environment* env) { |
824 // LoadAndCheckVersion() must be called *before* Init()! | 825 // LoadAndCheckVersion() must be called *before* Init()! |
825 DCHECK(!client_); | 826 DCHECK(!client_); |
826 | 827 |
827 // The APIs to query gsettings were introduced after the minimum glib | 828 // The APIs to query gsettings were introduced after the minimum glib |
(...skipping 143 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
971 // on exiting the process, it may happen that Delegate::OnDestroy() | 972 // on exiting the process, it may happen that Delegate::OnDestroy() |
972 // task is left pending on the file loop after the loop was quit, | 973 // task is left pending on the file loop after the loop was quit, |
973 // and pending tasks may then be deleted without being run. | 974 // and pending tasks may then be deleted without being run. |
974 // Here in the KDE version, we can safely close the file descriptor | 975 // Here in the KDE version, we can safely close the file descriptor |
975 // anyway. (Not that it really matters; the process is exiting.) | 976 // anyway. (Not that it really matters; the process is exiting.) |
976 if (inotify_fd_ >= 0) | 977 if (inotify_fd_ >= 0) |
977 ShutDown(); | 978 ShutDown(); |
978 DCHECK(inotify_fd_ < 0); | 979 DCHECK(inotify_fd_ < 0); |
979 } | 980 } |
980 | 981 |
981 virtual bool Init(MessageLoop* glib_default_loop, | 982 virtual bool Init(base::MessageLoopProxy* glib_default_loop, |
982 MessageLoopForIO* file_loop) OVERRIDE { | 983 MessageLoopForIO* file_loop) OVERRIDE { |
983 // This has to be called on the UI thread (http://crbug.com/69057). | 984 // This has to be called on the UI thread (http://crbug.com/69057). |
984 base::ThreadRestrictions::ScopedAllowIO allow_io; | 985 base::ThreadRestrictions::ScopedAllowIO allow_io; |
985 DCHECK(inotify_fd_ < 0); | 986 DCHECK(inotify_fd_ < 0); |
986 inotify_fd_ = inotify_init(); | 987 inotify_fd_ = inotify_init(); |
987 if (inotify_fd_ < 0) { | 988 if (inotify_fd_ < 0) { |
988 PLOG(ERROR) << "inotify_init failed"; | 989 PLOG(ERROR) << "inotify_init failed"; |
989 return false; | 990 return false; |
990 } | 991 } |
991 int flags = fcntl(inotify_fd_, F_GETFL); | 992 int flags = fcntl(inotify_fd_, F_GETFL); |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1024 return false; | 1025 return false; |
1025 notify_delegate_ = delegate; | 1026 notify_delegate_ = delegate; |
1026 if (!file_loop_->WatchFileDescriptor(inotify_fd_, true, | 1027 if (!file_loop_->WatchFileDescriptor(inotify_fd_, true, |
1027 MessageLoopForIO::WATCH_READ, &inotify_watcher_, this)) | 1028 MessageLoopForIO::WATCH_READ, &inotify_watcher_, this)) |
1028 return false; | 1029 return false; |
1029 // Simulate a change to avoid possibly losing updates before this point. | 1030 // Simulate a change to avoid possibly losing updates before this point. |
1030 OnChangeNotification(); | 1031 OnChangeNotification(); |
1031 return true; | 1032 return true; |
1032 } | 1033 } |
1033 | 1034 |
1034 virtual MessageLoop* GetNotificationLoop() OVERRIDE { | 1035 virtual base::MessageLoopProxy* GetNotificationLoop() OVERRIDE { |
1035 return file_loop_; | 1036 return file_loop_->message_loop_proxy(); |
1036 } | 1037 } |
1037 | 1038 |
1038 // Implement base::MessagePumpLibevent::Watcher. | 1039 // Implement base::MessagePumpLibevent::Watcher. |
1039 void OnFileCanReadWithoutBlocking(int fd) { | 1040 void OnFileCanReadWithoutBlocking(int fd) { |
1040 DCHECK_EQ(fd, inotify_fd_); | 1041 DCHECK_EQ(fd, inotify_fd_); |
1041 DCHECK(MessageLoop::current() == file_loop_); | 1042 DCHECK(MessageLoop::current() == file_loop_); |
1042 OnChangeNotification(); | 1043 OnChangeNotification(); |
1043 } | 1044 } |
1044 void OnFileCanWriteWithoutBlocking(int fd) { | 1045 void OnFileCanWriteWithoutBlocking(int fd) { |
1045 NOTREACHED(); | 1046 NOTREACHED(); |
(...skipping 542 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1588 } | 1589 } |
1589 } | 1590 } |
1590 | 1591 |
1591 ProxyConfigServiceLinux::Delegate::Delegate( | 1592 ProxyConfigServiceLinux::Delegate::Delegate( |
1592 base::Environment* env_var_getter, SettingGetter* setting_getter) | 1593 base::Environment* env_var_getter, SettingGetter* setting_getter) |
1593 : env_var_getter_(env_var_getter), setting_getter_(setting_getter), | 1594 : env_var_getter_(env_var_getter), setting_getter_(setting_getter), |
1594 glib_default_loop_(NULL), io_loop_(NULL) { | 1595 glib_default_loop_(NULL), io_loop_(NULL) { |
1595 } | 1596 } |
1596 | 1597 |
1597 void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig( | 1598 void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig( |
1598 MessageLoop* glib_default_loop, MessageLoop* io_loop, | 1599 base::MessageLoopProxy* glib_default_loop, |
| 1600 base::MessageLoopProxy* io_loop, |
1599 MessageLoopForIO* file_loop) { | 1601 MessageLoopForIO* file_loop) { |
1600 // We should be running on the default glib main loop thread right | 1602 // We should be running on the default glib main loop thread right |
1601 // now. gconf can only be accessed from this thread. | 1603 // now. gconf can only be accessed from this thread. |
1602 DCHECK(MessageLoop::current() == glib_default_loop); | 1604 DCHECK(glib_default_loop->BelongsToCurrentThread()); |
1603 glib_default_loop_ = glib_default_loop; | 1605 glib_default_loop_ = glib_default_loop; |
1604 io_loop_ = io_loop; | 1606 io_loop_ = io_loop; |
1605 | 1607 |
1606 // If we are passed a NULL io_loop or file_loop, then we don't set up | 1608 // If we are passed a NULL io_loop or file_loop, then we don't set up |
1607 // proxy setting change notifications. This should not be the usual | 1609 // proxy setting change notifications. This should not be the usual |
1608 // case but is intended to simplify test setups. | 1610 // case but is intended to simplify test setups. |
1609 if (!io_loop_ || !file_loop) | 1611 if (!io_loop_ || !file_loop) |
1610 VLOG(1) << "Monitoring of proxy setting changes is disabled"; | 1612 VLOG(1) << "Monitoring of proxy setting changes is disabled"; |
1611 | 1613 |
1612 // Fetch and cache the current proxy config. The config is left in | 1614 // Fetch and cache the current proxy config. The config is left in |
(...skipping 28 matching lines...) Expand all Loading... |
1641 reference_config_.set_id(1); // Mark it as valid. | 1643 reference_config_.set_id(1); // Mark it as valid. |
1642 | 1644 |
1643 // We only set up notifications if we have IO and file loops available. | 1645 // We only set up notifications if we have IO and file loops available. |
1644 // We do this after getting the initial configuration so that we don't have | 1646 // We do this after getting the initial configuration so that we don't have |
1645 // to worry about cancelling it if the initial fetch above fails. Note that | 1647 // to worry about cancelling it if the initial fetch above fails. Note that |
1646 // setting up notifications has the side effect of simulating a change, so | 1648 // setting up notifications has the side effect of simulating a change, so |
1647 // that we won't lose any updates that may have happened after the initial | 1649 // that we won't lose any updates that may have happened after the initial |
1648 // fetch and before setting up notifications. We'll detect the common case | 1650 // fetch and before setting up notifications. We'll detect the common case |
1649 // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it. | 1651 // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it. |
1650 if (io_loop && file_loop) { | 1652 if (io_loop && file_loop) { |
1651 MessageLoop* required_loop = setting_getter_->GetNotificationLoop(); | 1653 scoped_refptr<base::MessageLoopProxy> required_loop = |
1652 if (!required_loop || MessageLoop::current() == required_loop) { | 1654 setting_getter_->GetNotificationLoop(); |
| 1655 if (!required_loop || required_loop->BelongsToCurrentThread()) { |
1653 // In this case we are already on an acceptable thread. | 1656 // In this case we are already on an acceptable thread. |
1654 SetUpNotifications(); | 1657 SetUpNotifications(); |
1655 } else { | 1658 } else { |
1656 // Post a task to set up notifications. We don't wait for success. | 1659 // Post a task to set up notifications. We don't wait for success. |
1657 required_loop->PostTask(FROM_HERE, base::Bind( | 1660 required_loop->PostTask(FROM_HERE, base::Bind( |
1658 &ProxyConfigServiceLinux::Delegate::SetUpNotifications, this)); | 1661 &ProxyConfigServiceLinux::Delegate::SetUpNotifications, this)); |
1659 } | 1662 } |
1660 } | 1663 } |
1661 } | 1664 } |
1662 | 1665 |
1663 if (!got_config) { | 1666 if (!got_config) { |
1664 // We fall back on environment variables. | 1667 // We fall back on environment variables. |
1665 // | 1668 // |
1666 // Consulting environment variables doesn't need to be done from the | 1669 // Consulting environment variables doesn't need to be done from the |
1667 // default glib main loop, but it's a tiny enough amount of work. | 1670 // default glib main loop, but it's a tiny enough amount of work. |
1668 if (GetConfigFromEnv(&cached_config_)) { | 1671 if (GetConfigFromEnv(&cached_config_)) { |
1669 cached_config_.set_id(1); // Mark it as valid. | 1672 cached_config_.set_id(1); // Mark it as valid. |
1670 VLOG(1) << "Obtained proxy settings from environment variables"; | 1673 VLOG(1) << "Obtained proxy settings from environment variables"; |
1671 } | 1674 } |
1672 } | 1675 } |
1673 } | 1676 } |
1674 | 1677 |
1675 // Depending on the SettingGetter in use, this method will be called | 1678 // Depending on the SettingGetter in use, this method will be called |
1676 // on either the UI thread (GConf) or the file thread (KDE). | 1679 // on either the UI thread (GConf) or the file thread (KDE). |
1677 void ProxyConfigServiceLinux::Delegate::SetUpNotifications() { | 1680 void ProxyConfigServiceLinux::Delegate::SetUpNotifications() { |
1678 MessageLoop* required_loop = setting_getter_->GetNotificationLoop(); | 1681 scoped_refptr<base::MessageLoopProxy> required_loop = |
1679 DCHECK(!required_loop || MessageLoop::current() == required_loop); | 1682 setting_getter_->GetNotificationLoop(); |
| 1683 DCHECK(!required_loop || required_loop->BelongsToCurrentThread()); |
1680 if (!setting_getter_->SetUpNotifications(this)) | 1684 if (!setting_getter_->SetUpNotifications(this)) |
1681 LOG(ERROR) << "Unable to set up proxy configuration change notifications"; | 1685 LOG(ERROR) << "Unable to set up proxy configuration change notifications"; |
1682 } | 1686 } |
1683 | 1687 |
1684 void ProxyConfigServiceLinux::Delegate::AddObserver(Observer* observer) { | 1688 void ProxyConfigServiceLinux::Delegate::AddObserver(Observer* observer) { |
1685 observers_.AddObserver(observer); | 1689 observers_.AddObserver(observer); |
1686 } | 1690 } |
1687 | 1691 |
1688 void ProxyConfigServiceLinux::Delegate::RemoveObserver(Observer* observer) { | 1692 void ProxyConfigServiceLinux::Delegate::RemoveObserver(Observer* observer) { |
1689 observers_.RemoveObserver(observer); | 1693 observers_.RemoveObserver(observer); |
1690 } | 1694 } |
1691 | 1695 |
1692 ProxyConfigService::ConfigAvailability | 1696 ProxyConfigService::ConfigAvailability |
1693 ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig( | 1697 ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig( |
1694 ProxyConfig* config) { | 1698 ProxyConfig* config) { |
1695 // This is called from the IO thread. | 1699 // This is called from the IO thread. |
1696 DCHECK(!io_loop_ || MessageLoop::current() == io_loop_); | 1700 DCHECK(!io_loop_ || io_loop_->BelongsToCurrentThread()); |
1697 | 1701 |
1698 // Simply return the last proxy configuration that glib_default_loop | 1702 // Simply return the last proxy configuration that glib_default_loop |
1699 // notified us of. | 1703 // notified us of. |
1700 *config = cached_config_.is_valid() ? | 1704 *config = cached_config_.is_valid() ? |
1701 cached_config_ : ProxyConfig::CreateDirect(); | 1705 cached_config_ : ProxyConfig::CreateDirect(); |
1702 | 1706 |
1703 // We return CONFIG_VALID to indicate that *config was filled in. It is always | 1707 // We return CONFIG_VALID to indicate that *config was filled in. It is always |
1704 // going to be available since we initialized eagerly on the UI thread. | 1708 // going to be available since we initialized eagerly on the UI thread. |
1705 // TODO(eroman): do lazy initialization instead, so we no longer need | 1709 // TODO(eroman): do lazy initialization instead, so we no longer need |
1706 // to construct ProxyConfigServiceLinux on the UI thread. | 1710 // to construct ProxyConfigServiceLinux on the UI thread. |
1707 // In which case, we may return false here. | 1711 // In which case, we may return false here. |
1708 return CONFIG_VALID; | 1712 return CONFIG_VALID; |
1709 } | 1713 } |
1710 | 1714 |
1711 // Depending on the SettingGetter in use, this method will be called | 1715 // Depending on the SettingGetter in use, this method will be called |
1712 // on either the UI thread (GConf) or the file thread (KDE). | 1716 // on either the UI thread (GConf) or the file thread (KDE). |
1713 void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() { | 1717 void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() { |
1714 MessageLoop* required_loop = setting_getter_->GetNotificationLoop(); | 1718 scoped_refptr<base::MessageLoopProxy> required_loop = |
1715 DCHECK(!required_loop || MessageLoop::current() == required_loop); | 1719 setting_getter_->GetNotificationLoop(); |
| 1720 DCHECK(!required_loop || required_loop->BelongsToCurrentThread()); |
1716 ProxyConfig new_config; | 1721 ProxyConfig new_config; |
1717 bool valid = GetConfigFromSettings(&new_config); | 1722 bool valid = GetConfigFromSettings(&new_config); |
1718 if (valid) | 1723 if (valid) |
1719 new_config.set_id(1); // mark it as valid | 1724 new_config.set_id(1); // mark it as valid |
1720 | 1725 |
1721 // See if it is different from what we had before. | 1726 // See if it is different from what we had before. |
1722 if (new_config.is_valid() != reference_config_.is_valid() || | 1727 if (new_config.is_valid() != reference_config_.is_valid() || |
1723 !new_config.Equals(reference_config_)) { | 1728 !new_config.Equals(reference_config_)) { |
1724 // Post a task to |io_loop| with the new configuration, so it can | 1729 // Post a task to |io_loop| with the new configuration, so it can |
1725 // update |cached_config_|. | 1730 // update |cached_config_|. |
1726 io_loop_->PostTask(FROM_HERE, base::Bind( | 1731 io_loop_->PostTask(FROM_HERE, base::Bind( |
1727 &ProxyConfigServiceLinux::Delegate::SetNewProxyConfig, | 1732 &ProxyConfigServiceLinux::Delegate::SetNewProxyConfig, |
1728 this, new_config)); | 1733 this, new_config)); |
1729 // Update the thread-private copy in |reference_config_| as well. | 1734 // Update the thread-private copy in |reference_config_| as well. |
1730 reference_config_ = new_config; | 1735 reference_config_ = new_config; |
1731 } else { | 1736 } else { |
1732 VLOG(1) << "Detected no-op change to proxy settings. Doing nothing."; | 1737 VLOG(1) << "Detected no-op change to proxy settings. Doing nothing."; |
1733 } | 1738 } |
1734 } | 1739 } |
1735 | 1740 |
1736 void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig( | 1741 void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig( |
1737 const ProxyConfig& new_config) { | 1742 const ProxyConfig& new_config) { |
1738 DCHECK(MessageLoop::current() == io_loop_); | 1743 DCHECK(io_loop_->BelongsToCurrentThread()); |
1739 VLOG(1) << "Proxy configuration changed"; | 1744 VLOG(1) << "Proxy configuration changed"; |
1740 cached_config_ = new_config; | 1745 cached_config_ = new_config; |
1741 FOR_EACH_OBSERVER( | 1746 FOR_EACH_OBSERVER( |
1742 Observer, observers_, | 1747 Observer, observers_, |
1743 OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID)); | 1748 OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID)); |
1744 } | 1749 } |
1745 | 1750 |
1746 void ProxyConfigServiceLinux::Delegate::PostDestroyTask() { | 1751 void ProxyConfigServiceLinux::Delegate::PostDestroyTask() { |
1747 if (!setting_getter_.get()) | 1752 if (!setting_getter_.get()) |
1748 return; | 1753 return; |
1749 MessageLoop* shutdown_loop = setting_getter_->GetNotificationLoop(); | 1754 scoped_refptr<base::MessageLoopProxy> shutdown_loop = |
1750 if (!shutdown_loop || MessageLoop::current() == shutdown_loop) { | 1755 setting_getter_->GetNotificationLoop(); |
| 1756 if (!shutdown_loop || shutdown_loop->BelongsToCurrentThread()) { |
1751 // Already on the right thread, call directly. | 1757 // Already on the right thread, call directly. |
1752 // This is the case for the unittests. | 1758 // This is the case for the unittests. |
1753 OnDestroy(); | 1759 OnDestroy(); |
1754 } else { | 1760 } else { |
1755 // Post to shutdown thread. Note that on browser shutdown, we may quit | 1761 // Post to shutdown thread. Note that on browser shutdown, we may quit |
1756 // this MessageLoop and exit the program before ever running this. | 1762 // this MessageLoop and exit the program before ever running this. |
1757 shutdown_loop->PostTask(FROM_HERE, base::Bind( | 1763 shutdown_loop->PostTask(FROM_HERE, base::Bind( |
1758 &ProxyConfigServiceLinux::Delegate::OnDestroy, this)); | 1764 &ProxyConfigServiceLinux::Delegate::OnDestroy, this)); |
1759 } | 1765 } |
1760 } | 1766 } |
1761 void ProxyConfigServiceLinux::Delegate::OnDestroy() { | 1767 void ProxyConfigServiceLinux::Delegate::OnDestroy() { |
1762 MessageLoop* shutdown_loop = setting_getter_->GetNotificationLoop(); | 1768 scoped_refptr<base::MessageLoopProxy> shutdown_loop = |
1763 DCHECK(!shutdown_loop || MessageLoop::current() == shutdown_loop); | 1769 setting_getter_->GetNotificationLoop(); |
| 1770 DCHECK(!shutdown_loop || shutdown_loop->BelongsToCurrentThread()); |
1764 setting_getter_->ShutDown(); | 1771 setting_getter_->ShutDown(); |
1765 } | 1772 } |
1766 | 1773 |
1767 ProxyConfigServiceLinux::ProxyConfigServiceLinux() | 1774 ProxyConfigServiceLinux::ProxyConfigServiceLinux() |
1768 : delegate_(new Delegate(base::Environment::Create())) { | 1775 : delegate_(new Delegate(base::Environment::Create())) { |
1769 } | 1776 } |
1770 | 1777 |
1771 ProxyConfigServiceLinux::~ProxyConfigServiceLinux() { | 1778 ProxyConfigServiceLinux::~ProxyConfigServiceLinux() { |
1772 delegate_->PostDestroyTask(); | 1779 delegate_->PostDestroyTask(); |
1773 } | 1780 } |
(...skipping 15 matching lines...) Expand all Loading... |
1789 void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) { | 1796 void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) { |
1790 delegate_->RemoveObserver(observer); | 1797 delegate_->RemoveObserver(observer); |
1791 } | 1798 } |
1792 | 1799 |
1793 ProxyConfigService::ConfigAvailability | 1800 ProxyConfigService::ConfigAvailability |
1794 ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) { | 1801 ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) { |
1795 return delegate_->GetLatestProxyConfig(config); | 1802 return delegate_->GetLatestProxyConfig(config); |
1796 } | 1803 } |
1797 | 1804 |
1798 } // namespace net | 1805 } // namespace net |
OLD | NEW |