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 #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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 Loading... |
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 |
OLD | NEW |