1 // Copyright 2018 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "ash/system/cast/cast_notification_controller.h"
6 
7 #include "ash/public/cpp/notification_utils.h"
8 #include "ash/resources/vector_icons/vector_icons.h"
9 #include "ash/shell.h"
10 #include "ash/strings/grit/ash_strings.h"
11 #include "base/bind.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "ui/base/l10n/l10n_util.h"
14 #include "ui/message_center/message_center.h"
15 #include "ui/message_center/public/cpp/notification.h"
16 
17 using message_center::MessageCenter;
18 using message_center::Notification;
19 
20 namespace ash {
21 
22 namespace {
23 
ShouldShowNotification()24 bool ShouldShowNotification() {
25   auto* cast_config = CastConfigController::Get();
26   return cast_config && cast_config->HasSinksAndRoutes() &&
27          cast_config->HasActiveRoute();
28 }
29 
GetNotificationTitle(const CastSink & sink,const CastRoute & route)30 base::string16 GetNotificationTitle(const CastSink& sink,
31                                     const CastRoute& route) {
32   switch (route.content_source) {
33     case ContentSource::kUnknown:
34       return l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST_CAST_UNKNOWN);
35     case ContentSource::kTab:
36     case ContentSource::kDesktop:
37       return l10n_util::GetStringFUTF16(
38           IDS_ASH_STATUS_TRAY_CAST_NOTIFICATION_TITLE,
39           base::UTF8ToUTF16(sink.name));
40   }
41 }
42 
GetNotificationMessage(const CastRoute & route)43 base::string16 GetNotificationMessage(const CastRoute& route) {
44   switch (route.content_source) {
45     case ContentSource::kUnknown:
46       return base::string16();
47     case ContentSource::kTab:
48       return base::UTF8ToUTF16(route.title);
49     case ContentSource::kDesktop:
50       return l10n_util::GetStringUTF16(
51           IDS_ASH_STATUS_TRAY_CAST_CAST_DESKTOP_NOTIFICATION_MESSAGE);
52   }
53 }
54 
55 const char kNotificationId[] = "chrome://cast";
56 const char kNotifierId[] = "ash.cast";
57 
58 }  // namespace
59 
CastNotificationController()60 CastNotificationController::CastNotificationController() {
61   if (CastConfigController::Get()) {
62     CastConfigController::Get()->AddObserver(this);
63     CastConfigController::Get()->RequestDeviceRefresh();
64   }
65 }
66 
~CastNotificationController()67 CastNotificationController::~CastNotificationController() {
68   if (CastConfigController::Get())
69     CastConfigController::Get()->RemoveObserver(this);
70 }
71 
OnDevicesUpdated(const std::vector<SinkAndRoute> & devices)72 void CastNotificationController::OnDevicesUpdated(
73     const std::vector<SinkAndRoute>& devices) {
74   if (!ShouldShowNotification()) {
75     message_center::MessageCenter::Get()->RemoveNotification(
76         kNotificationId, false /* by_user */);
77     return;
78   }
79 
80   for (const auto& device : devices) {
81     const CastSink& sink = device.sink;
82     const CastRoute& route = device.route;
83 
84     // We only want to display casts that came from this machine, since on a
85     // busy network many other people could be casting.
86     if (route.id.empty() || !route.is_local_source)
87       continue;
88 
89     displayed_route_id_ = route.id;
90 
91     message_center::RichNotificationData data;
92     data.buttons.push_back(message_center::ButtonInfo(
93         l10n_util::GetStringUTF16(IDS_ASH_STATUS_TRAY_CAST_STOP)));
94 
95     std::unique_ptr<Notification> notification = CreateSystemNotification(
96         message_center::NOTIFICATION_TYPE_SIMPLE, kNotificationId,
97         GetNotificationTitle(sink, route), GetNotificationMessage(route),
98         base::string16() /* display_source */, GURL(),
99         message_center::NotifierId(
100             message_center::NotifierType::SYSTEM_COMPONENT, kNotifierId),
101         data,
102         base::MakeRefCounted<message_center::HandleNotificationClickDelegate>(
103             base::BindRepeating(&CastNotificationController::StopCasting,
104                                 weak_ptr_factory_.GetWeakPtr())),
105         kSystemMenuCastIcon,
106         message_center::SystemNotificationWarningLevel::NORMAL);
107     notification->set_pinned(true);
108     MessageCenter::Get()->AddNotification(std::move(notification));
109 
110     break;
111   }
112 }
113 
StopCasting()114 void CastNotificationController::StopCasting() {
115   CastConfigController::Get()->StopCasting(displayed_route_id_);
116   Shell::Get()->metrics()->RecordUserMetricsAction(
117       UMA_STATUS_AREA_CAST_STOP_CAST);
118 }
119 
120 }  // namespace ash
121