| 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..bd4c1764014d64fb7b4b4423adbe149acfa40e28 100644
|
| --- a/chrome/browser/notifications/notification_platform_bridge_linux.cc
|
| +++ b/chrome/browser/notifications/notification_platform_bridge_linux.cc
|
| @@ -88,7 +88,6 @@ void ForwardNotificationOperationOnUiThread(
|
| int action_index,
|
| const std::string& profile_id,
|
| bool is_incognito) {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| ProfileManager* profile_manager = g_browser_process->profile_manager();
|
|
|
| profile_manager->LoadProfile(
|
| @@ -127,12 +126,29 @@ class NotificationPlatformBridgeLinuxImpl
|
| public content::NotificationObserver,
|
| public base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl> {
|
| public:
|
| - NotificationPlatformBridgeLinuxImpl()
|
| - : task_runner_(base::CreateSingleThreadTaskRunnerWithTraits(
|
| - base::TaskTraits().MayBlock().WithPriority(
|
| - base::TaskPriority::USER_BLOCKING))) {
|
| + NotificationPlatformBridgeLinuxImpl(
|
| + scoped_refptr<base::SequencedTaskRunner> notification_task_runner,
|
| + scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
|
| + scoped_refptr<dbus::Bus> bus)
|
| + : notification_task_runner_(notification_task_runner),
|
| + ui_task_runner_(ui_task_runner),
|
| + bus_(bus) {
|
| + if (!notification_task_runner_) {
|
| + notification_task_runner_ = base::CreateSingleThreadTaskRunnerWithTraits(
|
| + base::TaskTraits().MayBlock().WithPriority(
|
| + base::TaskPriority::USER_BLOCKING));
|
| + }
|
| + DCHECK(ui_task_runner_);
|
| 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));
|
| }
|
| @@ -142,7 +158,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| const std::string& profile_id,
|
| bool is_incognito,
|
| const Notification& notification) override {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| // Notifications contain gfx::Image's which have reference counts
|
| // that are not thread safe. Because of this, we duplicate the
|
| // notification and its images. Wrap the notification in a
|
| @@ -163,7 +179,7 @@ class NotificationPlatformBridgeLinuxImpl
|
|
|
| void Close(const std::string& profile_id,
|
| const std::string& notification_id) override {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| PostTaskToTaskRunnerThread(
|
| base::BindOnce(&NotificationPlatformBridgeLinuxImpl::CloseOnTaskRunner,
|
| this, profile_id, notification_id));
|
| @@ -173,14 +189,14 @@ class NotificationPlatformBridgeLinuxImpl
|
| const std::string& profile_id,
|
| bool incognito,
|
| const GetDisplayedNotificationsCallback& callback) const override {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| PostTaskToTaskRunnerThread(base::BindOnce(
|
| &NotificationPlatformBridgeLinuxImpl::GetDisplayedOnTaskRunner, this,
|
| profile_id, incognito, callback));
|
| }
|
|
|
| void SetReadyCallback(NotificationBridgeReadyCallback callback) override {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| if (connected_.has_value()) {
|
| std::move(callback).Run(connected_.value());
|
| } else {
|
| @@ -188,6 +204,15 @@ class NotificationPlatformBridgeLinuxImpl
|
| }
|
| }
|
|
|
| + void CleanUp() {
|
| + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| + if (cleanup_posted_)
|
| + return;
|
| + PostTaskToTaskRunnerThread(base::BindOnce(
|
| + &NotificationPlatformBridgeLinuxImpl::CleanUpOnTaskRunner, this));
|
| + cleanup_posted_ = true;
|
| + }
|
| +
|
| private:
|
| friend class base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl>;
|
|
|
| @@ -238,14 +263,16 @@ class NotificationPlatformBridgeLinuxImpl
|
| };
|
|
|
| ~NotificationPlatformBridgeLinuxImpl() override {
|
| + DCHECK(cleanup_posted_);
|
| DCHECK(!bus_);
|
| + DCHECK(!notification_proxy_);
|
| DCHECK(notifications_.empty());
|
| }
|
|
|
| void Observe(int type,
|
| const content::NotificationSource& source,
|
| const content::NotificationDetails& details) override {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type);
|
| // The browser process is about to exit. Post the CleanUp() task
|
| // while we still can.
|
| @@ -253,27 +280,30 @@ class NotificationPlatformBridgeLinuxImpl
|
| }
|
|
|
| void PostTaskToUiThread(base::OnceClosure closure) const {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| - bool success = content::BrowserThread::PostTask(
|
| - content::BrowserThread::UI, FROM_HERE, std::move(closure));
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(ui_task_runner_);
|
| + bool success = ui_task_runner_->PostTask(FROM_HERE, std::move(closure));
|
| DCHECK(success);
|
| }
|
|
|
| void PostTaskToTaskRunnerThread(base::OnceClosure closure) const {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| - DCHECK(task_runner_);
|
| - bool success = task_runner_->PostTask(FROM_HERE, std::move(closure));
|
| + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(notification_task_runner_);
|
| + bool success =
|
| + notification_task_runner_->PostTask(FROM_HERE, std::move(closure));
|
| DCHECK(success);
|
| }
|
|
|
| // 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));
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| + 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 = notification_task_runner_;
|
| + bus_ = make_scoped_refptr(new dbus::Bus(bus_options));
|
| + }
|
|
|
| notification_proxy_ =
|
| bus_->GetObjectProxy(kFreedesktopNotificationsName,
|
| @@ -300,17 +330,8 @@ 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());
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| bus_->ShutdownAndBlock();
|
| bus_ = nullptr;
|
| notification_proxy_ = nullptr;
|
| @@ -323,7 +344,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| const std::string& profile_id,
|
| bool is_incognito,
|
| std::unique_ptr<Notification> notification) {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| NotificationData* data =
|
| FindNotificationData(notification_id, profile_id, is_incognito);
|
| if (data) {
|
| @@ -431,7 +452,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| // Makes the "CloseNotification" call to D-Bus.
|
| void CloseOnTaskRunner(const std::string& profile_id,
|
| const std::string& notification_id) {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| std::vector<NotificationData*> to_erase;
|
| for (const auto& pair : notifications_) {
|
| NotificationData* data = pair.first;
|
| @@ -453,7 +474,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| const std::string& profile_id,
|
| bool incognito,
|
| const GetDisplayedNotificationsCallback& callback) const {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| // TODO(thomasanderson): Implement.
|
| PostTaskToUiThread(base::BindOnce(
|
| callback, base::Passed(base::MakeUnique<std::set<std::string>>()),
|
| @@ -463,7 +484,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| NotificationData* FindNotificationData(const std::string& notification_id,
|
| const std::string& profile_id,
|
| bool is_incognito) {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| for (const auto& pair : notifications_) {
|
| NotificationData* data = pair.first;
|
| if (data->notification_id == notification_id &&
|
| @@ -477,7 +498,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| }
|
|
|
| NotificationData* FindNotificationData(uint32_t dbus_id) {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| for (const auto& pair : notifications_) {
|
| NotificationData* data = pair.first;
|
| if (data->dbus_id == dbus_id)
|
| @@ -490,7 +511,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| void ForwardNotificationOperation(NotificationData* data,
|
| NotificationCommon::Operation operation,
|
| int action_index) {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| PostTaskToUiThread(base::BindOnce(
|
| ForwardNotificationOperationOnUiThread, operation,
|
| data->notification_type, data->origin_url.spec(), data->notification_id,
|
| @@ -498,7 +519,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| }
|
|
|
| void OnActionInvoked(dbus::Signal* signal) {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| dbus::MessageReader reader(signal);
|
| uint32_t dbus_id;
|
| if (!reader.PopUint32(&dbus_id))
|
| @@ -529,7 +550,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| }
|
|
|
| void OnNotificationClosed(dbus::Signal* signal) {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| dbus::MessageReader reader(signal);
|
| uint32_t dbus_id;
|
| if (!reader.PopUint32(&dbus_id))
|
| @@ -546,7 +567,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| // Called once the connection has been set up (or not). |success|
|
| // indicates the connection is ready to use.
|
| void OnConnectionInitializationFinishedOnUiThread(bool success) {
|
| - DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| + DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
|
| connected_ = success;
|
| for (auto& callback : on_connected_callbacks_)
|
| std::move(callback).Run(success);
|
| @@ -556,7 +577,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| }
|
|
|
| void OnConnectionInitializationFinishedOnTaskRunner(bool success) {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| PostTaskToUiThread(
|
| base::BindOnce(&NotificationPlatformBridgeLinuxImpl::
|
| OnConnectionInitializationFinishedOnUiThread,
|
| @@ -566,7 +587,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| void OnSignalConnected(const std::string& interface_name,
|
| const std::string& signal_name,
|
| bool success) {
|
| - DCHECK(task_runner_->RunsTasksOnCurrentThread());
|
| + DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
|
| if (!success) {
|
| OnConnectionInitializationFinishedOnTaskRunner(false);
|
| return;
|
| @@ -577,7 +598,7 @@ class NotificationPlatformBridgeLinuxImpl
|
| //////////////////////////////////////////////////////////////////////////////
|
| // Members used only on the UI thread.
|
|
|
| - scoped_refptr<base::SequencedTaskRunner> task_runner_;
|
| + scoped_refptr<base::SequencedTaskRunner> notification_task_runner_;
|
|
|
| content::NotificationRegistrar registrar_;
|
|
|
| @@ -591,6 +612,8 @@ class NotificationPlatformBridgeLinuxImpl
|
| //////////////////////////////////////////////////////////////////////////////
|
| // Members used only on the task runner thread.
|
|
|
| + scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
|
| +
|
| scoped_refptr<dbus::Bus> bus_;
|
|
|
| dbus::ObjectProxy* notification_proxy_ = nullptr;
|
| @@ -609,7 +632,23 @@ class NotificationPlatformBridgeLinuxImpl
|
| };
|
|
|
| NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux()
|
| - : impl_(new NotificationPlatformBridgeLinuxImpl()) {}
|
| + : NotificationPlatformBridgeLinux(
|
| + nullptr,
|
| + content::BrowserThread::GetTaskRunnerForThread(
|
| + content::BrowserThread::UI),
|
| + nullptr) {
|
| + DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
|
| +}
|
| +
|
| +NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux(
|
| + scoped_refptr<base::SequencedTaskRunner> notification_task_runner,
|
| + scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
|
| + scoped_refptr<dbus::Bus> bus)
|
| + : impl_(new NotificationPlatformBridgeLinuxImpl(notification_task_runner,
|
| + ui_task_runner,
|
| + bus)) {
|
| + impl_->InitAfterConstructor();
|
| +}
|
|
|
| NotificationPlatformBridgeLinux::~NotificationPlatformBridgeLinux() = default;
|
|
|
| @@ -640,3 +679,7 @@ void NotificationPlatformBridgeLinux::SetReadyCallback(
|
| NotificationBridgeReadyCallback callback) {
|
| impl_->SetReadyCallback(std::move(callback));
|
| }
|
| +
|
| +void NotificationPlatformBridgeLinux::CleanUp() {
|
| + impl_->CleanUp();
|
| +}
|
|
|