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

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

Issue 2856753002: Linux native notifications: Add server capabilities metrics (Closed)
Patch Set: Rebase 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 #include <memory> 8 #include <memory>
9 #include <set> 9 #include <set>
10 #include <unordered_map> 10 #include <unordered_map>
11 #include <unordered_set>
11 #include <utility> 12 #include <utility>
12 #include <vector> 13 #include <vector>
13 14
14 #include "base/barrier_closure.h" 15 #include "base/barrier_closure.h"
15 #include "base/files/file_util.h" 16 #include "base/files/file_util.h"
17 #include "base/metrics/histogram_macros.h"
16 #include "base/strings/nullable_string16.h" 18 #include "base/strings/nullable_string16.h"
17 #include "base/strings/string_number_conversions.h" 19 #include "base/strings/string_number_conversions.h"
18 #include "base/strings/string_util.h" 20 #include "base/strings/string_util.h"
19 #include "base/strings/utf_string_conversions.h" 21 #include "base/strings/utf_string_conversions.h"
20 #include "base/task_scheduler/post_task.h" 22 #include "base/task_scheduler/post_task.h"
21 #include "chrome/browser/browser_process.h" 23 #include "chrome/browser/browser_process.h"
22 #include "chrome/browser/chrome_notification_types.h" 24 #include "chrome/browser/chrome_notification_types.h"
23 #include "chrome/browser/notifications/native_notification_display_service.h" 25 #include "chrome/browser/notifications/native_notification_display_service.h"
24 #include "chrome/browser/notifications/notification.h" 26 #include "chrome/browser/notifications/notification.h"
25 #include "chrome/browser/notifications/notification_display_service_factory.h" 27 #include "chrome/browser/notifications/notification_display_service_factory.h"
26 #include "chrome/browser/profiles/profile_manager.h" 28 #include "chrome/browser/profiles/profile_manager.h"
27 #include "chrome/browser/shell_integration_linux.h" 29 #include "chrome/browser/shell_integration_linux.h"
28 #include "content/public/browser/browser_thread.h" 30 #include "content/public/browser/browser_thread.h"
29 #include "content/public/browser/notification_service.h" 31 #include "content/public/browser/notification_service.h"
30 #include "dbus/bus.h" 32 #include "dbus/bus.h"
31 #include "dbus/message.h" 33 #include "dbus/message.h"
32 #include "dbus/object_proxy.h" 34 #include "dbus/object_proxy.h"
33 #include "ui/gfx/image/image_skia.h" 35 #include "ui/gfx/image/image_skia.h"
34 36
35 namespace { 37 namespace {
36 38
37 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications"; 39 const char kFreedesktopNotificationsName[] = "org.freedesktop.Notifications";
38 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications"; 40 const char kFreedesktopNotificationsPath[] = "/org/freedesktop/Notifications";
39 41
40 const char kDefaultButtonId[] = "default"; 42 const char kDefaultButtonId[] = "default";
41 const char kSettingsButtonId[] = "settings"; 43 const char kSettingsButtonId[] = "settings";
42 44
45 // The values in this enumeration correspond to those of the
46 // Linux.NotificationPlatformBridge.InitializationStatus histogram, so
47 // the ordering should not be changed. New error codes should be
48 // added at the end, before NUM_ITEMS.
49 enum class ConnectionInitializationStatusCode {
50 SUCCESS = 0,
51 NATIVE_NOTIFICATIONS_NOT_SUPPORTED = 1,
52 MISSING_REQUIRED_CAPABILITIES = 2,
53 COULD_NOT_CONNECT_TO_SIGNALS = 3,
54 NUM_ITEMS
55 };
56
43 gfx::Image DeepCopyImage(const gfx::Image& image) { 57 gfx::Image DeepCopyImage(const gfx::Image& image) {
44 std::unique_ptr<gfx::ImageSkia> image_skia(image.CopyImageSkia()); 58 std::unique_ptr<gfx::ImageSkia> image_skia(image.CopyImageSkia());
45 return gfx::Image(*image_skia); 59 return gfx::Image(*image_skia);
46 } 60 }
47 61
48 int NotificationPriorityToFdoUrgency(int priority) { 62 int NotificationPriorityToFdoUrgency(int priority) {
49 enum FdoUrgency { 63 enum FdoUrgency {
50 LOW = 0, 64 LOW = 0,
51 NORMAL = 1, 65 NORMAL = 1,
52 CRITICAL = 2, 66 CRITICAL = 2,
(...skipping 251 matching lines...) Expand 10 before | Expand all | Expand 10 after
304 bus_options.bus_type = dbus::Bus::SESSION; 318 bus_options.bus_type = dbus::Bus::SESSION;
305 bus_options.connection_type = dbus::Bus::PRIVATE; 319 bus_options.connection_type = dbus::Bus::PRIVATE;
306 bus_options.dbus_task_runner = task_runner_; 320 bus_options.dbus_task_runner = task_runner_;
307 bus_ = make_scoped_refptr(new dbus::Bus(bus_options)); 321 bus_ = make_scoped_refptr(new dbus::Bus(bus_options));
308 } 322 }
309 323
310 notification_proxy_ = 324 notification_proxy_ =
311 bus_->GetObjectProxy(kFreedesktopNotificationsName, 325 bus_->GetObjectProxy(kFreedesktopNotificationsName,
312 dbus::ObjectPath(kFreedesktopNotificationsPath)); 326 dbus::ObjectPath(kFreedesktopNotificationsPath));
313 if (!notification_proxy_) { 327 if (!notification_proxy_) {
314 OnConnectionInitializationFinishedOnTaskRunner(false); 328 OnConnectionInitializationFinishedOnTaskRunner(
329 ConnectionInitializationStatusCode::
330 NATIVE_NOTIFICATIONS_NOT_SUPPORTED);
315 return; 331 return;
316 } 332 }
317 333
334 dbus::MethodCall get_capabilities_call(kFreedesktopNotificationsName,
335 "GetCapabilities");
336 std::unique_ptr<dbus::Response> capabilities_response =
337 notification_proxy_->CallMethodAndBlock(
338 &get_capabilities_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT);
339 if (capabilities_response) {
340 dbus::MessageReader reader(capabilities_response.get());
341 std::vector<std::string> capabilities;
342 reader.PopArrayOfStrings(&capabilities);
343 for (const std::string& capability : capabilities)
344 capabilities_.insert(capability);
345 }
346 RecordMetricsForCapabilities();
347
318 connected_signals_barrier_ = base::BarrierClosure( 348 connected_signals_barrier_ = base::BarrierClosure(
319 2, base::Bind(&NotificationPlatformBridgeLinuxImpl:: 349 2, base::Bind(&NotificationPlatformBridgeLinuxImpl::
320 OnConnectionInitializationFinishedOnTaskRunner, 350 OnConnectionInitializationFinishedOnTaskRunner,
321 this, true)); 351 this, ConnectionInitializationStatusCode::SUCCESS));
322 notification_proxy_->ConnectToSignal( 352 notification_proxy_->ConnectToSignal(
323 kFreedesktopNotificationsName, "ActionInvoked", 353 kFreedesktopNotificationsName, "ActionInvoked",
324 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this), 354 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnActionInvoked, this),
325 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, 355 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected,
326 this)); 356 this));
327 notification_proxy_->ConnectToSignal( 357 notification_proxy_->ConnectToSignal(
328 kFreedesktopNotificationsName, "NotificationClosed", 358 kFreedesktopNotificationsName, "NotificationClosed",
329 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnNotificationClosed, 359 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnNotificationClosed,
330 this), 360 this),
331 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected, 361 base::Bind(&NotificationPlatformBridgeLinuxImpl::OnSignalConnected,
(...skipping 245 matching lines...) Expand 10 before | Expand all | Expand 10 after
577 void OnConnectionInitializationFinishedOnUiThread(bool success) { 607 void OnConnectionInitializationFinishedOnUiThread(bool success) {
578 DCHECK_CURRENTLY_ON(content::BrowserThread::UI); 608 DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
579 connected_ = success; 609 connected_ = success;
580 for (auto& callback : on_connected_callbacks_) 610 for (auto& callback : on_connected_callbacks_)
581 std::move(callback).Run(success); 611 std::move(callback).Run(success);
582 on_connected_callbacks_.clear(); 612 on_connected_callbacks_.clear();
583 if (!success) 613 if (!success)
584 CleanUp(); 614 CleanUp();
585 } 615 }
586 616
587 void OnConnectionInitializationFinishedOnTaskRunner(bool success) { 617 void OnConnectionInitializationFinishedOnTaskRunner(
618 ConnectionInitializationStatusCode status) {
588 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 619 DCHECK(task_runner_->RunsTasksOnCurrentThread());
589 PostTaskToUiThread( 620 UMA_HISTOGRAM_ENUMERATION(
590 base::BindOnce(&NotificationPlatformBridgeLinuxImpl:: 621 "Notifications.Linux.BridgeInitializationStatus",
591 OnConnectionInitializationFinishedOnUiThread, 622 static_cast<int>(status),
592 this, success)); 623 static_cast<int>(ConnectionInitializationStatusCode::NUM_ITEMS));
624 PostTaskToUiThread(base::BindOnce(
625 &NotificationPlatformBridgeLinuxImpl::
626 OnConnectionInitializationFinishedOnUiThread,
627 this, status == ConnectionInitializationStatusCode::SUCCESS));
593 } 628 }
594 629
595 void OnSignalConnected(const std::string& interface_name, 630 void OnSignalConnected(const std::string& interface_name,
596 const std::string& signal_name, 631 const std::string& signal_name,
597 bool success) { 632 bool success) {
598 DCHECK(task_runner_->RunsTasksOnCurrentThread()); 633 DCHECK(task_runner_->RunsTasksOnCurrentThread());
599 if (!success) { 634 if (!success) {
600 OnConnectionInitializationFinishedOnTaskRunner(false); 635 OnConnectionInitializationFinishedOnTaskRunner(
636 ConnectionInitializationStatusCode::COULD_NOT_CONNECT_TO_SIGNALS);
601 return; 637 return;
602 } 638 }
603 connected_signals_barrier_.Run(); 639 connected_signals_barrier_.Run();
604 } 640 }
605 641
642 void RecordMetricsForCapabilities() {
643 // Histogram macros must be called with the same name for each
644 // callsite, so we can't roll the below into a nice loop.
645 UMA_HISTOGRAM_BOOLEAN("Notifications.Freedesktop.Capabilities.ActionIcons",
646 capabilities_.count("action-icons"));
647 UMA_HISTOGRAM_BOOLEAN("Notifications.Freedesktop.Capabilities.Actions",
648 capabilities_.count("actions"));
649 UMA_HISTOGRAM_BOOLEAN("Notifications.Freedesktop.Capabilities.Body",
650 capabilities_.count("body"));
651 UMA_HISTOGRAM_BOOLEAN(
652 "Notifications.Freedesktop.Capabilities.BodyHyperlinks",
653 capabilities_.count("body-hyperlinks"));
654 UMA_HISTOGRAM_BOOLEAN("Notifications.Freedesktop.Capabilities.BodyImages",
655 capabilities_.count("body-images"));
656 UMA_HISTOGRAM_BOOLEAN("Notifications.Freedesktop.Capabilities.BodyMarkup",
657 capabilities_.count("body-markup"));
658 UMA_HISTOGRAM_BOOLEAN("Notifications.Freedesktop.Capabilities.IconMulti",
659 capabilities_.count("icon-multi"));
660 UMA_HISTOGRAM_BOOLEAN("Notifications.Freedesktop.Capabilities.IconStatic",
661 capabilities_.count("icon-static"));
662 UMA_HISTOGRAM_BOOLEAN("Notifications.Freedesktop.Capabilities.Persistence",
663 capabilities_.count("persistence"));
664 UMA_HISTOGRAM_BOOLEAN("Notifications.Freedesktop.Capabilities.Sound",
665 capabilities_.count("sound"));
666 }
667
606 ////////////////////////////////////////////////////////////////////////////// 668 //////////////////////////////////////////////////////////////////////////////
607 // Members used only on the UI thread. 669 // Members used only on the UI thread.
608 670
609 scoped_refptr<base::SequencedTaskRunner> task_runner_; 671 scoped_refptr<base::SequencedTaskRunner> task_runner_;
610 672
611 content::NotificationRegistrar registrar_; 673 content::NotificationRegistrar registrar_;
612 674
613 // State necessary for OnConnectionInitializationFinished() and 675 // State necessary for OnConnectionInitializationFinished() and
614 // SetReadyCallback(). 676 // SetReadyCallback().
615 base::Optional<bool> connected_; 677 base::Optional<bool> connected_;
616 std::vector<NotificationBridgeReadyCallback> on_connected_callbacks_; 678 std::vector<NotificationBridgeReadyCallback> on_connected_callbacks_;
617 679
618 ////////////////////////////////////////////////////////////////////////////// 680 //////////////////////////////////////////////////////////////////////////////
619 // Members used only on the task runner thread. 681 // Members used only on the task runner thread.
620 682
621 scoped_refptr<dbus::Bus> bus_; 683 scoped_refptr<dbus::Bus> bus_;
622 684
623 dbus::ObjectProxy* notification_proxy_ = nullptr; 685 dbus::ObjectProxy* notification_proxy_ = nullptr;
624 686
687 std::unordered_set<std::string> capabilities_;
688
625 base::Closure connected_signals_barrier_; 689 base::Closure connected_signals_barrier_;
626 690
627 // A std::set<std::unique_ptr<T>> doesn't work well because 691 // A std::set<std::unique_ptr<T>> doesn't work well because
628 // eg. std::set::erase(T) would require a std::unique_ptr<T> 692 // eg. std::set::erase(T) would require a std::unique_ptr<T>
629 // argument, so the data would get double-destructed. 693 // argument, so the data would get double-destructed.
630 template <typename T> 694 template <typename T>
631 using UnorderedUniqueSet = std::unordered_map<T*, std::unique_ptr<T>>; 695 using UnorderedUniqueSet = std::unordered_map<T*, std::unique_ptr<T>>;
632 696
633 UnorderedUniqueSet<NotificationData> notifications_; 697 UnorderedUniqueSet<NotificationData> notifications_;
634 698
(...skipping 35 matching lines...) Expand 10 before | Expand all | Expand 10 after
670 } 734 }
671 735
672 void NotificationPlatformBridgeLinux::SetReadyCallback( 736 void NotificationPlatformBridgeLinux::SetReadyCallback(
673 NotificationBridgeReadyCallback callback) { 737 NotificationBridgeReadyCallback callback) {
674 impl_->SetReadyCallback(std::move(callback)); 738 impl_->SetReadyCallback(std::move(callback));
675 } 739 }
676 740
677 void NotificationPlatformBridgeLinux::CleanUp() { 741 void NotificationPlatformBridgeLinux::CleanUp() {
678 impl_->CleanUp(); 742 impl_->CleanUp();
679 } 743 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698