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..e8ff4dd8a239f9a68077ffadcd7656cdd4abf7f9 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. |
| + void InitAfterConstructor() { |
| PostTaskToTaskRunnerThread( |
| base::BindOnce(&NotificationPlatformBridgeLinuxImpl::Init, this)); |
| } |
| @@ -188,6 +198,15 @@ class NotificationPlatformBridgeLinuxImpl |
| } |
| } |
| + void CleanUp() { |
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
| + if (cleanup_posted_) |
| + return; |
| + PostTaskToTaskRunnerThread(base::BindOnce( |
| + &NotificationPlatformBridgeLinuxImpl::CleanUpOnTaskRunner, this)); |
| + cleanup_posted_ = true; |
|
Peter Beverloo
2017/05/02 13:50:21
Instead of introducing cleanup_posted_, can we jus
Tom (Use chromium acct)
2017/05/02 21:23:16
Done.
FYI I added |cleanup_posted_| to catch the
|
| + } |
| + |
| private: |
| friend class base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl>; |
| @@ -238,7 +257,9 @@ class NotificationPlatformBridgeLinuxImpl |
| }; |
| ~NotificationPlatformBridgeLinuxImpl() override { |
| + DCHECK(cleanup_posted_); |
| DCHECK(!bus_); |
| + DCHECK(!notification_proxy_); |
| DCHECK(notifications_.empty()); |
| } |
| @@ -269,11 +290,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_) { |
| + 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,15 +323,6 @@ 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(); |
| @@ -609,7 +623,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 +660,7 @@ void NotificationPlatformBridgeLinux::SetReadyCallback( |
| NotificationBridgeReadyCallback callback) { |
| impl_->SetReadyCallback(std::move(callback)); |
| } |
| + |
| +void NotificationPlatformBridgeLinux::CleanUp() { |
| + impl_->CleanUp(); |
| +} |