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

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

Issue 2856753002: Linux native notifications: Add server capabilities metrics (Closed)
Patch Set: address peter@'s comments 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"
11 #include "base/metrics/histogram_macros.h"
11 #include "base/strings/nullable_string16.h" 12 #include "base/strings/nullable_string16.h"
12 #include "base/strings/string_number_conversions.h" 13 #include "base/strings/string_number_conversions.h"
13 #include "base/strings/string_util.h" 14 #include "base/strings/string_util.h"
14 #include "base/strings/utf_string_conversions.h" 15 #include "base/strings/utf_string_conversions.h"
15 #include "base/task_scheduler/post_task.h" 16 #include "base/task_scheduler/post_task.h"
16 #include "chrome/browser/browser_process.h" 17 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/chrome_notification_types.h" 18 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/notifications/native_notification_display_service.h" 19 #include "chrome/browser/notifications/native_notification_display_service.h"
19 #include "chrome/browser/notifications/notification.h" 20 #include "chrome/browser/notifications/notification.h"
20 #include "chrome/browser/notifications/notification_display_service_factory.h" 21 #include "chrome/browser/notifications/notification_display_service_factory.h"
21 #include "chrome/browser/profiles/profile_manager.h" 22 #include "chrome/browser/profiles/profile_manager.h"
22 #include "chrome/browser/shell_integration_linux.h" 23 #include "chrome/browser/shell_integration_linux.h"
23 #include "content/public/browser/browser_thread.h" 24 #include "content/public/browser/browser_thread.h"
24 #include "content/public/browser/notification_service.h" 25 #include "content/public/browser/notification_service.h"
25 #include "dbus/bus.h" 26 #include "dbus/bus.h"
26 #include "dbus/message.h" 27 #include "dbus/message.h"
27 #include "dbus/object_proxy.h" 28 #include "dbus/object_proxy.h"
28 #include "ui/gfx/image/image_skia.h" 29 #include "ui/gfx/image/image_skia.h"
29 30
30 namespace { 31 namespace {
31 32
32 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications"; 33 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications";
33 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications"; 34 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications";
34 35
35 const char kDefaultButtonId[] = "default"; 36 const char kDefaultButtonId[] = "default";
36 const char kSettingsButtonId[] = "settings"; 37 const char kSettingsButtonId[] = "settings";
37 38
39 enum class ConnectionInitializationStatusCode {
Mark P 2017/05/03 19:20:40 Please follow the practices here: https://chromium
Tom (Use chromium acct) 2017/05/03 22:20:29 Done.
40 SUCCESS = 0,
41 NATIVE_NOTIFICATIONS_NOT_SUPPORTED,
42 MISSING_REQUIRED_CAPABILITIES,
Mark P 2017/05/03 19:20:40 This value doesn't seem to be used anywhere.
Tom (Use chromium acct) 2017/05/03 22:20:29 It will be used soon in the future
43 COULD_NOT_CONNECT_TO_SIGNALS,
44 // The values in this enumeration correspond to those of the
45 // Linux.NotificationPlatformBridge.InitializationStatus histogram,
46 // so the ordering should not be changed. New error codes should be
47 // added at the end, before NUM_ITEMS.
48 NUM_ITEMS
49 };
50
38 gfx::Image DeepCopyImage(const gfx::Image& image) { 51 gfx::Image DeepCopyImage(const gfx::Image& image) {
39 std::unique_ptr<gfx::ImageSkia> image_skia(image.CopyImageSkia()); 52 std::unique_ptr<gfx::ImageSkia> image_skia(image.CopyImageSkia());
40 return gfx::Image(*image_skia); 53 return gfx::Image(*image_skia);
41 } 54 }
42 55
43 int NotificationPriorityToFdoUrgency(int priority) { 56 int NotificationPriorityToFdoUrgency(int priority) {
44 enum FdoUrgency { 57 enum FdoUrgency {
45 LOW = 0, 58 LOW = 0,
46 NORMAL = 1, 59 NORMAL = 1,
47 CRITICAL = 2, 60 CRITICAL = 2,
(...skipping 224 matching lines...) Expand 10 before | Expand all | Expand 10 after
272 dbus::Bus::Options bus_options; 285 dbus::Bus::Options bus_options;
273 bus_options.bus_type = dbus::Bus::SESSION; 286 bus_options.bus_type = dbus::Bus::SESSION;
274 bus_options.connection_type = dbus::Bus::PRIVATE; 287 bus_options.connection_type = dbus::Bus::PRIVATE;
275 bus_options.dbus_task_runner = task_runner_; 288 bus_options.dbus_task_runner = task_runner_;
276 bus_ = make_scoped_refptr(new dbus::Bus(bus_options)); 289 bus_ = make_scoped_refptr(new dbus::Bus(bus_options));
277 290
278 notification_proxy_ = 291 notification_proxy_ =
279 bus_->GetObjectProxy(kFreedesktopNotificationsName, 292 bus_->GetObjectProxy(kFreedesktopNotificationsName,
280 dbus::ObjectPath(kFreedesktopNotificationsPath)); 293 dbus::ObjectPath(kFreedesktopNotificationsPath));
281 if (!notification_proxy_) { 294 if (!notification_proxy_) {
282 OnConnectionInitializationFinishedOnTaskRunner(false); 295 OnConnectionInitializationFinishedOnTaskRunner(
296 ConnectionInitializationStatusCode::
297 NATIVE_NOTIFICATIONS_NOT_SUPPORTED);
283 return; 298 return;
284 } 299 }
285 300
301 dbus::MethodCall get_capabilities_call(kFreedesktopNotificationsName,
302 "GetCapabilities");
303 std::unique_ptr<dbus::Response> capabilities_response =
304 notification_proxy_->CallMethodAndBlock(
305 &get_capabilities_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
306 if (capabilities_response) {
307 dbus::MessageReader reader(capabilities_response.get());
308 std::vector<std::string> capabilities;
309 reader.PopArrayOfStrings(&capabilities);
310 for (const std::string& capability : capabilities)
311 capabilities_.insert(capability);
312 }
313 RecordMetricsForCapabilities();
314
286 connected_signals_barrier_ = base::BarrierClosure( 315 connected_signals_barrier_ = base::BarrierClosure(
287 2, base::Bind(&NotificationPlatformBridgeLinuxImpl:: 316 2, base::Bind(&NotificationPlatformBridgeLinuxImpl::
288 OnConnectionInitializationFinishedOnTaskRunner, 317 OnConnectionInitializationFinishedOnTaskRunner,
289 this, true)); 318 this, ConnectionInitializationStatusCode::SUCCESS));
290 notification_proxy_->ConnectToSignal( 319 notification_proxy_->ConnectToSignal(
291 kFreedesktopNotificationsName, "ActionInvoked", 320 kFreedesktopNotificationsName, "ActionInvoked",
292 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this), 321 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this),
293 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, 322 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected,
294 this)); 323 this));
295 notification_proxy_->ConnectToSignal( 324 notification_proxy_->ConnectToSignal(
296 kFreedesktopNotificationsName, "NotificationClosed", 325 kFreedesktopNotificationsName, "NotificationClosed",
297 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnNotificationClosed, 326 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnNotificationClosed,
298 this), 327 this),
299 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, 328 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected,
(...skipping 248 matching lines...) Expand 10 before | Expand all | Expand 10 after
548 void OnConnectionInitializationFinishedOnUiThread(bool success) { 577 void OnConnectionInitializationFinishedOnUiThread(bool success) {
549 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 578 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
550 connected_ = success; 579 connected_ = success;
551 for (auto& callback : on_connected_callbacks_) 580 for (auto& callback : on_connected_callbacks_)
552 std::move(callback).Run(success); 581 std::move(callback).Run(success);
553 on_connected_callbacks_.clear(); 582 on_connected_callbacks_.clear();
554 if (!success) 583 if (!success)
555 CleanUp(); 584 CleanUp();
556 } 585 }
557 586
558 void OnConnectionInitializationFinishedOnTaskRunner(bool success) { 587 void OnConnectionInitializationFinishedOnTaskRunner(
588 ConnectionInitializationStatusCode status) {
559 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 589 DCHECK(task_runner_->RunsTasksOnCurrentThread());
560 PostTaskToUiThread( 590 UMA_HISTOGRAM_ENUMERATION(
561 base::BindOnce(&NotificationPlatformBridgeLinuxImpl:: 591 "Linux.NotificationPlatformBridge.InitializationStatus",
562 OnConnectionInitializationFinishedOnUiThread, 592 static_cast<int>(status),
563 this, success)); 593 static_cast<int>(ConnectionInitializationStatusCode::NUM_ITEMS));
594 PostTaskToUiThread(base::BindOnce(
595 &NotificationPlatformBridgeLinuxImpl::
596 OnConnectionInitializationFinishedOnUiThread,
597 this, status == ConnectionInitializationStatusCode::SUCCESS));
564 } 598 }
565 599
566 void OnSignalConnected(const std::string& interface_name, 600 void OnSignalConnected(const std::string& interface_name,
567 const std::string& signal_name, 601 const std::string& signal_name,
568 bool success) { 602 bool success) {
569 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 603 DCHECK(task_runner_->RunsTasksOnCurrentThread());
570 if (!success) { 604 if (!success) {
571 OnConnectionInitializationFinishedOnTaskRunner(false); 605 OnConnectionInitializationFinishedOnTaskRunner(
606 ConnectionInitializationStatusCode::COULD_NOT_CONNECT_TO_SIGNALS);
572 return; 607 return;
573 } 608 }
574 connected_signals_barrier_.Run(); 609 connected_signals_barrier_.Run();
575 } 610 }
576 611
612 void RecordMetricsForCapabilities() {
613 // Histogram macros must be called with the same name for each
614 // callsite, so we can't roll the below into a nice loop.
Mark P 2017/05/03 19:20:40 Thank you for the comment.
615 UMA_HISTOGRAM_BOOLEAN("Freedesktop.Notifications.Capabilities.ActionIcons",
616 capabilities_.count("action-icons"));
617 UMA_HISTOGRAM_BOOLEAN("Freedesktop.Notifications.Capabilities.Actions",
618 capabilities_.count("actions"));
619 UMA_HISTOGRAM_BOOLEAN("Freedesktop.Notifications.Capabilities.Body",
620 capabilities_.count("body"));
621 UMA_HISTOGRAM_BOOLEAN(
622 "Freedesktop.Notifications.Capabilities.BodyHyperlinks",
623 capabilities_.count("body-hyperlinks"));
624 UMA_HISTOGRAM_BOOLEAN("Freedesktop.Notifications.Capabilities.BodyImages",
625 capabilities_.count("body-images"));
626 UMA_HISTOGRAM_BOOLEAN("Freedesktop.Notifications.Capabilities.BodyMarkup",
627 capabilities_.count("body-markup"));
628 UMA_HISTOGRAM_BOOLEAN("Freedesktop.Notifications.Capabilities.IconMulti",
629 capabilities_.count("icon-multi"));
630 UMA_HISTOGRAM_BOOLEAN("Freedesktop.Notifications.Capabilities.IconStatic",
631 capabilities_.count("icon-static"));
632 UMA_HISTOGRAM_BOOLEAN("Freedesktop.Notifications.Capabilities.Persistence",
633 capabilities_.count("persistence"));
634 UMA_HISTOGRAM_BOOLEAN("Freedesktop.Notifications.Capabilities.Sound",
635 capabilities_.count("sound"));
636 }
637
577 ////////////////////////////////////////////////////////////////////////////// 638 //////////////////////////////////////////////////////////////////////////////
578 // Members used only on the UI thread. 639 // Members used only on the UI thread.
579 640
580 scoped_refptr<base::SequencedTaskRunner> task_runner_; 641 scoped_refptr<base::SequencedTaskRunner> task_runner_;
581 642
582 content::NotificationRegistrar registrar_; 643 content::NotificationRegistrar registrar_;
583 644
584 // State necessary for OnConnectionInitializationFinished() and 645 // State necessary for OnConnectionInitializationFinished() and
585 // SetReadyCallback(). 646 // SetReadyCallback().
586 base::Optional<bool> connected_; 647 base::Optional<bool> connected_;
587 std::vector<NotificationBridgeReadyCallback> on_connected_callbacks_; 648 std::vector<NotificationBridgeReadyCallback> on_connected_callbacks_;
588 649
589 bool cleanup_posted_ = false; 650 bool cleanup_posted_ = false;
590 651
591 ////////////////////////////////////////////////////////////////////////////// 652 //////////////////////////////////////////////////////////////////////////////
592 // Members used only on the task runner thread. 653 // Members used only on the task runner thread.
593 654
594 scoped_refptr<dbus::Bus> bus_; 655 scoped_refptr<dbus::Bus> bus_;
595 656
596 dbus::ObjectProxy* notification_proxy_ = nullptr; 657 dbus::ObjectProxy* notification_proxy_ = nullptr;
597 658
659 std::unordered_set<std::string> capabilities_;
660
598 base::Closure connected_signals_barrier_; 661 base::Closure connected_signals_barrier_;
599 662
600 // A std::set<std::unique_ptr<T>> doesn't work well because 663 // 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> 664 // eg. std::set::erase(T) would require a std::unique_ptr<T>
602 // argument, so the data would get double-destructed. 665 // argument, so the data would get double-destructed.
603 template <typename T> 666 template <typename T>
604 using UnorderedUniqueSet = std::unordered_map<T*, std::unique_ptr<T>>; 667 using UnorderedUniqueSet = std::unordered_map<T*, std::unique_ptr<T>>;
605 668
606 UnorderedUniqueSet<NotificationData> notifications_; 669 UnorderedUniqueSet<NotificationData> notifications_;
607 670
(...skipping 25 matching lines...) Expand all
633 const std::string& profile_id, 696 const std::string& profile_id,
634 bool incognito, 697 bool incognito,
635 const GetDisplayedNotificationsCallback& callback) const { 698 const GetDisplayedNotificationsCallback& callback) const {
636 impl_->GetDisplayed(profile_id, incognito, callback); 699 impl_->GetDisplayed(profile_id, incognito, callback);
637 } 700 }
638 701
639 void NotificationPlatformBridgeLinux::SetReadyCallback( 702 void NotificationPlatformBridgeLinux::SetReadyCallback(
640 NotificationBridgeReadyCallback callback) { 703 NotificationBridgeReadyCallback callback) {
641 impl_->SetReadyCallback(std::move(callback)); 704 impl_->SetReadyCallback(std::move(callback));
642 } 705 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698