Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(106)

Side by Side Diff: net/proxy/proxy_config_service_linux.cc

Issue 2944313003: Remove the dependence on BrowserThread::FILE for (Closed)
Patch Set: address mmenke's comments Created 3 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 #if defined(USE_GCONF) 8 #if defined(USE_GCONF)
9 #include <gconf/gconf-client.h> 9 #include <gconf/gconf-client.h>
10 #endif // defined(USE_GCONF) 10 #endif // defined(USE_GCONF)
11 #include <limits.h> 11 #include <limits.h>
12 #include <stdio.h> 12 #include <stdio.h>
13 #include <stdlib.h> 13 #include <stdlib.h>
14 #include <sys/inotify.h> 14 #include <sys/inotify.h>
15 #include <unistd.h> 15 #include <unistd.h>
16 16
17 #include <map> 17 #include <map>
18 #include <utility> 18 #include <utility>
19 19
20 #include "base/bind.h" 20 #include "base/bind.h"
21 #include "base/compiler_specific.h" 21 #include "base/compiler_specific.h"
22 #include "base/debug/leak_annotations.h" 22 #include "base/debug/leak_annotations.h"
23 #include "base/files/file_descriptor_watcher_posix.h" 23 #include "base/files/file_descriptor_watcher_posix.h"
24 #include "base/files/file_path.h" 24 #include "base/files/file_path.h"
25 #include "base/files/file_util.h" 25 #include "base/files/file_util.h"
26 #include "base/files/scoped_file.h" 26 #include "base/files/scoped_file.h"
27 #include "base/logging.h" 27 #include "base/logging.h"
28 #include "base/macros.h" 28 #include "base/macros.h"
29 #include "base/nix/xdg_util.h" 29 #include "base/nix/xdg_util.h"
30 #include "base/sequenced_task_runner.h"
30 #include "base/single_thread_task_runner.h" 31 #include "base/single_thread_task_runner.h"
31 #include "base/strings/string_number_conversions.h" 32 #include "base/strings/string_number_conversions.h"
32 #include "base/strings/string_tokenizer.h" 33 #include "base/strings/string_tokenizer.h"
33 #include "base/strings/string_util.h" 34 #include "base/strings/string_util.h"
35 #include "base/task_scheduler/post_task.h"
36 #include "base/task_scheduler/task_traits.h"
34 #include "base/threading/thread_restrictions.h" 37 #include "base/threading/thread_restrictions.h"
35 #include "base/timer/timer.h" 38 #include "base/timer/timer.h"
36 #include "net/base/net_errors.h" 39 #include "net/base/net_errors.h"
37 #include "net/http/http_util.h" 40 #include "net/http/http_util.h"
38 #include "net/proxy/proxy_config.h" 41 #include "net/proxy/proxy_config.h"
39 #include "net/proxy/proxy_server.h" 42 #include "net/proxy/proxy_server.h"
40 #include "url/url_canon.h" 43 #include "url/url_canon.h"
41 44
42 #if defined(USE_GIO) 45 #if defined(USE_GIO)
43 #include "library_loaders/libgio.h" // nogncheck 46 #include "library_loaders/libgio.h" // nogncheck
(...skipping 169 matching lines...) Expand 10 before | Expand all | Expand 10 after
213 debounce_timer_(new base::OneShotTimer()) {} 216 debounce_timer_(new base::OneShotTimer()) {}
214 217
215 ~SettingGetterImplGConf() override { 218 ~SettingGetterImplGConf() override {
216 // client_ should have been released before now, from 219 // client_ should have been released before now, from
217 // Delegate::OnDestroy(), while running on the UI thread. However 220 // Delegate::OnDestroy(), while running on the UI thread. However
218 // on exiting the process, it may happen that Delegate::OnDestroy() 221 // on exiting the process, it may happen that Delegate::OnDestroy()
219 // task is left pending on the glib loop after the loop was quit, 222 // task is left pending on the glib loop after the loop was quit,
220 // and pending tasks may then be deleted without being run. 223 // and pending tasks may then be deleted without being run.
221 if (client_) { 224 if (client_) {
222 // gconf client was not cleaned up. 225 // gconf client was not cleaned up.
223 if (task_runner_->BelongsToCurrentThread()) { 226 if (task_runner_->RunsTasksInCurrentSequence()) {
224 // We are on the UI thread so we can clean it safely. This is 227 // We are on the UI thread so we can clean it safely. This is
225 // the case at least for ui_tests running under Valgrind in 228 // the case at least for ui_tests running under Valgrind in
226 // bug 16076. 229 // bug 16076.
227 VLOG(1) << "~SettingGetterImplGConf: releasing gconf client"; 230 VLOG(1) << "~SettingGetterImplGConf: releasing gconf client";
228 ShutDown(); 231 ShutDown();
229 } else { 232 } else {
230 // This is very bad! We are deleting the setting getter but we're not on 233 // This is very bad! We are deleting the setting getter but we're not on
231 // the UI thread. This is not supposed to happen: the setting getter is 234 // the UI thread. This is not supposed to happen: the setting getter is
232 // owned by the proxy config service's delegate, which is supposed to be 235 // owned by the proxy config service's delegate, which is supposed to be
233 // destroyed on the UI thread only. We will get change notifications to 236 // destroyed on the UI thread only. We will get change notifications to
234 // a deleted object if we continue here, so fail now. 237 // a deleted object if we continue here, so fail now.
235 LOG(FATAL) << "~SettingGetterImplGConf: deleting on wrong thread!"; 238 LOG(FATAL) << "~SettingGetterImplGConf: deleting on wrong thread!";
236 } 239 }
237 } 240 }
238 DCHECK(!client_); 241 DCHECK(!client_);
239 } 242 }
240 243
241 bool Init(const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner, 244 bool Init(const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner)
242 const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner)
243 override { 245 override {
244 DCHECK(glib_task_runner->BelongsToCurrentThread()); 246 DCHECK(glib_task_runner->RunsTasksInCurrentSequence());
245 DCHECK(!client_); 247 DCHECK(!client_);
246 DCHECK(!task_runner_.get()); 248 DCHECK(!task_runner_.get());
247 task_runner_ = glib_task_runner; 249 task_runner_ = glib_task_runner;
248 250
249 client_ = gconf_client_get_default(); 251 client_ = gconf_client_get_default();
250 if (!client_) { 252 if (!client_) {
251 // It's not clear whether/when this can return NULL. 253 // It's not clear whether/when this can return NULL.
252 LOG(ERROR) << "Unable to create a gconf client"; 254 LOG(ERROR) << "Unable to create a gconf client";
253 task_runner_ = nullptr; 255 task_runner_ = nullptr;
254 return false; 256 return false;
(...skipping 19 matching lines...) Expand all
274 if (added_system_proxy) 276 if (added_system_proxy)
275 gconf_client_remove_dir(client_, "/system/proxy", nullptr); 277 gconf_client_remove_dir(client_, "/system/proxy", nullptr);
276 g_object_unref(client_); 278 g_object_unref(client_);
277 client_ = nullptr; 279 client_ = nullptr;
278 task_runner_ = nullptr; 280 task_runner_ = nullptr;
279 return false; 281 return false;
280 } 282 }
281 283
282 void ShutDown() override { 284 void ShutDown() override {
283 if (client_) { 285 if (client_) {
284 DCHECK(task_runner_->BelongsToCurrentThread()); 286 DCHECK(task_runner_->RunsTasksInCurrentSequence());
285 // We must explicitly disable gconf notifications here, because the gconf 287 // We must explicitly disable gconf notifications here, because the gconf
286 // client will be shared between all setting getters, and they do not all 288 // client will be shared between all setting getters, and they do not all
287 // have the same lifetimes. (For instance, incognito sessions get their 289 // have the same lifetimes. (For instance, incognito sessions get their
288 // own, which is destroyed when the session ends.) 290 // own, which is destroyed when the session ends.)
289 gconf_client_notify_remove(client_, system_http_proxy_id_); 291 gconf_client_notify_remove(client_, system_http_proxy_id_);
290 gconf_client_notify_remove(client_, system_proxy_id_); 292 gconf_client_notify_remove(client_, system_proxy_id_);
291 gconf_client_remove_dir(client_, "/system/http_proxy", nullptr); 293 gconf_client_remove_dir(client_, "/system/http_proxy", nullptr);
292 gconf_client_remove_dir(client_, "/system/proxy", nullptr); 294 gconf_client_remove_dir(client_, "/system/proxy", nullptr);
293 g_object_unref(client_); 295 g_object_unref(client_);
294 client_ = nullptr; 296 client_ = nullptr;
295 task_runner_ = nullptr; 297 task_runner_ = nullptr;
296 } 298 }
297 debounce_timer_.reset(); 299 debounce_timer_.reset();
298 } 300 }
299 301
300 bool SetUpNotifications( 302 bool SetUpNotifications(
301 ProxyConfigServiceLinux::Delegate* delegate) override { 303 ProxyConfigServiceLinux::Delegate* delegate) override {
302 DCHECK(client_); 304 DCHECK(client_);
303 DCHECK(task_runner_->BelongsToCurrentThread()); 305 DCHECK(task_runner_->RunsTasksInCurrentSequence());
304 GError* error = nullptr; 306 GError* error = nullptr;
305 notify_delegate_ = delegate; 307 notify_delegate_ = delegate;
306 // We have to keep track of the IDs returned by gconf_client_notify_add() so 308 // We have to keep track of the IDs returned by gconf_client_notify_add() so
307 // that we can remove them in ShutDown(). (Otherwise, notifications will be 309 // that we can remove them in ShutDown(). (Otherwise, notifications will be
308 // delivered to this object after it is deleted, which is bad, m'kay?) 310 // delivered to this object after it is deleted, which is bad, m'kay?)
309 system_proxy_id_ = gconf_client_notify_add(client_, "/system/proxy", 311 system_proxy_id_ = gconf_client_notify_add(client_, "/system/proxy",
310 OnGConfChangeNotification, this, 312 OnGConfChangeNotification, this,
311 nullptr, &error); 313 nullptr, &error);
312 if (!error) { 314 if (!error) {
313 system_http_proxy_id_ = gconf_client_notify_add( 315 system_http_proxy_id_ = gconf_client_notify_add(
314 client_, "/system/http_proxy", OnGConfChangeNotification, this, 316 client_, "/system/http_proxy", OnGConfChangeNotification, this,
315 nullptr, &error); 317 nullptr, &error);
316 } 318 }
317 if (!error) { 319 if (!error) {
318 // Simulate a change to avoid possibly losing updates before this point. 320 // Simulate a change to avoid possibly losing updates before this point.
319 OnChangeNotification(); 321 OnChangeNotification();
320 return true; 322 return true;
321 } 323 }
322 324
323 LOG(ERROR) << "Error requesting gconf notifications: " << error->message; 325 LOG(ERROR) << "Error requesting gconf notifications: " << error->message;
324 g_error_free(error); 326 g_error_free(error);
325 ShutDown(); 327 ShutDown();
326 return false; 328 return false;
327 } 329 }
328 330
329 const scoped_refptr<base::SingleThreadTaskRunner>& GetNotificationTaskRunner() 331 const scoped_refptr<base::SequencedTaskRunner>& GetNotificationTaskRunner()
330 override { 332 override {
331 return task_runner_; 333 return task_runner_;
332 } 334 }
333 335
334 ProxyConfigSource GetConfigSource() override { 336 ProxyConfigSource GetConfigSource() override {
335 return PROXY_CONFIG_SOURCE_GCONF; 337 return PROXY_CONFIG_SOURCE_GCONF;
336 } 338 }
337 339
338 bool GetString(StringSetting key, std::string* result) override { 340 bool GetString(StringSetting key, std::string* result) override {
339 switch (key) { 341 switch (key) {
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after
388 bool BypassListIsReversed() override { 390 bool BypassListIsReversed() override {
389 // This is a KDE-specific setting. 391 // This is a KDE-specific setting.
390 return false; 392 return false;
391 } 393 }
392 394
393 bool MatchHostsUsingSuffixMatching() override { return false; } 395 bool MatchHostsUsingSuffixMatching() override { return false; }
394 396
395 private: 397 private:
396 bool GetStringByPath(base::StringPiece key, std::string* result) { 398 bool GetStringByPath(base::StringPiece key, std::string* result) {
397 DCHECK(client_); 399 DCHECK(client_);
398 DCHECK(task_runner_->BelongsToCurrentThread()); 400 DCHECK(task_runner_->RunsTasksInCurrentSequence());
399 GError* error = nullptr; 401 GError* error = nullptr;
400 gchar* value = gconf_client_get_string(client_, key.data(), &error); 402 gchar* value = gconf_client_get_string(client_, key.data(), &error);
401 if (HandleGError(error, key.data())) 403 if (HandleGError(error, key.data()))
402 return false; 404 return false;
403 if (!value) 405 if (!value)
404 return false; 406 return false;
405 *result = value; 407 *result = value;
406 g_free(value); 408 g_free(value);
407 return true; 409 return true;
408 } 410 }
409 bool GetBoolByPath(base::StringPiece key, bool* result) { 411 bool GetBoolByPath(base::StringPiece key, bool* result) {
410 DCHECK(client_); 412 DCHECK(client_);
411 DCHECK(task_runner_->BelongsToCurrentThread()); 413 DCHECK(task_runner_->RunsTasksInCurrentSequence());
412 GError* error = nullptr; 414 GError* error = nullptr;
413 // We want to distinguish unset values from values defaulting to 415 // We want to distinguish unset values from values defaulting to
414 // false. For that we need to use the type-generic 416 // false. For that we need to use the type-generic
415 // gconf_client_get() rather than gconf_client_get_bool(). 417 // gconf_client_get() rather than gconf_client_get_bool().
416 GConfValue* gconf_value = gconf_client_get(client_, key.data(), &error); 418 GConfValue* gconf_value = gconf_client_get(client_, key.data(), &error);
417 if (HandleGError(error, key.data())) 419 if (HandleGError(error, key.data()))
418 return false; 420 return false;
419 if (!gconf_value) { 421 if (!gconf_value) {
420 // Unset. 422 // Unset.
421 return false; 423 return false;
422 } 424 }
423 if (gconf_value->type != GCONF_VALUE_BOOL) { 425 if (gconf_value->type != GCONF_VALUE_BOOL) {
424 gconf_value_free(gconf_value); 426 gconf_value_free(gconf_value);
425 return false; 427 return false;
426 } 428 }
427 gboolean bool_value = gconf_value_get_bool(gconf_value); 429 gboolean bool_value = gconf_value_get_bool(gconf_value);
428 *result = static_cast<bool>(bool_value); 430 *result = static_cast<bool>(bool_value);
429 gconf_value_free(gconf_value); 431 gconf_value_free(gconf_value);
430 return true; 432 return true;
431 } 433 }
432 bool GetIntByPath(base::StringPiece key, int* result) { 434 bool GetIntByPath(base::StringPiece key, int* result) {
433 DCHECK(client_); 435 DCHECK(client_);
434 DCHECK(task_runner_->BelongsToCurrentThread()); 436 DCHECK(task_runner_->RunsTasksInCurrentSequence());
435 GError* error = nullptr; 437 GError* error = nullptr;
436 int value = gconf_client_get_int(client_, key.data(), &error); 438 int value = gconf_client_get_int(client_, key.data(), &error);
437 if (HandleGError(error, key.data())) 439 if (HandleGError(error, key.data()))
438 return false; 440 return false;
439 // We don't bother to distinguish an unset value because callers 441 // We don't bother to distinguish an unset value because callers
440 // don't care. 0 is returned if unset. 442 // don't care. 0 is returned if unset.
441 *result = value; 443 *result = value;
442 return true; 444 return true;
443 } 445 }
444 bool GetStringListByPath(base::StringPiece key, 446 bool GetStringListByPath(base::StringPiece key,
445 std::vector<std::string>* result) { 447 std::vector<std::string>* result) {
446 DCHECK(client_); 448 DCHECK(client_);
447 DCHECK(task_runner_->BelongsToCurrentThread()); 449 DCHECK(task_runner_->RunsTasksInCurrentSequence());
448 GError* error = nullptr; 450 GError* error = nullptr;
449 GSList* list = 451 GSList* list =
450 gconf_client_get_list(client_, key.data(), GCONF_VALUE_STRING, &error); 452 gconf_client_get_list(client_, key.data(), GCONF_VALUE_STRING, &error);
451 if (HandleGError(error, key.data())) 453 if (HandleGError(error, key.data()))
452 return false; 454 return false;
453 if (!list) 455 if (!list)
454 return false; 456 return false;
455 for (GSList *it = list; it; it = it->next) { 457 for (GSList *it = list; it; it = it->next) {
456 result->push_back(static_cast<char*>(it->data)); 458 result->push_back(static_cast<char*>(it->data));
457 g_free(it->data); 459 g_free(it->data);
458 } 460 }
459 g_slist_free(list); 461 g_slist_free(list);
460 return true; 462 return true;
461 } 463 }
462 464
463 // Logs and frees a glib error. Returns false if there was no error 465 // Logs and frees a glib error. Returns false if there was no error
464 // (error is NULL). 466 // (error is NULL).
465 bool HandleGError(GError* error, base::StringPiece key) { 467 bool HandleGError(GError* error, base::StringPiece key) {
466 if (!error) 468 if (!error)
467 return false; 469 return false;
468 470
469 LOG(ERROR) << "Error getting gconf value for " << key << ": " 471 LOG(ERROR) << "Error getting gconf value for " << key << ": "
470 << error->message; 472 << error->message;
471 g_error_free(error); 473 g_error_free(error);
472 return true; 474 return true;
473 } 475 }
474 476
475 // This is the callback from the debounce timer. 477 // This is the callback from the debounce timer.
476 void OnDebouncedNotification() { 478 void OnDebouncedNotification() {
477 DCHECK(task_runner_->BelongsToCurrentThread()); 479 DCHECK(task_runner_->RunsTasksInCurrentSequence());
478 CHECK(notify_delegate_); 480 CHECK(notify_delegate_);
479 // Forward to a method on the proxy config service delegate object. 481 // Forward to a method on the proxy config service delegate object.
480 notify_delegate_->OnCheckProxyConfigSettings(); 482 notify_delegate_->OnCheckProxyConfigSettings();
481 } 483 }
482 484
483 void OnChangeNotification() { 485 void OnChangeNotification() {
484 // We don't use Reset() because the timer may not yet be running. 486 // We don't use Reset() because the timer may not yet be running.
485 // (In that case Stop() is a no-op.) 487 // (In that case Stop() is a no-op.)
486 debounce_timer_->Stop(); 488 debounce_timer_->Stop();
487 debounce_timer_->Start(FROM_HERE, 489 debounce_timer_->Start(FROM_HERE,
(...skipping 17 matching lines...) Expand all
505 // will need in order to later call gconf_client_notify_remove(). 507 // will need in order to later call gconf_client_notify_remove().
506 guint system_proxy_id_; 508 guint system_proxy_id_;
507 guint system_http_proxy_id_; 509 guint system_http_proxy_id_;
508 510
509 ProxyConfigServiceLinux::Delegate* notify_delegate_; 511 ProxyConfigServiceLinux::Delegate* notify_delegate_;
510 std::unique_ptr<base::OneShotTimer> debounce_timer_; 512 std::unique_ptr<base::OneShotTimer> debounce_timer_;
511 513
512 // Task runner for the thread that we make gconf calls on. It should 514 // Task runner for the thread that we make gconf calls on. It should
513 // be the UI thread and all our methods should be called on this 515 // be the UI thread and all our methods should be called on this
514 // thread. Only for assertions. 516 // thread. Only for assertions.
515 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 517 scoped_refptr<base::SequencedTaskRunner> task_runner_;
516 518
517 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGConf); 519 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGConf);
518 }; 520 };
519 #endif // defined(USE_GCONF) 521 #endif // defined(USE_GCONF)
520 522
521 #if defined(USE_GIO) 523 #if defined(USE_GIO)
522 const char kProxyGConfSchema[] = "org.gnome.system.proxy"; 524 const char kProxyGConfSchema[] = "org.gnome.system.proxy";
523 525
524 // This setting getter uses gsettings, as used in most GNOME 3 desktops. 526 // This setting getter uses gsettings, as used in most GNOME 3 desktops.
525 class SettingGetterImplGSettings 527 class SettingGetterImplGSettings
(...skipping 10 matching lines...) Expand all
536 538
537 ~SettingGetterImplGSettings() override { 539 ~SettingGetterImplGSettings() override {
538 // client_ should have been released before now, from 540 // client_ should have been released before now, from
539 // Delegate::OnDestroy(), while running on the UI thread. However 541 // Delegate::OnDestroy(), while running on the UI thread. However
540 // on exiting the process, it may happen that 542 // on exiting the process, it may happen that
541 // Delegate::OnDestroy() task is left pending on the glib loop 543 // Delegate::OnDestroy() task is left pending on the glib loop
542 // after the loop was quit, and pending tasks may then be deleted 544 // after the loop was quit, and pending tasks may then be deleted
543 // without being run. 545 // without being run.
544 if (client_) { 546 if (client_) {
545 // gconf client was not cleaned up. 547 // gconf client was not cleaned up.
546 if (task_runner_->BelongsToCurrentThread()) { 548 if (task_runner_->RunsTasksInCurrentSequence()) {
547 // We are on the UI thread so we can clean it safely. This is 549 // We are on the UI thread so we can clean it safely. This is
548 // the case at least for ui_tests running under Valgrind in 550 // the case at least for ui_tests running under Valgrind in
549 // bug 16076. 551 // bug 16076.
550 VLOG(1) << "~SettingGetterImplGSettings: releasing gsettings client"; 552 VLOG(1) << "~SettingGetterImplGSettings: releasing gsettings client";
551 ShutDown(); 553 ShutDown();
552 } else { 554 } else {
553 LOG(WARNING) << "~SettingGetterImplGSettings: leaking gsettings client"; 555 LOG(WARNING) << "~SettingGetterImplGSettings: leaking gsettings client";
554 client_ = nullptr; 556 client_ = nullptr;
555 } 557 }
556 } 558 }
557 DCHECK(!client_); 559 DCHECK(!client_);
558 } 560 }
559 561
560 bool SchemaExists(base::StringPiece schema_name) { 562 bool SchemaExists(base::StringPiece schema_name) {
561 const gchar* const* schemas = libgio_loader_.g_settings_list_schemas(); 563 const gchar* const* schemas = libgio_loader_.g_settings_list_schemas();
562 while (*schemas) { 564 while (*schemas) {
563 if (!strcmp(schema_name.data(), static_cast<const char*>(*schemas))) 565 if (!strcmp(schema_name.data(), static_cast<const char*>(*schemas)))
564 return true; 566 return true;
565 schemas++; 567 schemas++;
566 } 568 }
567 return false; 569 return false;
568 } 570 }
569 571
570 // LoadAndCheckVersion() must be called *before* Init()! 572 // LoadAndCheckVersion() must be called *before* Init()!
571 bool LoadAndCheckVersion(base::Environment* env); 573 bool LoadAndCheckVersion(base::Environment* env);
572 574
573 bool Init(const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner, 575 bool Init(const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner)
574 const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner)
575 override { 576 override {
576 DCHECK(glib_task_runner->BelongsToCurrentThread()); 577 DCHECK(glib_task_runner->RunsTasksInCurrentSequence());
577 DCHECK(!client_); 578 DCHECK(!client_);
578 DCHECK(!task_runner_.get()); 579 DCHECK(!task_runner_.get());
579 580
580 if (!SchemaExists(kProxyGConfSchema) || 581 if (!SchemaExists(kProxyGConfSchema) ||
581 !(client_ = libgio_loader_.g_settings_new(kProxyGConfSchema))) { 582 !(client_ = libgio_loader_.g_settings_new(kProxyGConfSchema))) {
582 // It's not clear whether/when this can return NULL. 583 // It's not clear whether/when this can return NULL.
583 LOG(ERROR) << "Unable to create a gsettings client"; 584 LOG(ERROR) << "Unable to create a gsettings client";
584 return false; 585 return false;
585 } 586 }
586 task_runner_ = glib_task_runner; 587 task_runner_ = glib_task_runner;
587 // We assume these all work if the above call worked. 588 // We assume these all work if the above call worked.
588 http_client_ = libgio_loader_.g_settings_get_child(client_, "http"); 589 http_client_ = libgio_loader_.g_settings_get_child(client_, "http");
589 https_client_ = libgio_loader_.g_settings_get_child(client_, "https"); 590 https_client_ = libgio_loader_.g_settings_get_child(client_, "https");
590 ftp_client_ = libgio_loader_.g_settings_get_child(client_, "ftp"); 591 ftp_client_ = libgio_loader_.g_settings_get_child(client_, "ftp");
591 socks_client_ = libgio_loader_.g_settings_get_child(client_, "socks"); 592 socks_client_ = libgio_loader_.g_settings_get_child(client_, "socks");
592 DCHECK(http_client_ && https_client_ && ftp_client_ && socks_client_); 593 DCHECK(http_client_ && https_client_ && ftp_client_ && socks_client_);
593 return true; 594 return true;
594 } 595 }
595 596
596 void ShutDown() override { 597 void ShutDown() override {
597 if (client_) { 598 if (client_) {
598 DCHECK(task_runner_->BelongsToCurrentThread()); 599 DCHECK(task_runner_->RunsTasksInCurrentSequence());
599 // This also disables gsettings notifications. 600 // This also disables gsettings notifications.
600 g_object_unref(socks_client_); 601 g_object_unref(socks_client_);
601 g_object_unref(ftp_client_); 602 g_object_unref(ftp_client_);
602 g_object_unref(https_client_); 603 g_object_unref(https_client_);
603 g_object_unref(http_client_); 604 g_object_unref(http_client_);
604 g_object_unref(client_); 605 g_object_unref(client_);
605 // We only need to null client_ because it's the only one that we check. 606 // We only need to null client_ because it's the only one that we check.
606 client_ = nullptr; 607 client_ = nullptr;
607 task_runner_ = nullptr; 608 task_runner_ = nullptr;
608 } 609 }
609 debounce_timer_.reset(); 610 debounce_timer_.reset();
610 } 611 }
611 612
612 bool SetUpNotifications( 613 bool SetUpNotifications(
613 ProxyConfigServiceLinux::Delegate* delegate) override { 614 ProxyConfigServiceLinux::Delegate* delegate) override {
614 DCHECK(client_); 615 DCHECK(client_);
615 DCHECK(task_runner_->BelongsToCurrentThread()); 616 DCHECK(task_runner_->RunsTasksInCurrentSequence());
616 notify_delegate_ = delegate; 617 notify_delegate_ = delegate;
617 // We could watch for the change-event signal instead of changed, but 618 // We could watch for the change-event signal instead of changed, but
618 // since we have to watch more than one object, we'd still have to 619 // since we have to watch more than one object, we'd still have to
619 // debounce change notifications. This is conceptually simpler. 620 // debounce change notifications. This is conceptually simpler.
620 g_signal_connect(G_OBJECT(client_), "changed", 621 g_signal_connect(G_OBJECT(client_), "changed",
621 G_CALLBACK(OnGSettingsChangeNotification), this); 622 G_CALLBACK(OnGSettingsChangeNotification), this);
622 g_signal_connect(G_OBJECT(http_client_), "changed", 623 g_signal_connect(G_OBJECT(http_client_), "changed",
623 G_CALLBACK(OnGSettingsChangeNotification), this); 624 G_CALLBACK(OnGSettingsChangeNotification), this);
624 g_signal_connect(G_OBJECT(https_client_), "changed", 625 g_signal_connect(G_OBJECT(https_client_), "changed",
625 G_CALLBACK(OnGSettingsChangeNotification), this); 626 G_CALLBACK(OnGSettingsChangeNotification), this);
626 g_signal_connect(G_OBJECT(ftp_client_), "changed", 627 g_signal_connect(G_OBJECT(ftp_client_), "changed",
627 G_CALLBACK(OnGSettingsChangeNotification), this); 628 G_CALLBACK(OnGSettingsChangeNotification), this);
628 g_signal_connect(G_OBJECT(socks_client_), "changed", 629 g_signal_connect(G_OBJECT(socks_client_), "changed",
629 G_CALLBACK(OnGSettingsChangeNotification), this); 630 G_CALLBACK(OnGSettingsChangeNotification), this);
630 // Simulate a change to avoid possibly losing updates before this point. 631 // Simulate a change to avoid possibly losing updates before this point.
631 OnChangeNotification(); 632 OnChangeNotification();
632 return true; 633 return true;
633 } 634 }
634 635
635 const scoped_refptr<base::SingleThreadTaskRunner>& GetNotificationTaskRunner() 636 const scoped_refptr<base::SequencedTaskRunner>& GetNotificationTaskRunner()
636 override { 637 override {
637 return task_runner_; 638 return task_runner_;
638 } 639 }
639 640
640 ProxyConfigSource GetConfigSource() override { 641 ProxyConfigSource GetConfigSource() override {
641 return PROXY_CONFIG_SOURCE_GSETTINGS; 642 return PROXY_CONFIG_SOURCE_GSETTINGS;
642 } 643 }
643 644
644 bool GetString(StringSetting key, std::string* result) override { 645 bool GetString(StringSetting key, std::string* result) override {
645 DCHECK(client_); 646 DCHECK(client_);
(...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after
705 // This is a KDE-specific setting. 706 // This is a KDE-specific setting.
706 return false; 707 return false;
707 } 708 }
708 709
709 bool MatchHostsUsingSuffixMatching() override { return false; } 710 bool MatchHostsUsingSuffixMatching() override { return false; }
710 711
711 private: 712 private:
712 bool GetStringByPath(GSettings* client, 713 bool GetStringByPath(GSettings* client,
713 base::StringPiece key, 714 base::StringPiece key,
714 std::string* result) { 715 std::string* result) {
715 DCHECK(task_runner_->BelongsToCurrentThread()); 716 DCHECK(task_runner_->RunsTasksInCurrentSequence());
716 gchar* value = libgio_loader_.g_settings_get_string(client, key.data()); 717 gchar* value = libgio_loader_.g_settings_get_string(client, key.data());
717 if (!value) 718 if (!value)
718 return false; 719 return false;
719 *result = value; 720 *result = value;
720 g_free(value); 721 g_free(value);
721 return true; 722 return true;
722 } 723 }
723 bool GetBoolByPath(GSettings* client, base::StringPiece key, bool* result) { 724 bool GetBoolByPath(GSettings* client, base::StringPiece key, bool* result) {
724 DCHECK(task_runner_->BelongsToCurrentThread()); 725 DCHECK(task_runner_->RunsTasksInCurrentSequence());
725 *result = static_cast<bool>( 726 *result = static_cast<bool>(
726 libgio_loader_.g_settings_get_boolean(client, key.data())); 727 libgio_loader_.g_settings_get_boolean(client, key.data()));
727 return true; 728 return true;
728 } 729 }
729 bool GetIntByPath(GSettings* client, base::StringPiece key, int* result) { 730 bool GetIntByPath(GSettings* client, base::StringPiece key, int* result) {
730 DCHECK(task_runner_->BelongsToCurrentThread()); 731 DCHECK(task_runner_->RunsTasksInCurrentSequence());
731 *result = libgio_loader_.g_settings_get_int(client, key.data()); 732 *result = libgio_loader_.g_settings_get_int(client, key.data());
732 return true; 733 return true;
733 } 734 }
734 bool GetStringListByPath(GSettings* client, 735 bool GetStringListByPath(GSettings* client,
735 base::StringPiece key, 736 base::StringPiece key,
736 std::vector<std::string>* result) { 737 std::vector<std::string>* result) {
737 DCHECK(task_runner_->BelongsToCurrentThread()); 738 DCHECK(task_runner_->RunsTasksInCurrentSequence());
738 gchar** list = libgio_loader_.g_settings_get_strv(client, key.data()); 739 gchar** list = libgio_loader_.g_settings_get_strv(client, key.data());
739 if (!list) 740 if (!list)
740 return false; 741 return false;
741 for (size_t i = 0; list[i]; ++i) { 742 for (size_t i = 0; list[i]; ++i) {
742 result->push_back(static_cast<char*>(list[i])); 743 result->push_back(static_cast<char*>(list[i]));
743 g_free(list[i]); 744 g_free(list[i]);
744 } 745 }
745 g_free(list); 746 g_free(list);
746 return true; 747 return true;
747 } 748 }
748 749
749 // This is the callback from the debounce timer. 750 // This is the callback from the debounce timer.
750 void OnDebouncedNotification() { 751 void OnDebouncedNotification() {
751 DCHECK(task_runner_->BelongsToCurrentThread()); 752 DCHECK(task_runner_->RunsTasksInCurrentSequence());
752 CHECK(notify_delegate_); 753 CHECK(notify_delegate_);
753 // Forward to a method on the proxy config service delegate object. 754 // Forward to a method on the proxy config service delegate object.
754 notify_delegate_->OnCheckProxyConfigSettings(); 755 notify_delegate_->OnCheckProxyConfigSettings();
755 } 756 }
756 757
757 void OnChangeNotification() { 758 void OnChangeNotification() {
758 // We don't use Reset() because the timer may not yet be running. 759 // We don't use Reset() because the timer may not yet be running.
759 // (In that case Stop() is a no-op.) 760 // (In that case Stop() is a no-op.)
760 debounce_timer_->Stop(); 761 debounce_timer_->Stop();
761 debounce_timer_->Start(FROM_HERE, 762 debounce_timer_->Start(FROM_HERE,
(...skipping 15 matching lines...) Expand all
777 GSettings* http_client_; 778 GSettings* http_client_;
778 GSettings* https_client_; 779 GSettings* https_client_;
779 GSettings* ftp_client_; 780 GSettings* ftp_client_;
780 GSettings* socks_client_; 781 GSettings* socks_client_;
781 ProxyConfigServiceLinux::Delegate* notify_delegate_; 782 ProxyConfigServiceLinux::Delegate* notify_delegate_;
782 std::unique_ptr<base::OneShotTimer> debounce_timer_; 783 std::unique_ptr<base::OneShotTimer> debounce_timer_;
783 784
784 // Task runner for the thread that we make gsettings calls on. It should 785 // Task runner for the thread that we make gsettings calls on. It should
785 // be the UI thread and all our methods should be called on this 786 // be the UI thread and all our methods should be called on this
786 // thread. Only for assertions. 787 // thread. Only for assertions.
787 scoped_refptr<base::SingleThreadTaskRunner> task_runner_; 788 scoped_refptr<base::SequencedTaskRunner> task_runner_;
788 789
789 LibGioLoader libgio_loader_; 790 LibGioLoader libgio_loader_;
790 791
791 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGSettings); 792 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplGSettings);
792 }; 793 };
793 794
794 bool SettingGetterImplGSettings::LoadAndCheckVersion( 795 bool SettingGetterImplGSettings::LoadAndCheckVersion(
795 base::Environment* env) { 796 base::Environment* env) {
796 // LoadAndCheckVersion() must be called *before* Init()! 797 // LoadAndCheckVersion() must be called *before* Init()!
797 DCHECK(!client_); 798 DCHECK(!client_);
(...skipping 136 matching lines...) Expand 10 before | Expand all | Expand 10 after
934 // on exiting the process, it may happen that Delegate::OnDestroy() 935 // on exiting the process, it may happen that Delegate::OnDestroy()
935 // task is left pending on the file loop after the loop was quit, 936 // task is left pending on the file loop after the loop was quit,
936 // and pending tasks may then be deleted without being run. 937 // and pending tasks may then be deleted without being run.
937 // Here in the KDE version, we can safely close the file descriptor 938 // Here in the KDE version, we can safely close the file descriptor
938 // anyway. (Not that it really matters; the process is exiting.) 939 // anyway. (Not that it really matters; the process is exiting.)
939 if (inotify_fd_ >= 0) 940 if (inotify_fd_ >= 0)
940 ShutDown(); 941 ShutDown();
941 DCHECK_LT(inotify_fd_, 0); 942 DCHECK_LT(inotify_fd_, 0);
942 } 943 }
943 944
944 bool Init(const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner, 945 bool Init(const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner)
945 const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner)
946 override { 946 override {
947 // This has to be called on the UI thread (http://crbug.com/69057). 947 // This has to be called on the UI thread (http://crbug.com/69057).
948 base::ThreadRestrictions::ScopedAllowIO allow_io; 948 base::ThreadRestrictions::ScopedAllowIO allow_io;
949 DCHECK_LT(inotify_fd_, 0); 949 DCHECK_LT(inotify_fd_, 0);
950 inotify_fd_ = inotify_init(); 950 inotify_fd_ = inotify_init();
951 if (inotify_fd_ < 0) { 951 if (inotify_fd_ < 0) {
952 PLOG(ERROR) << "inotify_init failed"; 952 PLOG(ERROR) << "inotify_init failed";
953 return false; 953 return false;
954 } 954 }
955 if (!base::SetNonBlocking(inotify_fd_)) { 955 if (!base::SetNonBlocking(inotify_fd_)) {
956 PLOG(ERROR) << "base::SetNonBlocking failed"; 956 PLOG(ERROR) << "base::SetNonBlocking failed";
957 close(inotify_fd_); 957 close(inotify_fd_);
958 inotify_fd_ = -1; 958 inotify_fd_ = -1;
959 return false; 959 return false;
960 } 960 }
961 file_task_runner_ = file_task_runner; 961
962 constexpr base::TaskTraits kTraits = {base::TaskPriority::USER_VISIBLE,
963 base::MayBlock()};
964 file_task_runner_ = base::CreateSequencedTaskRunnerWithTraits(kTraits);
965
962 // The initial read is done on the current thread, not 966 // The initial read is done on the current thread, not
963 // |file_task_runner_|, since we will need to have it for 967 // |file_task_runner_|, since we will need to have it for
964 // SetUpAndFetchInitialConfig(). 968 // SetUpAndFetchInitialConfig().
965 UpdateCachedSettings(); 969 UpdateCachedSettings();
966 return true; 970 return true;
967 } 971 }
968 972
969 void ShutDown() override { 973 void ShutDown() override {
970 if (inotify_fd_ >= 0) { 974 if (inotify_fd_ >= 0) {
971 ResetCachedSettings(); 975 ResetCachedSettings();
972 inotify_watcher_.reset(); 976 inotify_watcher_.reset();
973 close(inotify_fd_); 977 close(inotify_fd_);
974 inotify_fd_ = -1; 978 inotify_fd_ = -1;
975 } 979 }
976 debounce_timer_.reset(); 980 debounce_timer_.reset();
977 } 981 }
978 982
979 bool SetUpNotifications( 983 bool SetUpNotifications(
980 ProxyConfigServiceLinux::Delegate* delegate) override { 984 ProxyConfigServiceLinux::Delegate* delegate) override {
981 DCHECK_GE(inotify_fd_, 0); 985 DCHECK_GE(inotify_fd_, 0);
982 DCHECK(file_task_runner_->BelongsToCurrentThread()); 986 DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
983 // We can't just watch the kioslaverc file directly, since KDE will write 987 // We can't just watch the kioslaverc file directly, since KDE will write
984 // a new copy of it and then rename it whenever settings are changed and 988 // a new copy of it and then rename it whenever settings are changed and
985 // inotify watches inodes (so we'll be watching the old deleted file after 989 // inotify watches inodes (so we'll be watching the old deleted file after
986 // the first change, and it will never change again). So, we watch the 990 // the first change, and it will never change again). So, we watch the
987 // directory instead. We then act only on changes to the kioslaverc entry. 991 // directory instead. We then act only on changes to the kioslaverc entry.
988 // TODO(eroman): What if the file is deleted? (handle with IN_DELETE). 992 // TODO(eroman): What if the file is deleted? (handle with IN_DELETE).
989 if (inotify_add_watch(inotify_fd_, kde_config_dir_.value().c_str(), 993 if (inotify_add_watch(inotify_fd_, kde_config_dir_.value().c_str(),
990 IN_MODIFY | IN_MOVED_TO) < 0) { 994 IN_MODIFY | IN_MOVED_TO) < 0) {
991 return false; 995 return false;
992 } 996 }
993 notify_delegate_ = delegate; 997 notify_delegate_ = delegate;
994 inotify_watcher_ = base::FileDescriptorWatcher::WatchReadable( 998 inotify_watcher_ = base::FileDescriptorWatcher::WatchReadable(
995 inotify_fd_, base::Bind(&SettingGetterImplKDE::OnChangeNotification, 999 inotify_fd_, base::Bind(&SettingGetterImplKDE::OnChangeNotification,
996 base::Unretained(this))); 1000 base::Unretained(this)));
997 // Simulate a change to avoid possibly losing updates before this point. 1001 // Simulate a change to avoid possibly losing updates before this point.
998 OnChangeNotification(); 1002 OnChangeNotification();
999 return true; 1003 return true;
1000 } 1004 }
1001 1005
1002 const scoped_refptr<base::SingleThreadTaskRunner>& GetNotificationTaskRunner() 1006 const scoped_refptr<base::SequencedTaskRunner>& GetNotificationTaskRunner()
1003 override { 1007 override {
1004 return file_task_runner_; 1008 return file_task_runner_;
1005 } 1009 }
1006 1010
1007 ProxyConfigSource GetConfigSource() override { 1011 ProxyConfigSource GetConfigSource() override {
1008 return PROXY_CONFIG_SOURCE_KDE; 1012 return PROXY_CONFIG_SOURCE_KDE;
1009 } 1013 }
1010 1014
1011 bool GetString(StringSetting key, std::string* result) override { 1015 bool GetString(StringSetting key, std::string* result) override {
1012 string_map_type::iterator it = string_table_.find(key); 1016 string_map_type::iterator it = string_table_.find(key);
(...skipping 239 matching lines...) Expand 10 before | Expand all | Expand 10 after
1252 AddKDESetting(key, value); 1256 AddKDESetting(key, value);
1253 } 1257 }
1254 } 1258 }
1255 if (ferror(input.get())) 1259 if (ferror(input.get()))
1256 LOG(ERROR) << "error reading " << kioslaverc.value(); 1260 LOG(ERROR) << "error reading " << kioslaverc.value();
1257 ResolveModeEffects(); 1261 ResolveModeEffects();
1258 } 1262 }
1259 1263
1260 // This is the callback from the debounce timer. 1264 // This is the callback from the debounce timer.
1261 void OnDebouncedNotification() { 1265 void OnDebouncedNotification() {
1262 DCHECK(file_task_runner_->BelongsToCurrentThread()); 1266 DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
1263 VLOG(1) << "inotify change notification for kioslaverc"; 1267 VLOG(1) << "inotify change notification for kioslaverc";
1264 UpdateCachedSettings(); 1268 UpdateCachedSettings();
1265 CHECK(notify_delegate_); 1269 CHECK(notify_delegate_);
1266 // Forward to a method on the proxy config service delegate object. 1270 // Forward to a method on the proxy config service delegate object.
1267 notify_delegate_->OnCheckProxyConfigSettings(); 1271 notify_delegate_->OnCheckProxyConfigSettings();
1268 } 1272 }
1269 1273
1270 // Called by OnFileCanReadWithoutBlocking() on the file thread. Reads 1274 // Called by OnFileCanReadWithoutBlocking() on the file thread. Reads
1271 // from the inotify file descriptor and starts up a debounce timer if 1275 // from the inotify file descriptor and starts up a debounce timer if
1272 // an event for kioslaverc is seen. 1276 // an event for kioslaverc is seen.
1273 void OnChangeNotification() { 1277 void OnChangeNotification() {
1274 DCHECK_GE(inotify_fd_, 0); 1278 DCHECK_GE(inotify_fd_, 0);
1275 DCHECK(file_task_runner_->BelongsToCurrentThread()); 1279 DCHECK(file_task_runner_->RunsTasksInCurrentSequence());
1276 char event_buf[(sizeof(inotify_event) + NAME_MAX + 1) * 4]; 1280 char event_buf[(sizeof(inotify_event) + NAME_MAX + 1) * 4];
1277 bool kioslaverc_touched = false; 1281 bool kioslaverc_touched = false;
1278 ssize_t r; 1282 ssize_t r;
1279 while ((r = read(inotify_fd_, event_buf, sizeof(event_buf))) > 0) { 1283 while ((r = read(inotify_fd_, event_buf, sizeof(event_buf))) > 0) {
1280 // inotify returns variable-length structures, which is why we have 1284 // inotify returns variable-length structures, which is why we have
1281 // this strange-looking loop instead of iterating through an array. 1285 // this strange-looking loop instead of iterating through an array.
1282 char* event_ptr = event_buf; 1286 char* event_ptr = event_buf;
1283 while (event_ptr < event_buf + r) { 1287 while (event_ptr < event_buf + r) {
1284 inotify_event* event = reinterpret_cast<inotify_event*>(event_ptr); 1288 inotify_event* event = reinterpret_cast<inotify_event*>(event_ptr);
1285 // The kernel always feeds us whole events. 1289 // The kernel always feeds us whole events.
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
1336 bool reversed_bypass_list_; 1340 bool reversed_bypass_list_;
1337 // We don't own |env_var_getter_|. It's safe to hold a pointer to it, since 1341 // We don't own |env_var_getter_|. It's safe to hold a pointer to it, since
1338 // both it and us are owned by ProxyConfigServiceLinux::Delegate, and have the 1342 // both it and us are owned by ProxyConfigServiceLinux::Delegate, and have the
1339 // same lifetime. 1343 // same lifetime.
1340 base::Environment* env_var_getter_; 1344 base::Environment* env_var_getter_;
1341 1345
1342 // We cache these settings whenever we re-read the kioslaverc file. 1346 // We cache these settings whenever we re-read the kioslaverc file.
1343 string_map_type string_table_; 1347 string_map_type string_table_;
1344 strings_map_type strings_table_; 1348 strings_map_type strings_table_;
1345 1349
1346 // Task runner of the file thread, for reading kioslaverc. If NULL, 1350 // Task runner for doing blocking file IO on, as well as handling inotify
1347 // just read it directly (for testing). We also handle inotify events 1351 // events on.
1348 // on this thread. 1352 scoped_refptr<base::SequencedTaskRunner> file_task_runner_;
1349 scoped_refptr<base::SingleThreadTaskRunner> file_task_runner_;
1350 1353
1351 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplKDE); 1354 DISALLOW_COPY_AND_ASSIGN(SettingGetterImplKDE);
1352 }; 1355 };
1353 1356
1354 } // namespace 1357 } // namespace
1355 1358
1356 bool ProxyConfigServiceLinux::Delegate::GetProxyFromSettings( 1359 bool ProxyConfigServiceLinux::Delegate::GetProxyFromSettings(
1357 SettingGetter::StringSetting host_key, 1360 SettingGetter::StringSetting host_key,
1358 ProxyServer* result_server) { 1361 ProxyServer* result_server) {
1359 std::string host; 1362 std::string host;
(...skipping 200 matching lines...) Expand 10 before | Expand all | Expand 10 after
1560 } 1563 }
1561 1564
1562 ProxyConfigServiceLinux::Delegate::Delegate( 1565 ProxyConfigServiceLinux::Delegate::Delegate(
1563 std::unique_ptr<base::Environment> env_var_getter, 1566 std::unique_ptr<base::Environment> env_var_getter,
1564 SettingGetter* setting_getter) 1567 SettingGetter* setting_getter)
1565 : env_var_getter_(std::move(env_var_getter)), 1568 : env_var_getter_(std::move(env_var_getter)),
1566 setting_getter_(setting_getter) {} 1569 setting_getter_(setting_getter) {}
1567 1570
1568 void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig( 1571 void ProxyConfigServiceLinux::Delegate::SetUpAndFetchInitialConfig(
1569 const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner, 1572 const scoped_refptr<base::SingleThreadTaskRunner>& glib_task_runner,
1570 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner, 1573 const scoped_refptr<base::SingleThreadTaskRunner>& io_task_runner) {
1571 const scoped_refptr<base::SingleThreadTaskRunner>& file_task_runner) {
1572 // We should be running on the default glib main loop thread right 1574 // We should be running on the default glib main loop thread right
1573 // now. gconf can only be accessed from this thread. 1575 // now. gconf can only be accessed from this thread.
1574 DCHECK(glib_task_runner->BelongsToCurrentThread()); 1576 DCHECK(glib_task_runner->RunsTasksInCurrentSequence());
1575 glib_task_runner_ = glib_task_runner; 1577 glib_task_runner_ = glib_task_runner;
1576 io_task_runner_ = io_task_runner; 1578 io_task_runner_ = io_task_runner;
1577 1579
1578 // If we are passed a NULL |io_task_runner| or |file_task_runner|, then we 1580 // If we are passed a NULL |io_task_runner|, then don't set up proxy
1579 // don't set up proxy setting change notifications. This should not be the 1581 // setting change notifications. This should not be the usual case but is
1580 // usual case but is intended to/ simplify test setups. 1582 // intended to/ simplify test setups.
1581 if (!io_task_runner_.get() || !file_task_runner.get()) 1583 if (!io_task_runner_.get())
1582 VLOG(1) << "Monitoring of proxy setting changes is disabled"; 1584 VLOG(1) << "Monitoring of proxy setting changes is disabled";
1583 1585
1584 // Fetch and cache the current proxy config. The config is left in 1586 // Fetch and cache the current proxy config. The config is left in
1585 // cached_config_, where GetLatestProxyConfig() running on the IO thread 1587 // cached_config_, where GetLatestProxyConfig() running on the IO thread
1586 // will expect to find it. This is safe to do because we return 1588 // will expect to find it. This is safe to do because we return
1587 // before this ProxyConfigServiceLinux is passed on to 1589 // before this ProxyConfigServiceLinux is passed on to
1588 // the ProxyService. 1590 // the ProxyService.
1589 1591
1590 // Note: It would be nice to prioritize environment variables 1592 // Note: It would be nice to prioritize environment variables
1591 // and only fall back to gconf if env vars were unset. But 1593 // and only fall back to gconf if env vars were unset. But
1592 // gnome-terminal "helpfully" sets http_proxy and no_proxy, and it 1594 // gnome-terminal "helpfully" sets http_proxy and no_proxy, and it
1593 // does so even if the proxy mode is set to auto, which would 1595 // does so even if the proxy mode is set to auto, which would
1594 // mislead us. 1596 // mislead us.
1595 1597
1596 bool got_config = false; 1598 bool got_config = false;
1597 if (setting_getter_ && 1599 if (setting_getter_ && setting_getter_->Init(glib_task_runner) &&
1598 setting_getter_->Init(glib_task_runner, file_task_runner) &&
1599 GetConfigFromSettings(&cached_config_)) { 1600 GetConfigFromSettings(&cached_config_)) {
1600 cached_config_.set_id(1); // Mark it as valid. 1601 cached_config_.set_id(1); // Mark it as valid.
1601 cached_config_.set_source(setting_getter_->GetConfigSource()); 1602 cached_config_.set_source(setting_getter_->GetConfigSource());
1602 VLOG(1) << "Obtained proxy settings from " 1603 VLOG(1) << "Obtained proxy settings from "
1603 << ProxyConfigSourceToString(cached_config_.source()); 1604 << ProxyConfigSourceToString(cached_config_.source());
1604 1605
1605 // If gconf proxy mode is "none", meaning direct, then we take 1606 // If gconf proxy mode is "none", meaning direct, then we take
1606 // that to be a valid config and will not check environment 1607 // that to be a valid config and will not check environment
1607 // variables. The alternative would have been to look for a proxy 1608 // variables. The alternative would have been to look for a proxy
1608 // whereever we can find one. 1609 // whereever we can find one.
1609 got_config = true; 1610 got_config = true;
1610 1611
1611 // Keep a copy of the config for use from this thread for 1612 // Keep a copy of the config for use from this thread for
1612 // comparison with updated settings when we get notifications. 1613 // comparison with updated settings when we get notifications.
1613 reference_config_ = cached_config_; 1614 reference_config_ = cached_config_;
1614 reference_config_.set_id(1); // Mark it as valid. 1615 reference_config_.set_id(1); // Mark it as valid.
1615 1616
1616 // We only set up notifications if we have IO and file loops available. 1617 // We only set up notifications if we have IO and file loops available.
1617 // We do this after getting the initial configuration so that we don't have 1618 // We do this after getting the initial configuration so that we don't have
1618 // to worry about cancelling it if the initial fetch above fails. Note that 1619 // to worry about cancelling it if the initial fetch above fails. Note that
1619 // setting up notifications has the side effect of simulating a change, so 1620 // setting up notifications has the side effect of simulating a change, so
1620 // that we won't lose any updates that may have happened after the initial 1621 // that we won't lose any updates that may have happened after the initial
1621 // fetch and before setting up notifications. We'll detect the common case 1622 // fetch and before setting up notifications. We'll detect the common case
1622 // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it. 1623 // of no changes in OnCheckProxyConfigSettings() (or sooner) and ignore it.
1623 if (io_task_runner.get() && file_task_runner.get()) { 1624 if (io_task_runner.get()) {
1624 scoped_refptr<base::SingleThreadTaskRunner> required_loop = 1625 scoped_refptr<base::SequencedTaskRunner> required_loop =
1625 setting_getter_->GetNotificationTaskRunner(); 1626 setting_getter_->GetNotificationTaskRunner();
1626 if (!required_loop.get() || required_loop->BelongsToCurrentThread()) { 1627 if (!required_loop.get() || required_loop->RunsTasksInCurrentSequence()) {
1627 // In this case we are already on an acceptable thread. 1628 // In this case we are already on an acceptable thread.
1628 SetUpNotifications(); 1629 SetUpNotifications();
1629 } else { 1630 } else {
1630 // Post a task to set up notifications. We don't wait for success. 1631 // Post a task to set up notifications. We don't wait for success.
1631 required_loop->PostTask(FROM_HERE, base::Bind( 1632 required_loop->PostTask(FROM_HERE, base::Bind(
1632 &ProxyConfigServiceLinux::Delegate::SetUpNotifications, this)); 1633 &ProxyConfigServiceLinux::Delegate::SetUpNotifications, this));
1633 } 1634 }
1634 } 1635 }
1635 } 1636 }
1636 1637
1637 if (!got_config) { 1638 if (!got_config) {
1638 // We fall back on environment variables. 1639 // We fall back on environment variables.
1639 // 1640 //
1640 // Consulting environment variables doesn't need to be done from the 1641 // Consulting environment variables doesn't need to be done from the
1641 // default glib main loop, but it's a tiny enough amount of work. 1642 // default glib main loop, but it's a tiny enough amount of work.
1642 if (GetConfigFromEnv(&cached_config_)) { 1643 if (GetConfigFromEnv(&cached_config_)) {
1643 cached_config_.set_source(PROXY_CONFIG_SOURCE_ENV); 1644 cached_config_.set_source(PROXY_CONFIG_SOURCE_ENV);
1644 cached_config_.set_id(1); // Mark it as valid. 1645 cached_config_.set_id(1); // Mark it as valid.
1645 VLOG(1) << "Obtained proxy settings from environment variables"; 1646 VLOG(1) << "Obtained proxy settings from environment variables";
1646 } 1647 }
1647 } 1648 }
1648 } 1649 }
1649 1650
1650 // Depending on the SettingGetter in use, this method will be called 1651 // Depending on the SettingGetter in use, this method will be called
1651 // on either the UI thread (GConf) or the file thread (KDE). 1652 // on either the UI thread (GConf) or the file thread (KDE).
1652 void ProxyConfigServiceLinux::Delegate::SetUpNotifications() { 1653 void ProxyConfigServiceLinux::Delegate::SetUpNotifications() {
1653 scoped_refptr<base::SingleThreadTaskRunner> required_loop = 1654 scoped_refptr<base::SequencedTaskRunner> required_loop =
1654 setting_getter_->GetNotificationTaskRunner(); 1655 setting_getter_->GetNotificationTaskRunner();
1655 DCHECK(!required_loop.get() || required_loop->BelongsToCurrentThread()); 1656 DCHECK(!required_loop.get() || required_loop->RunsTasksInCurrentSequence());
1656 if (!setting_getter_->SetUpNotifications(this)) 1657 if (!setting_getter_->SetUpNotifications(this))
1657 LOG(ERROR) << "Unable to set up proxy configuration change notifications"; 1658 LOG(ERROR) << "Unable to set up proxy configuration change notifications";
1658 } 1659 }
1659 1660
1660 void ProxyConfigServiceLinux::Delegate::AddObserver(Observer* observer) { 1661 void ProxyConfigServiceLinux::Delegate::AddObserver(Observer* observer) {
1661 observers_.AddObserver(observer); 1662 observers_.AddObserver(observer);
1662 } 1663 }
1663 1664
1664 void ProxyConfigServiceLinux::Delegate::RemoveObserver(Observer* observer) { 1665 void ProxyConfigServiceLinux::Delegate::RemoveObserver(Observer* observer) {
1665 observers_.RemoveObserver(observer); 1666 observers_.RemoveObserver(observer);
1666 } 1667 }
1667 1668
1668 ProxyConfigService::ConfigAvailability 1669 ProxyConfigService::ConfigAvailability
1669 ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig( 1670 ProxyConfigServiceLinux::Delegate::GetLatestProxyConfig(
1670 ProxyConfig* config) { 1671 ProxyConfig* config) {
1671 // This is called from the IO thread. 1672 // This is called from the IO thread.
1672 DCHECK(!io_task_runner_.get() || 1673 DCHECK(!io_task_runner_.get() ||
1673 io_task_runner_->BelongsToCurrentThread()); 1674 io_task_runner_->RunsTasksInCurrentSequence());
1674 1675
1675 // Simply return the last proxy configuration that glib_default_loop 1676 // Simply return the last proxy configuration that glib_default_loop
1676 // notified us of. 1677 // notified us of.
1677 if (cached_config_.is_valid()) { 1678 if (cached_config_.is_valid()) {
1678 *config = cached_config_; 1679 *config = cached_config_;
1679 } else { 1680 } else {
1680 *config = ProxyConfig::CreateDirect(); 1681 *config = ProxyConfig::CreateDirect();
1681 config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED); 1682 config->set_source(PROXY_CONFIG_SOURCE_SYSTEM_FAILED);
1682 } 1683 }
1683 1684
1684 // We return CONFIG_VALID to indicate that *config was filled in. It is always 1685 // We return CONFIG_VALID to indicate that *config was filled in. It is always
1685 // going to be available since we initialized eagerly on the UI thread. 1686 // going to be available since we initialized eagerly on the UI thread.
1686 // TODO(eroman): do lazy initialization instead, so we no longer need 1687 // TODO(eroman): do lazy initialization instead, so we no longer need
1687 // to construct ProxyConfigServiceLinux on the UI thread. 1688 // to construct ProxyConfigServiceLinux on the UI thread.
1688 // In which case, we may return false here. 1689 // In which case, we may return false here.
1689 return CONFIG_VALID; 1690 return CONFIG_VALID;
1690 } 1691 }
1691 1692
1692 // Depending on the SettingGetter in use, this method will be called 1693 // Depending on the SettingGetter in use, this method will be called
1693 // on either the UI thread (GConf) or the file thread (KDE). 1694 // on either the UI thread (GConf) or the file thread (KDE).
1694 void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() { 1695 void ProxyConfigServiceLinux::Delegate::OnCheckProxyConfigSettings() {
1695 scoped_refptr<base::SingleThreadTaskRunner> required_loop = 1696 scoped_refptr<base::SequencedTaskRunner> required_loop =
1696 setting_getter_->GetNotificationTaskRunner(); 1697 setting_getter_->GetNotificationTaskRunner();
1697 DCHECK(!required_loop.get() || required_loop->BelongsToCurrentThread()); 1698 DCHECK(!required_loop.get() || required_loop->RunsTasksInCurrentSequence());
1698 ProxyConfig new_config; 1699 ProxyConfig new_config;
1699 bool valid = GetConfigFromSettings(&new_config); 1700 bool valid = GetConfigFromSettings(&new_config);
1700 if (valid) 1701 if (valid)
1701 new_config.set_id(1); // mark it as valid 1702 new_config.set_id(1); // mark it as valid
1702 1703
1703 // See if it is different from what we had before. 1704 // See if it is different from what we had before.
1704 if (new_config.is_valid() != reference_config_.is_valid() || 1705 if (new_config.is_valid() != reference_config_.is_valid() ||
1705 !new_config.Equals(reference_config_)) { 1706 !new_config.Equals(reference_config_)) {
1706 // Post a task to the IO thread with the new configuration, so it can 1707 // Post a task to the IO thread with the new configuration, so it can
1707 // update |cached_config_|. 1708 // update |cached_config_|.
1708 io_task_runner_->PostTask(FROM_HERE, base::Bind( 1709 io_task_runner_->PostTask(FROM_HERE, base::Bind(
1709 &ProxyConfigServiceLinux::Delegate::SetNewProxyConfig, 1710 &ProxyConfigServiceLinux::Delegate::SetNewProxyConfig,
1710 this, new_config)); 1711 this, new_config));
1711 // Update the thread-private copy in |reference_config_| as well. 1712 // Update the thread-private copy in |reference_config_| as well.
1712 reference_config_ = new_config; 1713 reference_config_ = new_config;
1713 } else { 1714 } else {
1714 VLOG(1) << "Detected no-op change to proxy settings. Doing nothing."; 1715 VLOG(1) << "Detected no-op change to proxy settings. Doing nothing.";
1715 } 1716 }
1716 } 1717 }
1717 1718
1718 void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig( 1719 void ProxyConfigServiceLinux::Delegate::SetNewProxyConfig(
1719 const ProxyConfig& new_config) { 1720 const ProxyConfig& new_config) {
1720 DCHECK(io_task_runner_->BelongsToCurrentThread()); 1721 DCHECK(io_task_runner_->RunsTasksInCurrentSequence());
1721 VLOG(1) << "Proxy configuration changed"; 1722 VLOG(1) << "Proxy configuration changed";
1722 cached_config_ = new_config; 1723 cached_config_ = new_config;
1723 for (auto& observer : observers_) 1724 for (auto& observer : observers_)
1724 observer.OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID); 1725 observer.OnProxyConfigChanged(new_config, ProxyConfigService::CONFIG_VALID);
1725 } 1726 }
1726 1727
1727 void ProxyConfigServiceLinux::Delegate::PostDestroyTask() { 1728 void ProxyConfigServiceLinux::Delegate::PostDestroyTask() {
1728 if (!setting_getter_) 1729 if (!setting_getter_)
1729 return; 1730 return;
1730 1731
1731 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop = 1732 scoped_refptr<base::SequencedTaskRunner> shutdown_loop =
1732 setting_getter_->GetNotificationTaskRunner(); 1733 setting_getter_->GetNotificationTaskRunner();
1733 if (!shutdown_loop.get() || shutdown_loop->BelongsToCurrentThread()) { 1734 if (!shutdown_loop.get() || shutdown_loop->RunsTasksInCurrentSequence()) {
1734 // Already on the right thread, call directly. 1735 // Already on the right thread, call directly.
1735 // This is the case for the unittests. 1736 // This is the case for the unittests.
1736 OnDestroy(); 1737 OnDestroy();
1737 } else { 1738 } else {
1738 // Post to shutdown thread. Note that on browser shutdown, we may quit 1739 // Post to shutdown thread. Note that on browser shutdown, we may quit
1739 // this MessageLoop and exit the program before ever running this. 1740 // this MessageLoop and exit the program before ever running this.
1740 shutdown_loop->PostTask(FROM_HERE, base::Bind( 1741 shutdown_loop->PostTask(FROM_HERE, base::Bind(
1741 &ProxyConfigServiceLinux::Delegate::OnDestroy, this)); 1742 &ProxyConfigServiceLinux::Delegate::OnDestroy, this));
1742 } 1743 }
1743 } 1744 }
1744 void ProxyConfigServiceLinux::Delegate::OnDestroy() { 1745 void ProxyConfigServiceLinux::Delegate::OnDestroy() {
1745 scoped_refptr<base::SingleThreadTaskRunner> shutdown_loop = 1746 scoped_refptr<base::SequencedTaskRunner> shutdown_loop =
1746 setting_getter_->GetNotificationTaskRunner(); 1747 setting_getter_->GetNotificationTaskRunner();
1747 DCHECK(!shutdown_loop.get() || shutdown_loop->BelongsToCurrentThread()); 1748 DCHECK(!shutdown_loop.get() || shutdown_loop->RunsTasksInCurrentSequence());
1748 setting_getter_->ShutDown(); 1749 setting_getter_->ShutDown();
1749 } 1750 }
1750 1751
1751 ProxyConfigServiceLinux::ProxyConfigServiceLinux() 1752 ProxyConfigServiceLinux::ProxyConfigServiceLinux()
1752 : delegate_(new Delegate(base::Environment::Create())) { 1753 : delegate_(new Delegate(base::Environment::Create())) {
1753 } 1754 }
1754 1755
1755 ProxyConfigServiceLinux::~ProxyConfigServiceLinux() { 1756 ProxyConfigServiceLinux::~ProxyConfigServiceLinux() {
1756 delegate_->PostDestroyTask(); 1757 delegate_->PostDestroyTask();
1757 } 1758 }
(...skipping 14 matching lines...) Expand all
1772 void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) { 1773 void ProxyConfigServiceLinux::RemoveObserver(Observer* observer) {
1773 delegate_->RemoveObserver(observer); 1774 delegate_->RemoveObserver(observer);
1774 } 1775 }
1775 1776
1776 ProxyConfigService::ConfigAvailability 1777 ProxyConfigService::ConfigAvailability
1777 ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) { 1778 ProxyConfigServiceLinux::GetLatestProxyConfig(ProxyConfig* config) {
1778 return delegate_->GetLatestProxyConfig(config); 1779 return delegate_->GetLatestProxyConfig(config);
1779 } 1780 }
1780 1781
1781 } // namespace net 1782 } // namespace net
OLDNEW
« no previous file with comments | « net/proxy/proxy_config_service_linux.h ('k') | net/proxy/proxy_config_service_linux_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698