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 |