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

Unified Diff: chrome/browser/notifications/notification_platform_bridge_linux.cc

Issue 2849003002: Linux native notifications: Add initial unit test (Closed)
Patch Set: Created 3 years, 8 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 side-by-side diff with in-line comments
Download patch
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();
+}

Powered by Google App Engine
This is Rietveld 408576698