| 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 |