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

Side by Side Diff: chrome/browser/notifications/notification_platform_bridge_linux.cc

Issue 2849003002: Linux native notifications: Add initial unit test (Closed)
Patch Set: Use TestBrowserThreadBundle Created 3 years, 7 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 unified diff | Download patch
OLDNEW
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 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 "chrome/browser/notifications/notification_platform_bridge_linux.h" 5 #include "chrome/browser/notifications/notification_platform_bridge_linux.h"
6 6
7 #include <algorithm> 7 #include <algorithm>
8 8
9 #include "base/barrier_closure.h" 9 #include "base/barrier_closure.h"
10 #include "base/files/file_util.h" 10 #include "base/files/file_util.h"
(...skipping 109 matching lines...) Expand 10 before | Expand all | Expand 10 after
120 // static 120 // static
121 NotificationPlatformBridge* NotificationPlatformBridge::Create() { 121 NotificationPlatformBridge* NotificationPlatformBridge::Create() {
122 return new NotificationPlatformBridgeLinux(); 122 return new NotificationPlatformBridgeLinux();
123 } 123 }
124 124
125 class NotificationPlatformBridgeLinuxImpl 125 class NotificationPlatformBridgeLinuxImpl
126 : public NotificationPlatformBridge, 126 : public NotificationPlatformBridge,
127 public content::NotificationObserver, 127 public content::NotificationObserver,
128 public base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl> { 128 public base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl> {
129 public: 129 public:
130 NotificationPlatformBridgeLinuxImpl() 130 explicit NotificationPlatformBridgeLinuxImpl(scoped_refptr<dbus::Bus> bus)
131 : task_runner_(base::CreateSingleThreadTaskRunnerWithTraits( 131 : bus_(bus) {
132 base::TaskTraits().MayBlock().WithPriority( 132 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
133 base::TaskPriority::USER_BLOCKING))) { 133 task_runner_ = base::CreateSingleThreadTaskRunnerWithTraits(
134 base::TaskTraits().MayBlock().WithPriority(
135 base::TaskPriority::USER_BLOCKING));
134 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, 136 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
135 content::NotificationService::AllSources()); 137 content::NotificationService::AllSources());
138 }
139
140 // Init() cannot be called from within the constructor because of a
141 // race condition. The reference count for |this| starts out as 0.
142 // Posting the Init task would increment the count to 1. If the
143 // task finishes before the constructor returns, the count will go
144 // to 0 and the object would be prematurely destructed.
145 void InitAfterConstructor() {
136 PostTaskToTaskRunnerThread( 146 PostTaskToTaskRunnerThread(
137 base::BindOnce(&NotificationPlatformBridgeLinuxImpl::Init, this)); 147 base::BindOnce(&NotificationPlatformBridgeLinuxImpl::Init, this));
138 } 148 }
139 149
140 void Display(NotificationCommon::Type notification_type, 150 void Display(NotificationCommon::Type notification_type,
141 const std::string& notification_id, 151 const std::string& notification_id,
142 const std::string& profile_id, 152 const std::string& profile_id,
143 bool is_incognito, 153 bool is_incognito,
144 const Notification& notification) override { 154 const Notification& notification) override {
145 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 155 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
181 191
182 void SetReadyCallback(NotificationBridgeReadyCallback callback) override { 192 void SetReadyCallback(NotificationBridgeReadyCallback callback) override {
183 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 193 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
184 if (connected_.has_value()) { 194 if (connected_.has_value()) {
185 std::move(callback).Run(connected_.value()); 195 std::move(callback).Run(connected_.value());
186 } else { 196 } else {
187 on_connected_callbacks_.push_back(std::move(callback)); 197 on_connected_callbacks_.push_back(std::move(callback));
188 } 198 }
189 } 199 }
190 200
201 void CleanUp() {
202 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
203 if (cleanup_posted_)
204 return;
205 PostTaskToTaskRunnerThread(base::BindOnce(
206 &NotificationPlatformBridgeLinuxImpl::CleanUpOnTaskRunner, this));
207 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
208 }
209
191 private: 210 private:
192 friend class base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl>; 211 friend class base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl>;
193 212
194 struct ResourceFile { 213 struct ResourceFile {
195 explicit ResourceFile(const base::FilePath& file_path) 214 explicit ResourceFile(const base::FilePath& file_path)
196 : file_path(file_path) {} 215 : file_path(file_path) {}
197 ~ResourceFile() { base::DeleteFile(file_path, false); } 216 ~ResourceFile() { base::DeleteFile(file_path, false); }
198 const base::FilePath file_path; 217 const base::FilePath file_path;
199 }; 218 };
200 219
(...skipping 30 matching lines...) Expand all
231 size_t action_start = 0; 250 size_t action_start = 0;
232 size_t action_end = 0; 251 size_t action_end = 0;
233 252
234 // Temporary resource files associated with the notification that 253 // Temporary resource files associated with the notification that
235 // should be cleaned up when the notification is closed or on 254 // should be cleaned up when the notification is closed or on
236 // shutdown. 255 // shutdown.
237 std::vector<std::unique_ptr<ResourceFile>> resource_files; 256 std::vector<std::unique_ptr<ResourceFile>> resource_files;
238 }; 257 };
239 258
240 ~NotificationPlatformBridgeLinuxImpl() override { 259 ~NotificationPlatformBridgeLinuxImpl() override {
260 DCHECK(cleanup_posted_);
241 DCHECK(!bus_); 261 DCHECK(!bus_);
262 DCHECK(!notification_proxy_);
242 DCHECK(notifications_.empty()); 263 DCHECK(notifications_.empty());
243 } 264 }
244 265
245 void Observe(int type, 266 void Observe(int type,
246 const content::NotificationSource& source, 267 const content::NotificationSource& source,
247 const content::NotificationDetails& details) override { 268 const content::NotificationDetails& details) override {
248 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 269 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
249 DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type); 270 DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type);
250 // The browser process is about to exit. Post the CleanUp() task 271 // The browser process is about to exit. Post the CleanUp() task
251 // while we still can. 272 // while we still can.
(...skipping 10 matching lines...) Expand all
262 void PostTaskToTaskRunnerThread(base::OnceClosure closure) const { 283 void PostTaskToTaskRunnerThread(base::OnceClosure closure) const {
263 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 284 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
264 DCHECK(task_runner_); 285 DCHECK(task_runner_);
265 bool success = task_runner_->PostTask(FROM_HERE, std::move(closure)); 286 bool success = task_runner_->PostTask(FROM_HERE, std::move(closure));
266 DCHECK(success); 287 DCHECK(success);
267 } 288 }
268 289
269 // Sets up the D-Bus connection. 290 // Sets up the D-Bus connection.
270 void Init() { 291 void Init() {
271 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 292 DCHECK(task_runner_->RunsTasksOnCurrentThread());
272 dbus::Bus::Options bus_options; 293 if (!bus_) {
273 bus_options.bus_type = dbus::Bus::SESSION; 294 dbus::Bus::Options bus_options;
274 bus_options.connection_type = dbus::Bus::PRIVATE; 295 bus_options.bus_type = dbus::Bus::SESSION;
275 bus_options.dbus_task_runner = task_runner_; 296 bus_options.connection_type = dbus::Bus::PRIVATE;
276 bus_ = make_scoped_refptr(new dbus::Bus(bus_options)); 297 bus_options.dbus_task_runner = task_runner_;
298 bus_ = make_scoped_refptr(new dbus::Bus(bus_options));
299 }
277 300
278 notification_proxy_ = 301 notification_proxy_ =
279 bus_->GetObjectProxy(kFreedesktopNotificationsName, 302 bus_->GetObjectProxy(kFreedesktopNotificationsName,
280 dbus::ObjectPath(kFreedesktopNotificationsPath)); 303 dbus::ObjectPath(kFreedesktopNotificationsPath));
281 if (!notification_proxy_) { 304 if (!notification_proxy_) {
282 OnConnectionInitializationFinishedOnTaskRunner(false); 305 OnConnectionInitializationFinishedOnTaskRunner(false);
283 return; 306 return;
284 } 307 }
285 308
286 connected_signals_barrier_ = base::BarrierClosure( 309 connected_signals_barrier_ = base::BarrierClosure(
287 2, base::Bind(&NotificationPlatformBridgeLinuxImpl:: 310 2, base::Bind(&NotificationPlatformBridgeLinuxImpl::
288 OnConnectionInitializationFinishedOnTaskRunner, 311 OnConnectionInitializationFinishedOnTaskRunner,
289 this, true)); 312 this, true));
290 notification_proxy_->ConnectToSignal( 313 notification_proxy_->ConnectToSignal(
291 kFreedesktopNotificationsName, "ActionInvoked", 314 kFreedesktopNotificationsName, "ActionInvoked",
292 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this), 315 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this),
293 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, 316 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected,
294 this)); 317 this));
295 notification_proxy_->ConnectToSignal( 318 notification_proxy_->ConnectToSignal(
296 kFreedesktopNotificationsName, "NotificationClosed", 319 kFreedesktopNotificationsName, "NotificationClosed",
297 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnNotificationClosed, 320 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnNotificationClosed,
298 this), 321 this),
299 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, 322 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected,
300 this)); 323 this));
301 } 324 }
302 325
303 void CleanUp() {
304 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
305 if (cleanup_posted_)
306 return;
307 PostTaskToTaskRunnerThread(base::BindOnce(
308 &NotificationPlatformBridgeLinuxImpl::CleanUpOnTaskRunner, this));
309 cleanup_posted_ = true;
310 }
311
312 void CleanUpOnTaskRunner() { 326 void CleanUpOnTaskRunner() {
313 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 327 DCHECK(task_runner_->RunsTasksOnCurrentThread());
314 bus_->ShutdownAndBlock(); 328 bus_->ShutdownAndBlock();
315 bus_ = nullptr; 329 bus_ = nullptr;
316 notification_proxy_ = nullptr; 330 notification_proxy_ = nullptr;
317 notifications_.clear(); 331 notifications_.clear();
318 } 332 }
319 333
320 // Makes the "Notify" call to D-Bus. 334 // Makes the "Notify" call to D-Bus.
321 void DisplayOnTaskRunner(NotificationCommon::Type notification_type, 335 void DisplayOnTaskRunner(NotificationCommon::Type notification_type,
(...skipping 280 matching lines...) Expand 10 before | Expand all | Expand 10 after
602 // argument, so the data would get double-destructed. 616 // argument, so the data would get double-destructed.
603 template <typename T> 617 template <typename T>
604 using UnorderedUniqueSet = std::unordered_map<T*, std::unique_ptr<T>>; 618 using UnorderedUniqueSet = std::unordered_map<T*, std::unique_ptr<T>>;
605 619
606 UnorderedUniqueSet<NotificationData> notifications_; 620 UnorderedUniqueSet<NotificationData> notifications_;
607 621
608 DISALLOW_COPY_AND_ASSIGN(NotificationPlatformBridgeLinuxImpl); 622 DISALLOW_COPY_AND_ASSIGN(NotificationPlatformBridgeLinuxImpl);
609 }; 623 };
610 624
611 NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux() 625 NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux()
612 : impl_(new NotificationPlatformBridgeLinuxImpl()) {} 626 : NotificationPlatformBridgeLinux(nullptr) {}
627
628 NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux(
629 scoped_refptr<dbus::Bus> bus)
630 : impl_(new NotificationPlatformBridgeLinuxImpl(bus)) {
631 impl_->InitAfterConstructor();
632 }
613 633
614 NotificationPlatformBridgeLinux::~NotificationPlatformBridgeLinux() = default; 634 NotificationPlatformBridgeLinux::~NotificationPlatformBridgeLinux() = default;
615 635
616 void NotificationPlatformBridgeLinux::Display( 636 void NotificationPlatformBridgeLinux::Display(
617 NotificationCommon::Type notification_type, 637 NotificationCommon::Type notification_type,
618 const std::string& notification_id, 638 const std::string& notification_id,
619 const std::string& profile_id, 639 const std::string& profile_id,
620 bool is_incognito, 640 bool is_incognito,
621 const Notification& notification) { 641 const Notification& notification) {
622 impl_->Display(notification_type, notification_id, profile_id, is_incognito, 642 impl_->Display(notification_type, notification_id, profile_id, is_incognito,
(...skipping 10 matching lines...) Expand all
633 const std::string& profile_id, 653 const std::string& profile_id,
634 bool incognito, 654 bool incognito,
635 const GetDisplayedNotificationsCallback& callback) const { 655 const GetDisplayedNotificationsCallback& callback) const {
636 impl_->GetDisplayed(profile_id, incognito, callback); 656 impl_->GetDisplayed(profile_id, incognito, callback);
637 } 657 }
638 658
639 void NotificationPlatformBridgeLinux::SetReadyCallback( 659 void NotificationPlatformBridgeLinux::SetReadyCallback(
640 NotificationBridgeReadyCallback callback) { 660 NotificationBridgeReadyCallback callback) {
641 impl_->SetReadyCallback(std::move(callback)); 661 impl_->SetReadyCallback(std::move(callback));
642 } 662 }
663
664 void NotificationPlatformBridgeLinux::CleanUp() {
665 impl_->CleanUp();
666 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698