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

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

Issue 2849003002: Linux native notifications: Add initial unit test (Closed)
Patch Set: 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 70 matching lines...) Expand 10 before | Expand all | Expand 10 after
81 } 81 }
82 82
83 void ForwardNotificationOperationOnUiThread( 83 void ForwardNotificationOperationOnUiThread(
84 NotificationCommon::Operation operation, 84 NotificationCommon::Operation operation,
85 NotificationCommon::Type notification_type, 85 NotificationCommon::Type notification_type,
86 const std::string& origin, 86 const std::string& origin,
87 const std::string& notification_id, 87 const std::string& notification_id,
88 int action_index, 88 int action_index,
89 const std::string& profile_id, 89 const std::string& profile_id,
90 bool is_incognito) { 90 bool is_incognito) {
91 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
92 ProfileManager* profile_manager = g_browser_process->profile_manager(); 91 ProfileManager* profile_manager = g_browser_process->profile_manager();
93 92
94 profile_manager->LoadProfile( 93 profile_manager->LoadProfile(
95 profile_id, is_incognito, 94 profile_id, is_incognito,
96 base::Bind(&ProfileLoadedCallback, operation, notification_type, origin, 95 base::Bind(&ProfileLoadedCallback, operation, notification_type, origin,
97 notification_id, action_index, base::NullableString16())); 96 notification_id, action_index, base::NullableString16()));
98 } 97 }
99 98
100 // Writes |data| to a new temporary file and returns its path. 99 // Writes |data| to a new temporary file and returns its path.
101 // Returns base::FilePath() on failure. 100 // Returns base::FilePath() on failure.
(...skipping 18 matching lines...) Expand all
120 // static 119 // static
121 NotificationPlatformBridge* NotificationPlatformBridge::Create() { 120 NotificationPlatformBridge* NotificationPlatformBridge::Create() {
122 return new NotificationPlatformBridgeLinux(); 121 return new NotificationPlatformBridgeLinux();
123 } 122 }
124 123
125 class NotificationPlatformBridgeLinuxImpl 124 class NotificationPlatformBridgeLinuxImpl
126 : public NotificationPlatformBridge, 125 : public NotificationPlatformBridge,
127 public content::NotificationObserver, 126 public content::NotificationObserver,
128 public base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl> { 127 public base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl> {
129 public: 128 public:
130 NotificationPlatformBridgeLinuxImpl() 129 NotificationPlatformBridgeLinuxImpl(
131 : task_runner_(base::CreateSingleThreadTaskRunnerWithTraits( 130 scoped_refptr<base::SequencedTaskRunner> notification_task_runner,
132 base::TaskTraits().MayBlock().WithPriority( 131 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
133 base::TaskPriority::USER_BLOCKING))) { 132 scoped_refptr<dbus::Bus> bus)
133 : notification_task_runner_(notification_task_runner),
134 ui_task_runner_(ui_task_runner),
135 bus_(bus) {
136 if (!notification_task_runner_) {
137 notification_task_runner_ = base::CreateSingleThreadTaskRunnerWithTraits(
138 base::TaskTraits().MayBlock().WithPriority(
139 base::TaskPriority::USER_BLOCKING));
140 }
141 DCHECK(ui_task_runner_);
134 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING, 142 registrar_.Add(this, chrome::NOTIFICATION_APP_TERMINATING,
135 content::NotificationService::AllSources()); 143 content::NotificationService::AllSources());
144 }
145
146 // Init() cannot be called from within the constructor because of a
147 // race condition. The reference count for |this| starts out as 0.
148 // Posting the Init task would increment the count to 1. If the
149 // task finishes before the constructor returns, the count will go
150 // to 0 and the object would be prematurely destructed.
151 void InitAfterConstructor() {
136 PostTaskToTaskRunnerThread( 152 PostTaskToTaskRunnerThread(
137 base::BindOnce(&NotificationPlatformBridgeLinuxImpl::Init, this)); 153 base::BindOnce(&NotificationPlatformBridgeLinuxImpl::Init, this));
138 } 154 }
139 155
140 void Display(NotificationCommon::Type notification_type, 156 void Display(NotificationCommon::Type notification_type,
141 const std::string& notification_id, 157 const std::string& notification_id,
142 const std::string& profile_id, 158 const std::string& profile_id,
143 bool is_incognito, 159 bool is_incognito,
144 const Notification& notification) override { 160 const Notification& notification) override {
145 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 161 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
146 // Notifications contain gfx::Image's which have reference counts 162 // Notifications contain gfx::Image's which have reference counts
147 // that are not thread safe. Because of this, we duplicate the 163 // that are not thread safe. Because of this, we duplicate the
148 // notification and its images. Wrap the notification in a 164 // notification and its images. Wrap the notification in a
149 // unique_ptr to transfer ownership of the notification (and the 165 // unique_ptr to transfer ownership of the notification (and the
150 // non-thread-safe reference counts) to the task runner thread. 166 // non-thread-safe reference counts) to the task runner thread.
151 auto notification_copy = base::MakeUnique<Notification>(notification); 167 auto notification_copy = base::MakeUnique<Notification>(notification);
152 notification_copy->set_icon(DeepCopyImage(notification_copy->icon())); 168 notification_copy->set_icon(DeepCopyImage(notification_copy->icon()));
153 notification_copy->set_image(gfx::Image()); 169 notification_copy->set_image(gfx::Image());
154 notification_copy->set_small_image(gfx::Image()); 170 notification_copy->set_small_image(gfx::Image());
155 for (size_t i = 0; i < notification_copy->buttons().size(); i++) 171 for (size_t i = 0; i < notification_copy->buttons().size(); i++)
156 notification_copy->SetButtonIcon(i, gfx::Image()); 172 notification_copy->SetButtonIcon(i, gfx::Image());
157 173
158 PostTaskToTaskRunnerThread(base::BindOnce( 174 PostTaskToTaskRunnerThread(base::BindOnce(
159 &NotificationPlatformBridgeLinuxImpl::DisplayOnTaskRunner, this, 175 &NotificationPlatformBridgeLinuxImpl::DisplayOnTaskRunner, this,
160 notification_type, notification_id, profile_id, is_incognito, 176 notification_type, notification_id, profile_id, is_incognito,
161 base::Passed(&notification_copy))); 177 base::Passed(&notification_copy)));
162 } 178 }
163 179
164 void Close(const std::string& profile_id, 180 void Close(const std::string& profile_id,
165 const std::string& notification_id) override { 181 const std::string& notification_id) override {
166 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 182 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
167 PostTaskToTaskRunnerThread( 183 PostTaskToTaskRunnerThread(
168 base::BindOnce(&NotificationPlatformBridgeLinuxImpl::CloseOnTaskRunner, 184 base::BindOnce(&NotificationPlatformBridgeLinuxImpl::CloseOnTaskRunner,
169 this, profile_id, notification_id)); 185 this, profile_id, notification_id));
170 } 186 }
171 187
172 void GetDisplayed( 188 void GetDisplayed(
173 const std::string& profile_id, 189 const std::string& profile_id,
174 bool incognito, 190 bool incognito,
175 const GetDisplayedNotificationsCallback& callback) const override { 191 const GetDisplayedNotificationsCallback& callback) const override {
176 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 192 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
177 PostTaskToTaskRunnerThread(base::BindOnce( 193 PostTaskToTaskRunnerThread(base::BindOnce(
178 &NotificationPlatformBridgeLinuxImpl::GetDisplayedOnTaskRunner, this, 194 &NotificationPlatformBridgeLinuxImpl::GetDisplayedOnTaskRunner, this,
179 profile_id, incognito, callback)); 195 profile_id, incognito, callback));
180 } 196 }
181 197
182 void SetReadyCallback(NotificationBridgeReadyCallback callback) override { 198 void SetReadyCallback(NotificationBridgeReadyCallback callback) override {
183 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 199 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
184 if (connected_.has_value()) { 200 if (connected_.has_value()) {
185 std::move(callback).Run(connected_.value()); 201 std::move(callback).Run(connected_.value());
186 } else { 202 } else {
187 on_connected_callbacks_.push_back(std::move(callback)); 203 on_connected_callbacks_.push_back(std::move(callback));
188 } 204 }
189 } 205 }
190 206
207 void CleanUp() {
208 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
209 if (cleanup_posted_)
210 return;
211 PostTaskToTaskRunnerThread(base::BindOnce(
212 &NotificationPlatformBridgeLinuxImpl::CleanUpOnTaskRunner, this));
213 cleanup_posted_ = true;
214 }
215
191 private: 216 private:
192 friend class base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl>; 217 friend class base::RefCountedThreadSafe<NotificationPlatformBridgeLinuxImpl>;
193 218
194 struct ResourceFile { 219 struct ResourceFile {
195 explicit ResourceFile(const base::FilePath& file_path) 220 explicit ResourceFile(const base::FilePath& file_path)
196 : file_path(file_path) {} 221 : file_path(file_path) {}
197 ~ResourceFile() { base::DeleteFile(file_path, false); } 222 ~ResourceFile() { base::DeleteFile(file_path, false); }
198 const base::FilePath file_path; 223 const base::FilePath file_path;
199 }; 224 };
200 225
(...skipping 30 matching lines...) Expand all
231 size_t action_start = 0; 256 size_t action_start = 0;
232 size_t action_end = 0; 257 size_t action_end = 0;
233 258
234 // Temporary resource files associated with the notification that 259 // Temporary resource files associated with the notification that
235 // should be cleaned up when the notification is closed or on 260 // should be cleaned up when the notification is closed or on
236 // shutdown. 261 // shutdown.
237 std::vector<std::unique_ptr<ResourceFile>> resource_files; 262 std::vector<std::unique_ptr<ResourceFile>> resource_files;
238 }; 263 };
239 264
240 ~NotificationPlatformBridgeLinuxImpl() override { 265 ~NotificationPlatformBridgeLinuxImpl() override {
266 DCHECK(cleanup_posted_);
241 DCHECK(!bus_); 267 DCHECK(!bus_);
268 DCHECK(!notification_proxy_);
242 DCHECK(notifications_.empty()); 269 DCHECK(notifications_.empty());
243 } 270 }
244 271
245 void Observe(int type, 272 void Observe(int type,
246 const content::NotificationSource& source, 273 const content::NotificationSource& source,
247 const content::NotificationDetails& details) override { 274 const content::NotificationDetails& details) override {
248 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 275 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
249 DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type); 276 DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type);
250 // The browser process is about to exit. Post the CleanUp() task 277 // The browser process is about to exit. Post the CleanUp() task
251 // while we still can. 278 // while we still can.
252 CleanUp(); 279 CleanUp();
253 } 280 }
254 281
255 void PostTaskToUiThread(base::OnceClosure closure) const { 282 void PostTaskToUiThread(base::OnceClosure closure) const {
256 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 283 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
257 bool success = content::BrowserThread::PostTask( 284 DCHECK(ui_task_runner_);
258 content::BrowserThread::UI, FROM_HERE, std::move(closure)); 285 bool success = ui_task_runner_->PostTask(FROM_HERE, std::move(closure));
259 DCHECK(success); 286 DCHECK(success);
260 } 287 }
261 288
262 void PostTaskToTaskRunnerThread(base::OnceClosure closure) const { 289 void PostTaskToTaskRunnerThread(base::OnceClosure closure) const {
263 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 290 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
264 DCHECK(task_runner_); 291 DCHECK(notification_task_runner_);
265 bool success = task_runner_->PostTask(FROM_HERE, std::move(closure)); 292 bool success =
293 notification_task_runner_->PostTask(FROM_HERE, std::move(closure));
266 DCHECK(success); 294 DCHECK(success);
267 } 295 }
268 296
269 // Sets up the D-Bus connection. 297 // Sets up the D-Bus connection.
270 void Init() { 298 void Init() {
271 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 299 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
272 dbus::Bus::Options bus_options; 300 if (!bus_) {
273 bus_options.bus_type = dbus::Bus::SESSION; 301 dbus::Bus::Options bus_options;
274 bus_options.connection_type = dbus::Bus::PRIVATE; 302 bus_options.bus_type = dbus::Bus::SESSION;
275 bus_options.dbus_task_runner = task_runner_; 303 bus_options.connection_type = dbus::Bus::PRIVATE;
276 bus_ = make_scoped_refptr(new dbus::Bus(bus_options)); 304 bus_options.dbus_task_runner = notification_task_runner_;
305 bus_ = make_scoped_refptr(new dbus::Bus(bus_options));
306 }
277 307
278 notification_proxy_ = 308 notification_proxy_ =
279 bus_->GetObjectProxy(kFreedesktopNotificationsName, 309 bus_->GetObjectProxy(kFreedesktopNotificationsName,
280 dbus::ObjectPath(kFreedesktopNotificationsPath)); 310 dbus::ObjectPath(kFreedesktopNotificationsPath));
281 if (!notification_proxy_) { 311 if (!notification_proxy_) {
282 OnConnectionInitializationFinishedOnTaskRunner(false); 312 OnConnectionInitializationFinishedOnTaskRunner(false);
283 return; 313 return;
284 } 314 }
285 315
286 connected_signals_barrier_ = base::BarrierClosure( 316 connected_signals_barrier_ = base::BarrierClosure(
287 2, base::Bind(&NotificationPlatformBridgeLinuxImpl:: 317 2, base::Bind(&NotificationPlatformBridgeLinuxImpl::
288 OnConnectionInitializationFinishedOnTaskRunner, 318 OnConnectionInitializationFinishedOnTaskRunner,
289 this, true)); 319 this, true));
290 notification_proxy_->ConnectToSignal( 320 notification_proxy_->ConnectToSignal(
291 kFreedesktopNotificationsName, "ActionInvoked", 321 kFreedesktopNotificationsName, "ActionInvoked",
292 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this), 322 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this),
293 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, 323 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected,
294 this)); 324 this));
295 notification_proxy_->ConnectToSignal( 325 notification_proxy_->ConnectToSignal(
296 kFreedesktopNotificationsName, "NotificationClosed", 326 kFreedesktopNotificationsName, "NotificationClosed",
297 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnNotificationClosed, 327 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnNotificationClosed,
298 this), 328 this),
299 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, 329 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected,
300 this)); 330 this));
301 } 331 }
302 332
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() { 333 void CleanUpOnTaskRunner() {
313 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 334 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
314 bus_->ShutdownAndBlock(); 335 bus_->ShutdownAndBlock();
315 bus_ = nullptr; 336 bus_ = nullptr;
316 notification_proxy_ = nullptr; 337 notification_proxy_ = nullptr;
317 notifications_.clear(); 338 notifications_.clear();
318 } 339 }
319 340
320 // Makes the "Notify" call to D-Bus. 341 // Makes the "Notify" call to D-Bus.
321 void DisplayOnTaskRunner(NotificationCommon::Type notification_type, 342 void DisplayOnTaskRunner(NotificationCommon::Type notification_type,
322 const std::string& notification_id, 343 const std::string& notification_id,
323 const std::string& profile_id, 344 const std::string& profile_id,
324 bool is_incognito, 345 bool is_incognito,
325 std::unique_ptr<Notification> notification) { 346 std::unique_ptr<Notification> notification) {
326 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 347 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
327 NotificationData* data = 348 NotificationData* data =
328 FindNotificationData(notification_id, profile_id, is_incognito); 349 FindNotificationData(notification_id, profile_id, is_incognito);
329 if (data) { 350 if (data) {
330 // Update an existing notification. 351 // Update an existing notification.
331 data->notification_type = notification_type; 352 data->notification_type = notification_type;
332 data->resource_files.clear(); 353 data->resource_files.clear();
333 } else { 354 } else {
334 // Send the notification for the first time. 355 // Send the notification for the first time.
335 data = 356 data =
336 new NotificationData(notification_type, notification_id, profile_id, 357 new NotificationData(notification_type, notification_id, profile_id,
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after
424 } 445 }
425 if (!data->dbus_id) { 446 if (!data->dbus_id) {
426 // There was some sort of error with creating the notification. 447 // There was some sort of error with creating the notification.
427 notifications_.erase(data); 448 notifications_.erase(data);
428 } 449 }
429 } 450 }
430 451
431 // Makes the "CloseNotification" call to D-Bus. 452 // Makes the "CloseNotification" call to D-Bus.
432 void CloseOnTaskRunner(const std::string& profile_id, 453 void CloseOnTaskRunner(const std::string& profile_id,
433 const std::string& notification_id) { 454 const std::string& notification_id) {
434 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 455 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
435 std::vector<NotificationData*> to_erase; 456 std::vector<NotificationData*> to_erase;
436 for (const auto& pair : notifications_) { 457 for (const auto& pair : notifications_) {
437 NotificationData* data = pair.first; 458 NotificationData* data = pair.first;
438 if (data->notification_id == notification_id && 459 if (data->notification_id == notification_id &&
439 data->profile_id == profile_id) { 460 data->profile_id == profile_id) {
440 dbus::MethodCall method_call(kFreedesktopNotificationsName, 461 dbus::MethodCall method_call(kFreedesktopNotificationsName,
441 "CloseNotification"); 462 "CloseNotification");
442 dbus::MessageWriter writer(&method_call); 463 dbus::MessageWriter writer(&method_call);
443 writer.AppendUint32(data->dbus_id); 464 writer.AppendUint32(data->dbus_id);
444 notification_proxy_->CallMethodAndBlock( 465 notification_proxy_->CallMethodAndBlock(
445 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); 466 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
446 } 467 }
447 } 468 }
448 for (NotificationData* data : to_erase) 469 for (NotificationData* data : to_erase)
449 notifications_.erase(data); 470 notifications_.erase(data);
450 } 471 }
451 472
452 void GetDisplayedOnTaskRunner( 473 void GetDisplayedOnTaskRunner(
453 const std::string& profile_id, 474 const std::string& profile_id,
454 bool incognito, 475 bool incognito,
455 const GetDisplayedNotificationsCallback& callback) const { 476 const GetDisplayedNotificationsCallback& callback) const {
456 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 477 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
457 // TODO(thomasanderson): Implement. 478 // TODO(thomasanderson): Implement.
458 PostTaskToUiThread(base::BindOnce( 479 PostTaskToUiThread(base::BindOnce(
459 callback, base::Passed(base::MakeUnique<std::set<std::string>>()), 480 callback, base::Passed(base::MakeUnique<std::set<std::string>>()),
460 false)); 481 false));
461 } 482 }
462 483
463 NotificationData* FindNotificationData(const std::string& notification_id, 484 NotificationData* FindNotificationData(const std::string& notification_id,
464 const std::string& profile_id, 485 const std::string& profile_id,
465 bool is_incognito) { 486 bool is_incognito) {
466 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 487 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
467 for (const auto& pair : notifications_) { 488 for (const auto& pair : notifications_) {
468 NotificationData* data = pair.first; 489 NotificationData* data = pair.first;
469 if (data->notification_id == notification_id && 490 if (data->notification_id == notification_id &&
470 data->profile_id == profile_id && 491 data->profile_id == profile_id &&
471 data->is_incognito == is_incognito) { 492 data->is_incognito == is_incognito) {
472 return data; 493 return data;
473 } 494 }
474 } 495 }
475 496
476 return nullptr; 497 return nullptr;
477 } 498 }
478 499
479 NotificationData* FindNotificationData(uint32_t dbus_id) { 500 NotificationData* FindNotificationData(uint32_t dbus_id) {
480 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 501 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
481 for (const auto& pair : notifications_) { 502 for (const auto& pair : notifications_) {
482 NotificationData* data = pair.first; 503 NotificationData* data = pair.first;
483 if (data->dbus_id == dbus_id) 504 if (data->dbus_id == dbus_id)
484 return data; 505 return data;
485 } 506 }
486 507
487 return nullptr; 508 return nullptr;
488 } 509 }
489 510
490 void ForwardNotificationOperation(NotificationData* data, 511 void ForwardNotificationOperation(NotificationData* data,
491 NotificationCommon::Operation operation, 512 NotificationCommon::Operation operation,
492 int action_index) { 513 int action_index) {
493 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 514 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
494 PostTaskToUiThread(base::BindOnce( 515 PostTaskToUiThread(base::BindOnce(
495 ForwardNotificationOperationOnUiThread, operation, 516 ForwardNotificationOperationOnUiThread, operation,
496 data->notification_type, data->origin_url.spec(), data->notification_id, 517 data->notification_type, data->origin_url.spec(), data->notification_id,
497 action_index, data->profile_id, data->is_incognito)); 518 action_index, data->profile_id, data->is_incognito));
498 } 519 }
499 520
500 void OnActionInvoked(dbus::Signal* signal) { 521 void OnActionInvoked(dbus::Signal* signal) {
501 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 522 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
502 dbus::MessageReader reader(signal); 523 dbus::MessageReader reader(signal);
503 uint32_t dbus_id; 524 uint32_t dbus_id;
504 if (!reader.PopUint32(&dbus_id)) 525 if (!reader.PopUint32(&dbus_id))
505 return; 526 return;
506 std::string action; 527 std::string action;
507 if (!reader.PopString(&action)) 528 if (!reader.PopString(&action))
508 return; 529 return;
509 530
510 NotificationData* data = FindNotificationData(dbus_id); 531 NotificationData* data = FindNotificationData(dbus_id);
511 if (!data) 532 if (!data)
(...skipping 10 matching lines...) Expand all
522 size_t n_buttons = data->action_end - data->action_start; 543 size_t n_buttons = data->action_end - data->action_start;
523 size_t id_zero_based = id - data->action_start; 544 size_t id_zero_based = id - data->action_start;
524 if (id_zero_based >= n_buttons) 545 if (id_zero_based >= n_buttons)
525 return; 546 return;
526 ForwardNotificationOperation(data, NotificationCommon::CLICK, 547 ForwardNotificationOperation(data, NotificationCommon::CLICK,
527 id_zero_based); 548 id_zero_based);
528 } 549 }
529 } 550 }
530 551
531 void OnNotificationClosed(dbus::Signal* signal) { 552 void OnNotificationClosed(dbus::Signal* signal) {
532 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 553 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
533 dbus::MessageReader reader(signal); 554 dbus::MessageReader reader(signal);
534 uint32_t dbus_id; 555 uint32_t dbus_id;
535 if (!reader.PopUint32(&dbus_id)) 556 if (!reader.PopUint32(&dbus_id))
536 return; 557 return;
537 558
538 NotificationData* data = FindNotificationData(dbus_id); 559 NotificationData* data = FindNotificationData(dbus_id);
539 if (!data) 560 if (!data)
540 return; 561 return;
541 562
542 ForwardNotificationOperation(data, NotificationCommon::CLOSE, -1); 563 ForwardNotificationOperation(data, NotificationCommon::CLOSE, -1);
543 notifications_.erase(data); 564 notifications_.erase(data);
544 } 565 }
545 566
546 // Called once the connection has been set up (or not). |success| 567 // Called once the connection has been set up (or not). |success|
547 // indicates the connection is ready to use. 568 // indicates the connection is ready to use.
548 void OnConnectionInitializationFinishedOnUiThread(bool success) { 569 void OnConnectionInitializationFinishedOnUiThread(bool success) {
549 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 570 DCHECK(ui_task_runner_->RunsTasksOnCurrentThread());
550 connected_ = success; 571 connected_ = success;
551 for (auto& callback : on_connected_callbacks_) 572 for (auto& callback : on_connected_callbacks_)
552 std::move(callback).Run(success); 573 std::move(callback).Run(success);
553 on_connected_callbacks_.clear(); 574 on_connected_callbacks_.clear();
554 if (!success) 575 if (!success)
555 CleanUp(); 576 CleanUp();
556 } 577 }
557 578
558 void OnConnectionInitializationFinishedOnTaskRunner(bool success) { 579 void OnConnectionInitializationFinishedOnTaskRunner(bool success) {
559 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 580 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
560 PostTaskToUiThread( 581 PostTaskToUiThread(
561 base::BindOnce(&NotificationPlatformBridgeLinuxImpl:: 582 base::BindOnce(&NotificationPlatformBridgeLinuxImpl::
562 OnConnectionInitializationFinishedOnUiThread, 583 OnConnectionInitializationFinishedOnUiThread,
563 this, success)); 584 this, success));
564 } 585 }
565 586
566 void OnSignalConnected(const std::string& interface_name, 587 void OnSignalConnected(const std::string& interface_name,
567 const std::string& signal_name, 588 const std::string& signal_name,
568 bool success) { 589 bool success) {
569 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 590 DCHECK(notification_task_runner_->RunsTasksOnCurrentThread());
570 if (!success) { 591 if (!success) {
571 OnConnectionInitializationFinishedOnTaskRunner(false); 592 OnConnectionInitializationFinishedOnTaskRunner(false);
572 return; 593 return;
573 } 594 }
574 connected_signals_barrier_.Run(); 595 connected_signals_barrier_.Run();
575 } 596 }
576 597
577 ////////////////////////////////////////////////////////////////////////////// 598 //////////////////////////////////////////////////////////////////////////////
578 // Members used only on the UI thread. 599 // Members used only on the UI thread.
579 600
580 scoped_refptr<base::SequencedTaskRunner> task_runner_; 601 scoped_refptr<base::SequencedTaskRunner> notification_task_runner_;
581 602
582 content::NotificationRegistrar registrar_; 603 content::NotificationRegistrar registrar_;
583 604
584 // State necessary for OnConnectionInitializationFinished() and 605 // State necessary for OnConnectionInitializationFinished() and
585 // SetReadyCallback(). 606 // SetReadyCallback().
586 base::Optional<bool> connected_; 607 base::Optional<bool> connected_;
587 std::vector<NotificationBridgeReadyCallback> on_connected_callbacks_; 608 std::vector<NotificationBridgeReadyCallback> on_connected_callbacks_;
588 609
589 bool cleanup_posted_ = false; 610 bool cleanup_posted_ = false;
590 611
591 ////////////////////////////////////////////////////////////////////////////// 612 //////////////////////////////////////////////////////////////////////////////
592 // Members used only on the task runner thread. 613 // Members used only on the task runner thread.
593 614
615 scoped_refptr<base::SequencedTaskRunner> ui_task_runner_;
616
594 scoped_refptr<dbus::Bus> bus_; 617 scoped_refptr<dbus::Bus> bus_;
595 618
596 dbus::ObjectProxy* notification_proxy_ = nullptr; 619 dbus::ObjectProxy* notification_proxy_ = nullptr;
597 620
598 base::Closure connected_signals_barrier_; 621 base::Closure connected_signals_barrier_;
599 622
600 // A std::set<std::unique_ptr<T>> doesn't work well because 623 // A std::set<std::unique_ptr<T>> doesn't work well because
601 // eg. std::set::erase(T) would require a std::unique_ptr<T> 624 // eg. std::set::erase(T) would require a std::unique_ptr<T>
602 // argument, so the data would get double-destructed. 625 // argument, so the data would get double-destructed.
603 template <typename T> 626 template <typename T>
604 using UnorderedUniqueSet = std::unordered_map<T*, std::unique_ptr<T>>; 627 using UnorderedUniqueSet = std::unordered_map<T*, std::unique_ptr<T>>;
605 628
606 UnorderedUniqueSet<NotificationData> notifications_; 629 UnorderedUniqueSet<NotificationData> notifications_;
607 630
608 DISALLOW_COPY_AND_ASSIGN(NotificationPlatformBridgeLinuxImpl); 631 DISALLOW_COPY_AND_ASSIGN(NotificationPlatformBridgeLinuxImpl);
609 }; 632 };
610 633
611 NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux() 634 NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux()
612 : impl_(new NotificationPlatformBridgeLinuxImpl()) {} 635 : NotificationPlatformBridgeLinux(
636 nullptr,
637 content::BrowserThread::GetTaskRunnerForThread(
638 content::BrowserThread::UI),
639 nullptr) {
640 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
641 }
642
643 NotificationPlatformBridgeLinux::NotificationPlatformBridgeLinux(
644 scoped_refptr<base::SequencedTaskRunner> notification_task_runner,
645 scoped_refptr<base::SequencedTaskRunner> ui_task_runner,
646 scoped_refptr<dbus::Bus> bus)
647 : impl_(new NotificationPlatformBridgeLinuxImpl(notification_task_runner,
648 ui_task_runner,
649 bus)) {
650 impl_->InitAfterConstructor();
651 }
613 652
614 NotificationPlatformBridgeLinux::~NotificationPlatformBridgeLinux() = default; 653 NotificationPlatformBridgeLinux::~NotificationPlatformBridgeLinux() = default;
615 654
616 void NotificationPlatformBridgeLinux::Display( 655 void NotificationPlatformBridgeLinux::Display(
617 NotificationCommon::Type notification_type, 656 NotificationCommon::Type notification_type,
618 const std::string& notification_id, 657 const std::string& notification_id,
619 const std::string& profile_id, 658 const std::string& profile_id,
620 bool is_incognito, 659 bool is_incognito,
621 const Notification& notification) { 660 const Notification& notification) {
622 impl_->Display(notification_type, notification_id, profile_id, is_incognito, 661 impl_->Display(notification_type, notification_id, profile_id, is_incognito,
(...skipping 10 matching lines...) Expand all
633 const std::string& profile_id, 672 const std::string& profile_id,
634 bool incognito, 673 bool incognito,
635 const GetDisplayedNotificationsCallback& callback) const { 674 const GetDisplayedNotificationsCallback& callback) const {
636 impl_->GetDisplayed(profile_id, incognito, callback); 675 impl_->GetDisplayed(profile_id, incognito, callback);
637 } 676 }
638 677
639 void NotificationPlatformBridgeLinux::SetReadyCallback( 678 void NotificationPlatformBridgeLinux::SetReadyCallback(
640 NotificationBridgeReadyCallback callback) { 679 NotificationBridgeReadyCallback callback) {
641 impl_->SetReadyCallback(std::move(callback)); 680 impl_->SetReadyCallback(std::move(callback));
642 } 681 }
682
683 void NotificationPlatformBridgeLinux::CleanUp() {
684 impl_->CleanUp();
685 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698