OLD | NEW |
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 #include <memory> | 8 #include <memory> |
9 #include <set> | 9 #include <set> |
10 #include <unordered_map> | 10 #include <unordered_map> |
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
331 const content::NotificationSource& source, | 331 const content::NotificationSource& source, |
332 const content::NotificationDetails& details) override { | 332 const content::NotificationDetails& details) override { |
333 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 333 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
334 DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type); | 334 DCHECK_EQ(chrome::NOTIFICATION_APP_TERMINATING, type); |
335 // The browser process is about to exit. Post the CleanUp() task | 335 // The browser process is about to exit. Post the CleanUp() task |
336 // while we still can. | 336 // while we still can. |
337 CleanUp(); | 337 CleanUp(); |
338 } | 338 } |
339 | 339 |
340 void PostTaskToUiThread(base::OnceClosure closure) const { | 340 void PostTaskToUiThread(base::OnceClosure closure) const { |
341 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 341 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
342 bool success = content::BrowserThread::PostTask( | 342 bool success = content::BrowserThread::PostTask( |
343 content::BrowserThread::UI, FROM_HERE, std::move(closure)); | 343 content::BrowserThread::UI, FROM_HERE, std::move(closure)); |
344 DCHECK(success); | 344 DCHECK(success); |
345 } | 345 } |
346 | 346 |
347 void PostTaskToTaskRunnerThread(base::OnceClosure closure) const { | 347 void PostTaskToTaskRunnerThread(base::OnceClosure closure) const { |
348 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 348 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
349 DCHECK(task_runner_); | 349 DCHECK(task_runner_); |
350 bool success = task_runner_->PostTask(FROM_HERE, std::move(closure)); | 350 bool success = task_runner_->PostTask(FROM_HERE, std::move(closure)); |
351 DCHECK(success); | 351 DCHECK(success); |
352 } | 352 } |
353 | 353 |
354 // Sets up the D-Bus connection. | 354 // Sets up the D-Bus connection. |
355 void InitOnTaskRunner() { | 355 void InitOnTaskRunner() { |
356 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 356 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
357 // |bus_| may be non-null in unit testing where a fake bus is used. | 357 // |bus_| may be non-null in unit testing where a fake bus is used. |
358 if (!bus_) { | 358 if (!bus_) { |
359 dbus::Bus::Options bus_options; | 359 dbus::Bus::Options bus_options; |
360 bus_options.bus_type = dbus::Bus::SESSION; | 360 bus_options.bus_type = dbus::Bus::SESSION; |
361 bus_options.connection_type = dbus::Bus::PRIVATE; | 361 bus_options.connection_type = dbus::Bus::PRIVATE; |
362 bus_options.dbus_task_runner = task_runner_; | 362 bus_options.dbus_task_runner = task_runner_; |
363 bus_ = make_scoped_refptr(new dbus::Bus(bus_options)); | 363 bus_ = make_scoped_refptr(new dbus::Bus(bus_options)); |
364 } | 364 } |
365 | 365 |
366 notification_proxy_ = | 366 notification_proxy_ = |
(...skipping 55 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
422 this)); | 422 this)); |
423 notification_proxy_->ConnectToSignal( | 423 notification_proxy_->ConnectToSignal( |
424 kFreedesktopNotificationsName, kSignalNotificationClosed, | 424 kFreedesktopNotificationsName, kSignalNotificationClosed, |
425 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnNotificationClosed, | 425 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnNotificationClosed, |
426 this), | 426 this), |
427 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, | 427 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, |
428 this)); | 428 this)); |
429 } | 429 } |
430 | 430 |
431 void CleanUpOnTaskRunner() { | 431 void CleanUpOnTaskRunner() { |
432 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 432 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
433 if (bus_) | 433 if (bus_) |
434 bus_->ShutdownAndBlock(); | 434 bus_->ShutdownAndBlock(); |
435 bus_ = nullptr; | 435 bus_ = nullptr; |
436 notification_proxy_ = nullptr; | 436 notification_proxy_ = nullptr; |
437 notifications_.clear(); | 437 notifications_.clear(); |
438 } | 438 } |
439 | 439 |
440 // Makes the "Notify" call to D-Bus. | 440 // Makes the "Notify" call to D-Bus. |
441 void DisplayOnTaskRunner(NotificationCommon::Type notification_type, | 441 void DisplayOnTaskRunner(NotificationCommon::Type notification_type, |
442 const std::string& notification_id, | 442 const std::string& notification_id, |
443 const std::string& profile_id, | 443 const std::string& profile_id, |
444 bool is_incognito, | 444 bool is_incognito, |
445 std::unique_ptr<Notification> notification) { | 445 std::unique_ptr<Notification> notification) { |
446 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 446 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
447 NotificationData* data = | 447 NotificationData* data = |
448 FindNotificationData(notification_id, profile_id, is_incognito); | 448 FindNotificationData(notification_id, profile_id, is_incognito); |
449 if (data) { | 449 if (data) { |
450 // Update an existing notification. | 450 // Update an existing notification. |
451 data->notification_type = notification_type; | 451 data->notification_type = notification_type; |
452 data->resource_files.clear(); | 452 data->resource_files.clear(); |
453 } else { | 453 } else { |
454 // Send the notification for the first time. | 454 // Send the notification for the first time. |
455 data = | 455 data = |
456 new NotificationData(notification_type, notification_id, profile_id, | 456 new NotificationData(notification_type, notification_id, profile_id, |
(...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
560 } | 560 } |
561 if (!data->dbus_id) { | 561 if (!data->dbus_id) { |
562 // There was some sort of error with creating the notification. | 562 // There was some sort of error with creating the notification. |
563 notifications_.erase(data); | 563 notifications_.erase(data); |
564 } | 564 } |
565 } | 565 } |
566 | 566 |
567 // Makes the "CloseNotification" call to D-Bus. | 567 // Makes the "CloseNotification" call to D-Bus. |
568 void CloseOnTaskRunner(const std::string& profile_id, | 568 void CloseOnTaskRunner(const std::string& profile_id, |
569 const std::string& notification_id) { | 569 const std::string& notification_id) { |
570 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 570 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
571 std::vector<NotificationData*> to_erase; | 571 std::vector<NotificationData*> to_erase; |
572 for (const auto& pair : notifications_) { | 572 for (const auto& pair : notifications_) { |
573 NotificationData* data = pair.first; | 573 NotificationData* data = pair.first; |
574 if (data->notification_id == notification_id && | 574 if (data->notification_id == notification_id && |
575 data->profile_id == profile_id) { | 575 data->profile_id == profile_id) { |
576 dbus::MethodCall method_call(kFreedesktopNotificationsName, | 576 dbus::MethodCall method_call(kFreedesktopNotificationsName, |
577 kMethodCloseNotification); | 577 kMethodCloseNotification); |
578 dbus::MessageWriter writer(&method_call); | 578 dbus::MessageWriter writer(&method_call); |
579 writer.AppendUint32(data->dbus_id); | 579 writer.AppendUint32(data->dbus_id); |
580 notification_proxy_->CallMethodAndBlock( | 580 notification_proxy_->CallMethodAndBlock( |
581 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); | 581 &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); |
582 to_erase.push_back(data); | 582 to_erase.push_back(data); |
583 } | 583 } |
584 } | 584 } |
585 for (NotificationData* data : to_erase) | 585 for (NotificationData* data : to_erase) |
586 notifications_.erase(data); | 586 notifications_.erase(data); |
587 } | 587 } |
588 | 588 |
589 void GetDisplayedOnTaskRunner( | 589 void GetDisplayedOnTaskRunner( |
590 const std::string& profile_id, | 590 const std::string& profile_id, |
591 bool incognito, | 591 bool incognito, |
592 const GetDisplayedNotificationsCallback& callback) const { | 592 const GetDisplayedNotificationsCallback& callback) const { |
593 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 593 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
594 auto displayed = base::MakeUnique<std::set<std::string>>(); | 594 auto displayed = base::MakeUnique<std::set<std::string>>(); |
595 for (const auto& pair : notifications_) { | 595 for (const auto& pair : notifications_) { |
596 NotificationData* data = pair.first; | 596 NotificationData* data = pair.first; |
597 if (data->profile_id == profile_id && data->is_incognito == incognito) | 597 if (data->profile_id == profile_id && data->is_incognito == incognito) |
598 displayed->insert(data->notification_id); | 598 displayed->insert(data->notification_id); |
599 } | 599 } |
600 PostTaskToUiThread(base::BindOnce(callback, std::move(displayed), true)); | 600 PostTaskToUiThread(base::BindOnce(callback, std::move(displayed), true)); |
601 } | 601 } |
602 | 602 |
603 NotificationData* FindNotificationData(const std::string& notification_id, | 603 NotificationData* FindNotificationData(const std::string& notification_id, |
604 const std::string& profile_id, | 604 const std::string& profile_id, |
605 bool is_incognito) { | 605 bool is_incognito) { |
606 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 606 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
607 for (const auto& pair : notifications_) { | 607 for (const auto& pair : notifications_) { |
608 NotificationData* data = pair.first; | 608 NotificationData* data = pair.first; |
609 if (data->notification_id == notification_id && | 609 if (data->notification_id == notification_id && |
610 data->profile_id == profile_id && | 610 data->profile_id == profile_id && |
611 data->is_incognito == is_incognito) { | 611 data->is_incognito == is_incognito) { |
612 return data; | 612 return data; |
613 } | 613 } |
614 } | 614 } |
615 | 615 |
616 return nullptr; | 616 return nullptr; |
617 } | 617 } |
618 | 618 |
619 NotificationData* FindNotificationDataWithDBusId(uint32_t dbus_id) { | 619 NotificationData* FindNotificationDataWithDBusId(uint32_t dbus_id) { |
620 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 620 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
621 DCHECK(dbus_id); | 621 DCHECK(dbus_id); |
622 for (const auto& pair : notifications_) { | 622 for (const auto& pair : notifications_) { |
623 NotificationData* data = pair.first; | 623 NotificationData* data = pair.first; |
624 if (data->dbus_id == dbus_id) | 624 if (data->dbus_id == dbus_id) |
625 return data; | 625 return data; |
626 } | 626 } |
627 | 627 |
628 return nullptr; | 628 return nullptr; |
629 } | 629 } |
630 | 630 |
631 void ForwardNotificationOperation(NotificationData* data, | 631 void ForwardNotificationOperation(NotificationData* data, |
632 NotificationCommon::Operation operation, | 632 NotificationCommon::Operation operation, |
633 int action_index) { | 633 int action_index) { |
634 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 634 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
635 PostTaskToUiThread(base::BindOnce( | 635 PostTaskToUiThread(base::BindOnce( |
636 ForwardNotificationOperationOnUiThread, operation, | 636 ForwardNotificationOperationOnUiThread, operation, |
637 data->notification_type, data->origin_url.spec(), data->notification_id, | 637 data->notification_type, data->origin_url.spec(), data->notification_id, |
638 action_index, data->profile_id, data->is_incognito)); | 638 action_index, data->profile_id, data->is_incognito)); |
639 } | 639 } |
640 | 640 |
641 void OnActionInvoked(dbus::Signal* signal) { | 641 void OnActionInvoked(dbus::Signal* signal) { |
642 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 642 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
643 dbus::MessageReader reader(signal); | 643 dbus::MessageReader reader(signal); |
644 uint32_t dbus_id; | 644 uint32_t dbus_id; |
645 if (!reader.PopUint32(&dbus_id) || !dbus_id) | 645 if (!reader.PopUint32(&dbus_id) || !dbus_id) |
646 return; | 646 return; |
647 std::string action; | 647 std::string action; |
648 if (!reader.PopString(&action)) | 648 if (!reader.PopString(&action)) |
649 return; | 649 return; |
650 | 650 |
651 NotificationData* data = FindNotificationDataWithDBusId(dbus_id); | 651 NotificationData* data = FindNotificationDataWithDBusId(dbus_id); |
652 if (!data) | 652 if (!data) |
(...skipping 10 matching lines...) Expand all Loading... |
663 size_t n_buttons = data->action_end - data->action_start; | 663 size_t n_buttons = data->action_end - data->action_start; |
664 size_t id_zero_based = id - data->action_start; | 664 size_t id_zero_based = id - data->action_start; |
665 if (id_zero_based >= n_buttons) | 665 if (id_zero_based >= n_buttons) |
666 return; | 666 return; |
667 ForwardNotificationOperation(data, NotificationCommon::CLICK, | 667 ForwardNotificationOperation(data, NotificationCommon::CLICK, |
668 id_zero_based); | 668 id_zero_based); |
669 } | 669 } |
670 } | 670 } |
671 | 671 |
672 void OnNotificationClosed(dbus::Signal* signal) { | 672 void OnNotificationClosed(dbus::Signal* signal) { |
673 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 673 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
674 dbus::MessageReader reader(signal); | 674 dbus::MessageReader reader(signal); |
675 uint32_t dbus_id; | 675 uint32_t dbus_id; |
676 if (!reader.PopUint32(&dbus_id) || !dbus_id) | 676 if (!reader.PopUint32(&dbus_id) || !dbus_id) |
677 return; | 677 return; |
678 | 678 |
679 NotificationData* data = FindNotificationDataWithDBusId(dbus_id); | 679 NotificationData* data = FindNotificationDataWithDBusId(dbus_id); |
680 if (!data) | 680 if (!data) |
681 return; | 681 return; |
682 | 682 |
683 ForwardNotificationOperation(data, NotificationCommon::CLOSE, -1); | 683 ForwardNotificationOperation(data, NotificationCommon::CLOSE, -1); |
684 notifications_.erase(data); | 684 notifications_.erase(data); |
685 } | 685 } |
686 | 686 |
687 // Called once the connection has been set up (or not). |success| | 687 // Called once the connection has been set up (or not). |success| |
688 // indicates the connection is ready to use. | 688 // indicates the connection is ready to use. |
689 void OnConnectionInitializationFinishedOnUiThread(bool success) { | 689 void OnConnectionInitializationFinishedOnUiThread(bool success) { |
690 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); | 690 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); |
691 connected_ = success; | 691 connected_ = success; |
692 for (auto& callback : on_connected_callbacks_) | 692 for (auto& callback : on_connected_callbacks_) |
693 std::move(callback).Run(success); | 693 std::move(callback).Run(success); |
694 on_connected_callbacks_.clear(); | 694 on_connected_callbacks_.clear(); |
695 if (!success) | 695 if (!success) |
696 CleanUp(); | 696 CleanUp(); |
697 } | 697 } |
698 | 698 |
699 void OnConnectionInitializationFinishedOnTaskRunner( | 699 void OnConnectionInitializationFinishedOnTaskRunner( |
700 ConnectionInitializationStatusCode status) { | 700 ConnectionInitializationStatusCode status) { |
701 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 701 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
702 UMA_HISTOGRAM_ENUMERATION( | 702 UMA_HISTOGRAM_ENUMERATION( |
703 "Notifications.Linux.BridgeInitializationStatus", | 703 "Notifications.Linux.BridgeInitializationStatus", |
704 static_cast<int>(status), | 704 static_cast<int>(status), |
705 static_cast<int>(ConnectionInitializationStatusCode::NUM_ITEMS)); | 705 static_cast<int>(ConnectionInitializationStatusCode::NUM_ITEMS)); |
706 PostTaskToUiThread(base::BindOnce( | 706 PostTaskToUiThread(base::BindOnce( |
707 &NotificationPlatformBridgeLinuxImpl:: | 707 &NotificationPlatformBridgeLinuxImpl:: |
708 OnConnectionInitializationFinishedOnUiThread, | 708 OnConnectionInitializationFinishedOnUiThread, |
709 this, status == ConnectionInitializationStatusCode::SUCCESS)); | 709 this, status == ConnectionInitializationStatusCode::SUCCESS)); |
710 } | 710 } |
711 | 711 |
712 void OnSignalConnected(const std::string& interface_name, | 712 void OnSignalConnected(const std::string& interface_name, |
713 const std::string& signal_name, | 713 const std::string& signal_name, |
714 bool success) { | 714 bool success) { |
715 DCHECK(task_runner_->RunsTasksOnCurrentThread()); | 715 DCHECK(task_runner_->RunsTasksInCurrentSequence()); |
716 if (!success) { | 716 if (!success) { |
717 OnConnectionInitializationFinishedOnTaskRunner( | 717 OnConnectionInitializationFinishedOnTaskRunner( |
718 ConnectionInitializationStatusCode::COULD_NOT_CONNECT_TO_SIGNALS); | 718 ConnectionInitializationStatusCode::COULD_NOT_CONNECT_TO_SIGNALS); |
719 return; | 719 return; |
720 } | 720 } |
721 connected_signals_barrier_.Run(); | 721 connected_signals_barrier_.Run(); |
722 } | 722 } |
723 | 723 |
724 void RecordMetricsForCapabilities() { | 724 void RecordMetricsForCapabilities() { |
725 // Histogram macros must be called with the same name for each | 725 // Histogram macros must be called with the same name for each |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
824 } | 824 } |
825 | 825 |
826 void NotificationPlatformBridgeLinux::SetReadyCallback( | 826 void NotificationPlatformBridgeLinux::SetReadyCallback( |
827 NotificationBridgeReadyCallback callback) { | 827 NotificationBridgeReadyCallback callback) { |
828 impl_->SetReadyCallback(std::move(callback)); | 828 impl_->SetReadyCallback(std::move(callback)); |
829 } | 829 } |
830 | 830 |
831 void NotificationPlatformBridgeLinux::CleanUp() { | 831 void NotificationPlatformBridgeLinux::CleanUp() { |
832 impl_->CleanUp(); | 832 impl_->CleanUp(); |
833 } | 833 } |
OLD | NEW |