| 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 <sstream> | 10 #include <sstream> |
| 11 #include <unordered_map> | 11 #include <unordered_map> |
| 12 #include <unordered_set> | 12 #include <unordered_set> |
| 13 #include <utility> | 13 #include <utility> |
| 14 #include <vector> | 14 #include <vector> |
| 15 | 15 |
| 16 #include "base/barrier_closure.h" | 16 #include "base/barrier_closure.h" |
| 17 #include "base/files/file_util.h" | 17 #include "base/files/file_util.h" |
| 18 #include "base/i18n/number_formatting.h" | 18 #include "base/i18n/number_formatting.h" |
| 19 #include "base/metrics/histogram_macros.h" | 19 #include "base/metrics/histogram_macros.h" |
| 20 #include "base/strings/nullable_string16.h" | 20 #include "base/strings/nullable_string16.h" |
| 21 #include "base/strings/string_number_conversions.h" | 21 #include "base/strings/string_number_conversions.h" |
| 22 #include "base/strings/string_split.h" | 22 #include "base/strings/string_split.h" |
| 23 #include "base/strings/string_util.h" | 23 #include "base/strings/string_util.h" |
| 24 #include "base/strings/utf_string_conversions.h" | 24 #include "base/strings/utf_string_conversions.h" |
| 25 #include "base/task_scheduler/post_task.h" | 25 #include "base/task_scheduler/post_task.h" |
| 26 #include "base/version.h" | |
| 27 #include "chrome/browser/browser_process.h" | 26 #include "chrome/browser/browser_process.h" |
| 28 #include "chrome/browser/chrome_notification_types.h" | 27 #include "chrome/browser/chrome_notification_types.h" |
| 29 #include "chrome/browser/notifications/native_notification_display_service.h" | 28 #include "chrome/browser/notifications/native_notification_display_service.h" |
| 30 #include "chrome/browser/notifications/notification.h" | 29 #include "chrome/browser/notifications/notification.h" |
| 31 #include "chrome/browser/notifications/notification_display_service_factory.h" | 30 #include "chrome/browser/notifications/notification_display_service_factory.h" |
| 32 #include "chrome/browser/profiles/profile_manager.h" | 31 #include "chrome/browser/profiles/profile_manager.h" |
| 33 #include "chrome/browser/shell_integration_linux.h" | 32 #include "chrome/browser/shell_integration_linux.h" |
| 34 #include "chrome/grit/generated_resources.h" | 33 #include "chrome/grit/generated_resources.h" |
| 35 #include "components/url_formatter/elide_url.h" | 34 #include "components/url_formatter/elide_url.h" |
| 36 #include "content/public/browser/browser_thread.h" | 35 #include "content/public/browser/browser_thread.h" |
| 37 #include "content/public/browser/notification_service.h" | 36 #include "content/public/browser/notification_service.h" |
| 38 #include "dbus/bus.h" | 37 #include "dbus/bus.h" |
| 39 #include "dbus/message.h" | 38 #include "dbus/message.h" |
| 40 #include "dbus/object_proxy.h" | 39 #include "dbus/object_proxy.h" |
| 41 #include "net/base/escape.h" | 40 #include "net/base/escape.h" |
| 42 #include "skia/ext/image_operations.h" | 41 #include "skia/ext/image_operations.h" |
| 43 #include "ui/base/l10n/l10n_util.h" | 42 #include "ui/base/l10n/l10n_util.h" |
| 44 #include "ui/gfx/image/image_skia.h" | 43 #include "ui/gfx/image/image_skia.h" |
| 45 | 44 |
| 46 namespace { | 45 namespace { |
| 47 | 46 |
| 48 // DBus name / path. | 47 // DBus name / path. |
| 49 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications"; | 48 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications"; |
| 50 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications"; | 49 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications"; |
| 51 | 50 |
| 52 // DBus methods. | 51 // DBus methods. |
| 53 const char kMethodCloseNotification[] = "CloseNotification"; | 52 const char kMethodCloseNotification[] = "CloseNotification"; |
| 54 const char kMethodGetCapabilities[] = "GetCapabilities"; | 53 const char kMethodGetCapabilities[] = "GetCapabilities"; |
| 55 const char kMethodNotify[] = "Notify"; | 54 const char kMethodNotify[] = "Notify"; |
| 56 const char kMethodGetServerInformation[] = "GetServerInformation"; | |
| 57 | 55 |
| 58 // DBus signals. | 56 // DBus signals. |
| 59 const char kSignalActionInvoked[] = "ActionInvoked"; | 57 const char kSignalActionInvoked[] = "ActionInvoked"; |
| 60 const char kSignalNotificationClosed[] = "NotificationClosed"; | 58 const char kSignalNotificationClosed[] = "NotificationClosed"; |
| 61 | 59 |
| 62 // Capabilities. | 60 // Capabilities. |
| 63 const char kCapabilityActionIcons[] = "action-icons"; | 61 const char kCapabilityActionIcons[] = "action-icons"; |
| 64 const char kCapabilityActions[] = "actions"; | 62 const char kCapabilityActions[] = "actions"; |
| 65 const char kCapabilityBody[] = "body"; | 63 const char kCapabilityBody[] = "body"; |
| 66 const char kCapabilityBodyHyperlinks[] = "body-hyperlinks"; | 64 const char kCapabilityBodyHyperlinks[] = "body-hyperlinks"; |
| (...skipping 14 matching lines...) Expand all Loading... |
| 81 | 79 |
| 82 // The values in this enumeration correspond to those of the | 80 // The values in this enumeration correspond to those of the |
| 83 // Linux.NotificationPlatformBridge.InitializationStatus histogram, so | 81 // Linux.NotificationPlatformBridge.InitializationStatus histogram, so |
| 84 // the ordering should not be changed. New error codes should be | 82 // the ordering should not be changed. New error codes should be |
| 85 // added at the end, before NUM_ITEMS. | 83 // added at the end, before NUM_ITEMS. |
| 86 enum class ConnectionInitializationStatusCode { | 84 enum class ConnectionInitializationStatusCode { |
| 87 SUCCESS = 0, | 85 SUCCESS = 0, |
| 88 NATIVE_NOTIFICATIONS_NOT_SUPPORTED = 1, | 86 NATIVE_NOTIFICATIONS_NOT_SUPPORTED = 1, |
| 89 MISSING_REQUIRED_CAPABILITIES = 2, | 87 MISSING_REQUIRED_CAPABILITIES = 2, |
| 90 COULD_NOT_CONNECT_TO_SIGNALS = 3, | 88 COULD_NOT_CONNECT_TO_SIGNALS = 3, |
| 91 INCOMPATIBLE_SPEC_VERSION = 4, | 89 INCOMPATIBLE_SPEC_VERSION = 4, // DEPRECATED |
| 92 NUM_ITEMS | 90 NUM_ITEMS |
| 93 }; | 91 }; |
| 94 | 92 |
| 95 int ClampInt(int value, int low, int hi) { | 93 int ClampInt(int value, int low, int hi) { |
| 96 return std::max(std::min(value, hi), low); | 94 return std::max(std::min(value, hi), low); |
| 97 } | 95 } |
| 98 | 96 |
| 99 base::string16 CreateNotificationTitle(const Notification& notification) { | 97 base::string16 CreateNotificationTitle(const Notification& notification) { |
| 100 base::string16 title; | 98 base::string16 title; |
| 101 if (notification.type() == message_center::NOTIFICATION_TYPE_PROGRESS) { | 99 if (notification.type() == message_center::NOTIFICATION_TYPE_PROGRESS) { |
| (...skipping 323 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 425 std::vector<std::string> capabilities; | 423 std::vector<std::string> capabilities; |
| 426 reader.PopArrayOfStrings(&capabilities); | 424 reader.PopArrayOfStrings(&capabilities); |
| 427 for (const std::string& capability : capabilities) | 425 for (const std::string& capability : capabilities) |
| 428 capabilities_.insert(capability); | 426 capabilities_.insert(capability); |
| 429 } | 427 } |
| 430 RecordMetricsForCapabilities(); | 428 RecordMetricsForCapabilities(); |
| 431 PostTaskToUiThread(base::BindOnce( | 429 PostTaskToUiThread(base::BindOnce( |
| 432 &NotificationPlatformBridgeLinuxImpl::SetBodyImagesSupported, this, | 430 &NotificationPlatformBridgeLinuxImpl::SetBodyImagesSupported, this, |
| 433 base::ContainsKey(capabilities_, kCapabilityBodyImages))); | 431 base::ContainsKey(capabilities_, kCapabilityBodyImages))); |
| 434 | 432 |
| 435 dbus::MethodCall get_server_information_call(kFreedesktopNotificationsName, | |
| 436 kMethodGetServerInformation); | |
| 437 std::unique_ptr<dbus::Response> server_information_response = | |
| 438 notification_proxy_->CallMethodAndBlock( | |
| 439 &get_server_information_call, | |
| 440 dbus::ObjectProxy::TIMEOUT_USE_DEFAULT); | |
| 441 if (server_information_response) { | |
| 442 dbus::MessageReader reader(server_information_response.get()); | |
| 443 std::string spec_version; | |
| 444 reader.PopString(&spec_version); // name | |
| 445 reader.PopString(&spec_version); // vendor | |
| 446 reader.PopString(&spec_version); // version | |
| 447 reader.PopString(&spec_version); // spec_version | |
| 448 spec_version_ = base::Version(spec_version); | |
| 449 } | |
| 450 // The minimum supported spec version is 1.1, because this was the | |
| 451 // version that added image hints. | |
| 452 if (!spec_version_.IsValid() || | |
| 453 spec_version_ < base::Version(std::vector<uint32_t>{1, 1})) { | |
| 454 OnConnectionInitializationFinishedOnTaskRunner( | |
| 455 ConnectionInitializationStatusCode::INCOMPATIBLE_SPEC_VERSION); | |
| 456 return; | |
| 457 } | |
| 458 | |
| 459 connected_signals_barrier_ = base::BarrierClosure( | 433 connected_signals_barrier_ = base::BarrierClosure( |
| 460 2, base::Bind(&NotificationPlatformBridgeLinuxImpl:: | 434 2, base::Bind(&NotificationPlatformBridgeLinuxImpl:: |
| 461 OnConnectionInitializationFinishedOnTaskRunner, | 435 OnConnectionInitializationFinishedOnTaskRunner, |
| 462 this, ConnectionInitializationStatusCode::SUCCESS)); | 436 this, ConnectionInitializationStatusCode::SUCCESS)); |
| 463 notification_proxy_->ConnectToSignal( | 437 notification_proxy_->ConnectToSignal( |
| 464 kFreedesktopNotificationsName, kSignalActionInvoked, | 438 kFreedesktopNotificationsName, kSignalActionInvoked, |
| 465 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this), | 439 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this), |
| 466 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, | 440 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, |
| 467 this)); | 441 this)); |
| 468 notification_proxy_->ConnectToSignal( | 442 notification_proxy_->ConnectToSignal( |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 624 desktop_file = desktop_file.RemoveFinalExtension(); | 598 desktop_file = desktop_file.RemoveFinalExtension(); |
| 625 dbus::MessageWriter desktop_entry_writer(nullptr); | 599 dbus::MessageWriter desktop_entry_writer(nullptr); |
| 626 hints_writer.OpenDictEntry(&desktop_entry_writer); | 600 hints_writer.OpenDictEntry(&desktop_entry_writer); |
| 627 desktop_entry_writer.AppendString("desktop-entry"); | 601 desktop_entry_writer.AppendString("desktop-entry"); |
| 628 desktop_entry_writer.AppendVariantOfString(desktop_file.value()); | 602 desktop_entry_writer.AppendVariantOfString(desktop_file.value()); |
| 629 hints_writer.CloseContainer(&desktop_entry_writer); | 603 hints_writer.CloseContainer(&desktop_entry_writer); |
| 630 | 604 |
| 631 std::unique_ptr<ResourceFile> icon_file = | 605 std::unique_ptr<ResourceFile> icon_file = |
| 632 WriteDataToTmpFile(notification->icon().As1xPNGBytes()); | 606 WriteDataToTmpFile(notification->icon().As1xPNGBytes()); |
| 633 if (icon_file) { | 607 if (icon_file) { |
| 634 dbus::MessageWriter image_path_writer(nullptr); | 608 for (const std::string& hint_name : {"image_path", "image-path"}) { |
| 635 hints_writer.OpenDictEntry(&image_path_writer); | 609 dbus::MessageWriter image_path_writer(nullptr); |
| 636 image_path_writer.AppendString( | 610 hints_writer.OpenDictEntry(&image_path_writer); |
| 637 spec_version_ == base::Version(std::vector<uint32_t>{1, 1}) | 611 image_path_writer.AppendString(hint_name); |
| 638 ? "image_path" | 612 image_path_writer.AppendVariantOfString(icon_file->file_path().value()); |
| 639 : "image-path"); | 613 hints_writer.CloseContainer(&image_path_writer); |
| 640 image_path_writer.AppendVariantOfString(icon_file->file_path().value()); | 614 } |
| 641 hints_writer.CloseContainer(&image_path_writer); | |
| 642 data->resource_files.push_back(std::move(icon_file)); | 615 data->resource_files.push_back(std::move(icon_file)); |
| 643 } | 616 } |
| 644 | 617 |
| 645 writer.CloseContainer(&hints_writer); | 618 writer.CloseContainer(&hints_writer); |
| 646 | 619 |
| 647 const int32_t kExpireTimeoutDefault = -1; | 620 const int32_t kExpireTimeoutDefault = -1; |
| 648 const int32_t kExpireTimeoutNever = 0; | 621 const int32_t kExpireTimeoutNever = 0; |
| 649 writer.AppendInt32(notification->never_timeout() ? kExpireTimeoutNever | 622 writer.AppendInt32(notification->never_timeout() ? kExpireTimeoutNever |
| 650 : kExpireTimeoutDefault); | 623 : kExpireTimeoutDefault); |
| 651 | 624 |
| (...skipping 217 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 869 | 842 |
| 870 ////////////////////////////////////////////////////////////////////////////// | 843 ////////////////////////////////////////////////////////////////////////////// |
| 871 // Members used only on the task runner thread. | 844 // Members used only on the task runner thread. |
| 872 | 845 |
| 873 scoped_refptr<dbus::Bus> bus_; | 846 scoped_refptr<dbus::Bus> bus_; |
| 874 | 847 |
| 875 dbus::ObjectProxy* notification_proxy_ = nullptr; | 848 dbus::ObjectProxy* notification_proxy_ = nullptr; |
| 876 | 849 |
| 877 std::unordered_set<std::string> capabilities_; | 850 std::unordered_set<std::string> capabilities_; |
| 878 | 851 |
| 879 base::Version spec_version_; | |
| 880 | |
| 881 base::Closure connected_signals_barrier_; | 852 base::Closure connected_signals_barrier_; |
| 882 | 853 |
| 883 // A std::set<std::unique_ptr<T>> doesn't work well because | 854 // A std::set<std::unique_ptr<T>> doesn't work well because |
| 884 // eg. std::set::erase(T) would require a std::unique_ptr<T> | 855 // eg. std::set::erase(T) would require a std::unique_ptr<T> |
| 885 // argument, so the data would get double-destructed. | 856 // argument, so the data would get double-destructed. |
| 886 template <typename T> | 857 template <typename T> |
| 887 using UnorderedUniqueSet = std::unordered_map<T*, std::unique_ptr<T>>; | 858 using UnorderedUniqueSet = std::unordered_map<T*, std::unique_ptr<T>>; |
| 888 | 859 |
| 889 UnorderedUniqueSet<NotificationData> notifications_; | 860 UnorderedUniqueSet<NotificationData> notifications_; |
| 890 | 861 |
| (...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 926 } | 897 } |
| 927 | 898 |
| 928 void NotificationPlatformBridgeLinux::SetReadyCallback( | 899 void NotificationPlatformBridgeLinux::SetReadyCallback( |
| 929 NotificationBridgeReadyCallback callback) { | 900 NotificationBridgeReadyCallback callback) { |
| 930 impl_->SetReadyCallback(std::move(callback)); | 901 impl_->SetReadyCallback(std::move(callback)); |
| 931 } | 902 } |
| 932 | 903 |
| 933 void NotificationPlatformBridgeLinux::CleanUp() { | 904 void NotificationPlatformBridgeLinux::CleanUp() { |
| 934 impl_->CleanUp(); | 905 impl_->CleanUp(); |
| 935 } | 906 } |
| OLD | NEW |