Chromium Code Reviews| Index: chrome/browser/notifications/notification_platform_bridge_linux.cc |
| diff --git a/chrome/browser/notifications/notification_platform_bridge_linux.cc b/chrome/browser/notifications/notification_platform_bridge_linux.cc |
| index cf71db8869d0a8a1c7c5f89085a7fd8338243d6c..f0f34a0742f86ea63d03baad46e7acf98ac218ad 100644 |
| --- a/chrome/browser/notifications/notification_platform_bridge_linux.cc |
| +++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc |
| @@ -127,12 +127,22 @@ class NotificationPlatformBridgeLinuxImpl |
| public content::NotificationObserver, |
| public base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl> { |
| public: |
| - NotificationPlatformBridgeLinuxImpl() |
| - : task_runner_(base::CreateSingleThreadTaskRunnerWithTraits( |
| - base::TaskTraits().MayBlock().WithPriority( |
| - base::TaskPriority::USER_BLOCKING))) { |
| + explicit NotificationPlatformBridgeLinuxImpl(scoped_refptr<dbus::Bus> bus) |
| + : bus_(bus) { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + task_runner_ = base::CreateSingleThreadTaskRunnerWithTraits( |
| + base::TaskTraits().MayBlock().WithPriority( |
| + base::TaskPriority::USER_BLOCKING)); |
| registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, |
| content::NotificationService::AllSources()); |
| + } |
| + |
| + // Init() cannot be called from within the constructor because of a |
| + // race condition. The reference count for |this| starts out as 0. |
| + // Posting the Init task would increment the count to 1. If the |
| + // task finishes before the constructor returns, the count will go |
| + // to 0 and the object would be prematurely destructed. |
|
Peter Beverloo
2017/05/03 00:31:26
Thank you for the detailed comment!
|
| + void InitAfterConstructor() { |
|
Lei Zhang
2017/05/03 01:10:45
This can be Init(), and Init() can be InitOnTaskRu
Tom (Use chromium acct)
2017/05/03 01:22:17
Done.
|
| PostTaskToTaskRunnerThread( |
| base::BindOnce(&NotificationPlatformBridgeLinuxImpl::Init, this)); |
| } |
| @@ -188,6 +198,12 @@ class NotificationPlatformBridgeLinuxImpl |
| } |
| } |
| + void CleanUp() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + PostTaskToTaskRunnerThread(base::BindOnce( |
| + &NotificationPlatformBridgeLinuxImpl::CleanUpOnTaskRunner, this)); |
| + } |
| + |
| private: |
| friend class base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl>; |
| @@ -239,6 +255,7 @@ class NotificationPlatformBridgeLinuxImpl |
| ~NotificationPlatformBridgeLinuxImpl() override { |
| DCHECK(!bus_); |
| + DCHECK(!notification_proxy_); |
| DCHECK(notifications_.empty()); |
| } |
| @@ -269,11 +286,13 @@ class NotificationPlatformBridgeLinuxImpl |
| // Sets up the D-Bus connection. |
| void Init() { |
| DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| - dbus::Bus::Options bus_options; |
| - bus_options.bus_type = dbus::Bus::SESSION; |
| - bus_options.connection_type = dbus::Bus::PRIVATE; |
| - bus_options.dbus_task_runner = task_runner_; |
| - bus_ = make_scoped_refptr(new dbus::Bus(bus_options)); |
| + if (!bus_) { |
|
Lei Zhang
2017/05/03 01:10:46
May be good to mention this happens under normal c
Tom (Use chromium acct)
2017/05/03 01:22:17
Done.
|
| + dbus::Bus::Options bus_options; |
| + bus_options.bus_type = dbus::Bus::SESSION; |
| + bus_options.connection_type = dbus::Bus::PRIVATE; |
| + bus_options.dbus_task_runner = task_runner_; |
| + bus_ = make_scoped_refptr(new dbus::Bus(bus_options)); |
| + } |
| notification_proxy_ = |
| bus_->GetObjectProxy(kFreedesktopNotificationsName, |
| @@ -300,18 +319,10 @@ class NotificationPlatformBridgeLinuxImpl |
| this)); |
| } |
| - void CleanUp() { |
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| - if (cleanup_posted_) |
| - return; |
| - PostTaskToTaskRunnerThread(base::BindOnce( |
| - &NotificationPlatformBridgeLinuxImpl::CleanUpOnTaskRunner, this)); |
| - cleanup_posted_ = true; |
| - } |
| - |
| void CleanUpOnTaskRunner() { |
| DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| - bus_->ShutdownAndBlock(); |
| + if (bus_) |
| + bus_->ShutdownAndBlock(); |
| bus_ = nullptr; |
| notification_proxy_ = nullptr; |
| notifications_.clear(); |
| @@ -586,8 +597,6 @@ class NotificationPlatformBridgeLinuxImpl |
| base::Optional<bool> connected_; |
| std::vector<NotificationBridgeReadyCallback> on_connected_callbacks_; |
| - bool cleanup_posted_ = false; |
| - |
| ////////////////////////////////////////////////////////////////////////////// |
| // Members used only on the task runner thread. |
| @@ -609,7 +618,13 @@ class NotificationPlatformBridgeLinuxImpl |
| }; |
| NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux() |
| - : impl_(new NotificationPlatformBridgeLinuxImpl()) {} |
| + : NotificationPlatformBridgeLinux(nullptr) {} |
| + |
| +NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux( |
| + scoped_refptr<dbus::Bus> bus) |
| + : impl_(new NotificationPlatformBridgeLinuxImpl(bus)) { |
| + impl_->InitAfterConstructor(); |
| +} |
| NotificationPlatformBridgeLinux::~NotificationPlatformBridgeLinux() = default; |
| @@ -640,3 +655,7 @@ void NotificationPlatformBridgeLinux::SetReadyCallback( |
| NotificationBridgeReadyCallback callback) { |
| impl_->SetReadyCallback(std::move(callback)); |
| } |
| + |
| +void NotificationPlatformBridgeLinux::CleanUp() { |
| + impl_->CleanUp(); |
| +} |