1 // Copyright 2016 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/public/cpp/external_arc/message_center/arc_notification_manager.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "ash/public/cpp/arc_app_id_provider.h"
11 #include "ash/public/cpp/ash_features.h"
12 #include "ash/public/cpp/external_arc/message_center/arc_notification_delegate.h"
13 #include "ash/public/cpp/external_arc/message_center/arc_notification_item_impl.h"
14 #include "ash/public/cpp/external_arc/message_center/arc_notification_view.h"
15 #include "ash/public/cpp/message_center/arc_notification_constants.h"
16 #include "ash/public/cpp/message_center/arc_notification_manager_delegate.h"
17 #include "base/bind.h"
18 #include "base/command_line.h"
19 #include "base/stl_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "components/arc/session/mojo_channel.h"
22 #include "ui/message_center/lock_screen/lock_screen_controller.h"
23 #include "ui/message_center/message_center_impl.h"
24 #include "ui/message_center/message_center_observer.h"
25 #include "ui/message_center/views/message_view_factory.h"
26
27 using arc::ConnectionHolder;
28 using arc::MojoChannel;
29 using arc::mojom::ArcDoNotDisturbStatus;
30 using arc::mojom::ArcDoNotDisturbStatusPtr;
31 using arc::mojom::ArcNotificationData;
32 using arc::mojom::ArcNotificationDataPtr;
33 using arc::mojom::ArcNotificationEvent;
34 using arc::mojom::ArcNotificationPriority;
35 using arc::mojom::MessageCenterVisibility;
36 using arc::mojom::NotificationConfiguration;
37 using arc::mojom::NotificationConfigurationPtr;
38 using arc::mojom::NotificationsHost;
39 using arc::mojom::NotificationsInstance;
40
41 namespace ash {
42 namespace {
43
44 constexpr char kPlayStorePackageName[] = "com.android.vending";
45
CreateCustomMessageView(const message_center::Notification & notification)46 std::unique_ptr<message_center::MessageView> CreateCustomMessageView(
47 const message_center::Notification& notification) {
48 DCHECK_EQ(notification.notifier_id().type,
49 message_center::NotifierType::ARC_APPLICATION);
50 DCHECK_EQ(kArcNotificationCustomViewType, notification.custom_view_type());
51 auto* arc_delegate =
52 static_cast<ArcNotificationDelegate*>(notification.delegate());
53 return arc_delegate->CreateCustomMessageView(notification);
54 }
55
56 class DoNotDisturbManager : public message_center::MessageCenterObserver {
57 public:
DoNotDisturbManager(ArcNotificationManager * manager)58 explicit DoNotDisturbManager(ArcNotificationManager* manager)
59 : manager_(manager) {}
OnQuietModeChanged(bool in_quiet_mode)60 void OnQuietModeChanged(bool in_quiet_mode) override {
61 manager_->SetDoNotDisturbStatusOnAndroid(in_quiet_mode);
62 }
63
64 private:
65 ArcNotificationManager* const manager_;
66
67 DISALLOW_COPY_AND_ASSIGN(DoNotDisturbManager);
68 };
69
70 class VisibilityManager : public message_center::MessageCenterObserver {
71 public:
VisibilityManager(ArcNotificationManager * manager)72 explicit VisibilityManager(ArcNotificationManager* manager)
73 : manager_(manager) {}
OnCenterVisibilityChanged(message_center::Visibility visibility)74 void OnCenterVisibilityChanged(
75 message_center::Visibility visibility) override {
76 manager_->OnMessageCenterVisibilityChanged(toMojom(visibility));
77 }
78
79 private:
toMojom(message_center::Visibility visibility)80 static MessageCenterVisibility toMojom(
81 message_center::Visibility visibility) {
82 if (visibility == message_center::Visibility::VISIBILITY_TRANSIENT)
83 return MessageCenterVisibility::VISIBILITY_TRANSIENT;
84 if (visibility == message_center::Visibility::VISIBILITY_MESSAGE_CENTER)
85 return MessageCenterVisibility::VISIBILITY_MESSAGE_CENTER;
86 VLOG(2) << "Unknown message_center::Visibility: " << visibility;
87 return MessageCenterVisibility::VISIBILITY_TRANSIENT;
88 }
89
90 ArcNotificationManager* const manager_;
91
92 DISALLOW_COPY_AND_ASSIGN(VisibilityManager);
93 };
94
95 } // namespace
96
97 class ArcNotificationManager::InstanceOwner {
98 public:
99 InstanceOwner() = default;
100 ~InstanceOwner() = default;
101
SetInstanceRemote(mojo::PendingRemote<arc::mojom::NotificationsInstance> instance_remote)102 void SetInstanceRemote(
103 mojo::PendingRemote<arc::mojom::NotificationsInstance> instance_remote) {
104 DCHECK(!channel_);
105
106 channel_ =
107 std::make_unique<MojoChannel<NotificationsInstance, NotificationsHost>>(
108 &holder_, std::move(instance_remote));
109
110 // Using base::Unretained because |this| owns |channel_|.
111 channel_->set_disconnect_handler(
112 base::BindOnce(&InstanceOwner::OnDisconnected, base::Unretained(this)));
113 channel_->QueryVersion();
114 }
115
holder()116 ConnectionHolder<NotificationsInstance, NotificationsHost>* holder() {
117 return &holder_;
118 }
119
120 private:
OnDisconnected()121 void OnDisconnected() { channel_.reset(); }
122
123 ConnectionHolder<NotificationsInstance, NotificationsHost> holder_;
124 std::unique_ptr<MojoChannel<NotificationsInstance, NotificationsHost>>
125 channel_;
126
127 DISALLOW_COPY_AND_ASSIGN(InstanceOwner);
128 };
129
130 // static
SetCustomNotificationViewFactory()131 void ArcNotificationManager::SetCustomNotificationViewFactory() {
132 message_center::MessageViewFactory::SetCustomNotificationViewFactory(
133 kArcNotificationCustomViewType,
134 base::BindRepeating(&CreateCustomMessageView));
135 }
136
ArcNotificationManager()137 ArcNotificationManager::ArcNotificationManager()
138 : instance_owner_(std::make_unique<InstanceOwner>()) {}
139
~ArcNotificationManager()140 ArcNotificationManager::~ArcNotificationManager() {
141 for (auto& obs : observers_)
142 obs.OnArcNotificationManagerDestroyed(this);
143
144 message_center_->RemoveObserver(do_not_disturb_manager_.get());
145 message_center_->RemoveObserver(visibility_manager_.get());
146
147 instance_owner_->holder()->RemoveObserver(this);
148 instance_owner_->holder()->SetHost(nullptr);
149
150 // Ensures that any callback tied to |instance_owner_| is not invoked.
151 instance_owner_.reset();
152 }
153
SetInstance(mojo::PendingRemote<arc::mojom::NotificationsInstance> instance_remote)154 void ArcNotificationManager::SetInstance(
155 mojo::PendingRemote<arc::mojom::NotificationsInstance> instance_remote) {
156 instance_owner_->SetInstanceRemote(std::move(instance_remote));
157 }
158
159 ConnectionHolder<NotificationsInstance, NotificationsHost>*
GetConnectionHolderForTest()160 ArcNotificationManager::GetConnectionHolderForTest() {
161 return instance_owner_->holder();
162 }
163
OnConnectionReady()164 void ArcNotificationManager::OnConnectionReady() {
165 DCHECK(!ready_);
166
167 // TODO(hidehiko): Replace this by ConnectionHolder::IsConnected().
168 ready_ = true;
169
170 // Sync the initial quiet mode state with Android.
171 SetDoNotDisturbStatusOnAndroid(message_center_->IsQuietMode());
172
173 // Sync the initial visibility of message center with Android.
174 auto visibility = message_center_->IsMessageCenterVisible()
175 ? MessageCenterVisibility::VISIBILITY_MESSAGE_CENTER
176 : MessageCenterVisibility::VISIBILITY_TRANSIENT;
177 OnMessageCenterVisibilityChanged(visibility);
178
179 // Set configuration variables for notifications on arc.
180 SetNotificationConfiguration();
181 }
182
OnConnectionClosed()183 void ArcNotificationManager::OnConnectionClosed() {
184 DCHECK(ready_);
185 while (!items_.empty()) {
186 auto it = items_.begin();
187 std::unique_ptr<ArcNotificationItem> item = std::move(it->second);
188 items_.erase(it);
189 item->OnClosedFromAndroid();
190 }
191 ready_ = false;
192 }
193
OnNotificationPosted(ArcNotificationDataPtr data)194 void ArcNotificationManager::OnNotificationPosted(ArcNotificationDataPtr data) {
195 if (ShouldIgnoreNotification(data.get())) {
196 VLOG(3) << "Posted notification was ignored.";
197 return;
198 }
199
200 const std::string& key = data->key;
201 auto it = items_.find(key);
202 if (it == items_.end()) {
203 // Show a notification on the primary logged-in user's desktop and badge the
204 // app icon in the shelf if the icon exists.
205 // TODO(yoshiki): Reconsider when ARC supports multi-user.
206 auto item = std::make_unique<ArcNotificationItemImpl>(
207 this, message_center_, key, main_profile_id_);
208 auto result = items_.insert(std::make_pair(key, std::move(item)));
209 DCHECK(result.second);
210 it = result.first;
211 }
212
213 std::string app_id =
214 data->package_name
215 ? ArcAppIdProvider::Get()->GetAppIdByPackageName(*data->package_name)
216 : std::string();
217 it->second->OnUpdatedFromAndroid(std::move(data), app_id);
218
219 for (auto& observer : observers_)
220 observer.OnNotificationUpdated(it->second->GetNotificationId(), app_id);
221 }
222
OnNotificationUpdated(ArcNotificationDataPtr data)223 void ArcNotificationManager::OnNotificationUpdated(
224 ArcNotificationDataPtr data) {
225 if (ShouldIgnoreNotification(data.get())) {
226 VLOG(3) << "Updated notification was ignored.";
227 return;
228 }
229
230 const std::string& key = data->key;
231 auto it = items_.find(key);
232 if (it == items_.end())
233 return;
234
235 bool is_remote_view_focused =
236 (data->remote_input_state ==
237 arc::mojom::ArcNotificationRemoteInputState::OPENED);
238 if (is_remote_view_focused && (previously_focused_notification_key_ != key)) {
239 if (!previously_focused_notification_key_.empty()) {
240 auto prev_it = items_.find(previously_focused_notification_key_);
241 // The case that another remote input is focused. Notify the previously-
242 // focused notification (if any).
243 if (prev_it != items_.end())
244 prev_it->second->OnRemoteInputActivationChanged(false);
245 }
246
247 // Notify the newly-focused notification.
248 previously_focused_notification_key_ = key;
249 it->second->OnRemoteInputActivationChanged(true);
250 } else if (!is_remote_view_focused &&
251 (previously_focused_notification_key_ == key)) {
252 // The case that the previously-focused notification gets unfocused. Notify
253 // the previously-focused notification if the notification still exists.
254 auto it = items_.find(previously_focused_notification_key_);
255 if (it != items_.end())
256 it->second->OnRemoteInputActivationChanged(false);
257
258 previously_focused_notification_key_.clear();
259 }
260
261 std::string app_id =
262 data->package_name
263 ? ArcAppIdProvider::Get()->GetAppIdByPackageName(*data->package_name)
264 : std::string();
265 it->second->OnUpdatedFromAndroid(std::move(data), app_id);
266
267 for (auto& observer : observers_)
268 observer.OnNotificationUpdated(it->second->GetNotificationId(), app_id);
269 }
270
OpenMessageCenter()271 void ArcNotificationManager::OpenMessageCenter() {
272 delegate_->ShowMessageCenter();
273 }
274
CloseMessageCenter()275 void ArcNotificationManager::CloseMessageCenter() {
276 delegate_->HideMessageCenter();
277 }
278
OnLockScreenSettingUpdated(arc::mojom::ArcLockScreenNotificationSettingPtr setting)279 void ArcNotificationManager::OnLockScreenSettingUpdated(
280 arc::mojom::ArcLockScreenNotificationSettingPtr setting) {
281 // TODO(yoshiki): sync the setting.
282 }
283
ProcessUserAction(arc::mojom::ArcNotificationUserActionDataPtr data)284 void ArcNotificationManager::ProcessUserAction(
285 arc::mojom::ArcNotificationUserActionDataPtr data) {
286 if (!data->defer_until_unlock) {
287 PerformUserAction(data->action_id, data->to_be_focused_after_unlock);
288 return;
289 }
290
291 // TODO(yoshiki): remove the static cast after refactionring.
292 static_cast<message_center::MessageCenterImpl*>(message_center_)
293 ->lock_screen_controller()
294 ->DismissLockScreenThenExecute(
295 base::BindOnce(&ArcNotificationManager::PerformUserAction,
296 weak_ptr_factory_.GetWeakPtr(), data->action_id,
297 data->to_be_focused_after_unlock),
298 base::BindOnce(&ArcNotificationManager::CancelUserAction,
299 weak_ptr_factory_.GetWeakPtr(), data->action_id));
300 }
301
PerformUserAction(uint32_t id,bool open_message_center)302 void ArcNotificationManager::PerformUserAction(uint32_t id,
303 bool open_message_center) {
304 // TODO(yoshiki): Pass the event to the message center and handle the action
305 // in the NotificationDelegate::Click() for consistency with non-arc
306 // notifications.
307 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
308 instance_owner_->holder(), PerformDeferredUserAction);
309
310 // On shutdown, the ARC channel may quit earlier than notifications.
311 if (!notifications_instance) {
312 VLOG(2) << "Trying to perform the defered operation, "
313 "but the ARC channel has already gone.";
314 return;
315 }
316
317 notifications_instance->PerformDeferredUserAction(id);
318
319 if (open_message_center) {
320 OpenMessageCenter();
321 // TODO(yoshiki): focus the target notification after opening the message
322 // center.
323 }
324 }
325
CancelUserAction(uint32_t id)326 void ArcNotificationManager::CancelUserAction(uint32_t id) {
327 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
328 instance_owner_->holder(), CancelDeferredUserAction);
329
330 // On shutdown, the ARC channel may quit earlier than notifications.
331 if (!notifications_instance) {
332 VLOG(2) << "Trying to cancel the defered operation, "
333 "but the ARC channel has already gone.";
334 return;
335 }
336
337 notifications_instance->CancelDeferredUserAction(id);
338 }
339
OnNotificationRemoved(const std::string & key)340 void ArcNotificationManager::OnNotificationRemoved(const std::string& key) {
341 auto it = items_.find(key);
342 if (it == items_.end()) {
343 VLOG(3) << "Android requests to remove a notification (key: " << key
344 << "), but it is already gone.";
345 return;
346 }
347
348 std::unique_ptr<ArcNotificationItem> item = std::move(it->second);
349 items_.erase(it);
350 item->OnClosedFromAndroid();
351
352 for (auto& observer : observers_)
353 observer.OnNotificationRemoved(item->GetNotificationId());
354 }
355
SendNotificationRemovedFromChrome(const std::string & key)356 void ArcNotificationManager::SendNotificationRemovedFromChrome(
357 const std::string& key) {
358 auto it = items_.find(key);
359 if (it == items_.end()) {
360 VLOG(3) << "Chrome requests to remove a notification (key: " << key
361 << "), but it is already gone.";
362 return;
363 }
364
365 // The removed ArcNotificationItem needs to live in this scope, since the
366 // given argument |key| may be a part of the removed item.
367 std::unique_ptr<ArcNotificationItem> item = std::move(it->second);
368 items_.erase(it);
369
370 for (auto& observer : observers_)
371 observer.OnNotificationRemoved(item->GetNotificationId());
372
373 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
374 instance_owner_->holder(), SendNotificationEventToAndroid);
375
376 // On shutdown, the ARC channel may quit earlier than notifications.
377 if (!notifications_instance) {
378 VLOG(2) << "ARC Notification (key: " << key
379 << ") is closed, but the ARC channel has already gone.";
380 return;
381 }
382
383 notifications_instance->SendNotificationEventToAndroid(
384 key, ArcNotificationEvent::CLOSED);
385 }
386
SendNotificationClickedOnChrome(const std::string & key)387 void ArcNotificationManager::SendNotificationClickedOnChrome(
388 const std::string& key) {
389 if (items_.find(key) == items_.end()) {
390 VLOG(3) << "Chrome requests to fire a click event on notification (key: "
391 << key << "), but it is gone.";
392 return;
393 }
394
395 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
396 instance_owner_->holder(), SendNotificationEventToAndroid);
397
398 // On shutdown, the ARC channel may quit earlier than notifications.
399 if (!notifications_instance) {
400 VLOG(2) << "ARC Notification (key: " << key
401 << ") is clicked, but the ARC channel has already gone.";
402 return;
403 }
404
405 notifications_instance->SendNotificationEventToAndroid(
406 key, ArcNotificationEvent::BODY_CLICKED);
407 }
408
SendNotificationActivatedInChrome(const std::string & key,bool activated)409 void ArcNotificationManager::SendNotificationActivatedInChrome(
410 const std::string& key,
411 bool activated) {
412 if (items_.find(key) == items_.end()) {
413 VLOG(3)
414 << "Chrome requests to fire an activation event on notification (key: "
415 << key << "), but it is gone.";
416 return;
417 }
418
419 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
420 instance_owner_->holder(), SendNotificationEventToAndroid);
421
422 // On shutdown, the ARC channel may quit earlier than notifications.
423 if (!notifications_instance) {
424 VLOG(2) << "ARC Notification (key: " << key
425 << ") is (de)activated, but the ARC channel has already gone.";
426 return;
427 }
428
429 notifications_instance->SendNotificationEventToAndroid(
430 key, activated ? ArcNotificationEvent::ACTIVATED
431 : ArcNotificationEvent::DEACTIVATED);
432 }
433
CreateNotificationWindow(const std::string & key)434 void ArcNotificationManager::CreateNotificationWindow(const std::string& key) {
435 if (items_.find(key) == items_.end()) {
436 VLOG(3) << "Chrome requests to create window on notification (key: " << key
437 << "), but it is gone.";
438 return;
439 }
440
441 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
442 instance_owner_->holder(), CreateNotificationWindow);
443 if (!notifications_instance)
444 return;
445
446 notifications_instance->CreateNotificationWindow(key);
447 }
448
CloseNotificationWindow(const std::string & key)449 void ArcNotificationManager::CloseNotificationWindow(const std::string& key) {
450 if (items_.find(key) == items_.end()) {
451 VLOG(3) << "Chrome requests to close window on notification (key: " << key
452 << "), but it is gone.";
453 return;
454 }
455
456 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
457 instance_owner_->holder(), CloseNotificationWindow);
458 if (!notifications_instance)
459 return;
460
461 notifications_instance->CloseNotificationWindow(key);
462 }
463
OpenNotificationSettings(const std::string & key)464 void ArcNotificationManager::OpenNotificationSettings(const std::string& key) {
465 if (items_.find(key) == items_.end()) {
466 DVLOG(3) << "Chrome requests to fire a click event on the notification "
467 << "settings button (key: " << key << "), but it is gone.";
468 return;
469 }
470
471 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
472 instance_owner_->holder(), OpenNotificationSettings);
473
474 // On shutdown, the ARC channel may quit earlier than notifications.
475 if (!notifications_instance)
476 return;
477
478 notifications_instance->OpenNotificationSettings(key);
479 }
480
OpenNotificationSnoozeSettings(const std::string & key)481 void ArcNotificationManager::OpenNotificationSnoozeSettings(
482 const std::string& key) {
483 if (!base::Contains(items_, key)) {
484 DVLOG(3) << "Chrome requests to show a snooze setting gut on the"
485 << "notification (key: " << key << "), but it is gone.";
486 return;
487 }
488
489 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
490 instance_owner_->holder(), OpenNotificationSnoozeSettings);
491
492 // On shutdown, the ARC channel may quit earlier than notifications.
493 if (!notifications_instance)
494 return;
495
496 notifications_instance->OpenNotificationSnoozeSettings(key);
497 }
498
IsOpeningSettingsSupported() const499 bool ArcNotificationManager::IsOpeningSettingsSupported() const {
500 const auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
501 instance_owner_->holder(), OpenNotificationSettings);
502 return notifications_instance != nullptr;
503 }
504
SendNotificationToggleExpansionOnChrome(const std::string & key)505 void ArcNotificationManager::SendNotificationToggleExpansionOnChrome(
506 const std::string& key) {
507 if (items_.find(key) == items_.end()) {
508 VLOG(3) << "Chrome requests to fire a click event on notification (key: "
509 << key << "), but it is gone.";
510 return;
511 }
512
513 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
514 instance_owner_->holder(), SendNotificationEventToAndroid);
515
516 // On shutdown, the ARC channel may quit earlier than notifications.
517 if (!notifications_instance) {
518 VLOG(2) << "ARC Notification (key: " << key
519 << ") is clicked, but the ARC channel has already gone.";
520 return;
521 }
522
523 notifications_instance->SendNotificationEventToAndroid(
524 key, ArcNotificationEvent::TOGGLE_EXPANSION);
525 }
526
ShouldIgnoreNotification(ArcNotificationData * data)527 bool ArcNotificationManager::ShouldIgnoreNotification(
528 ArcNotificationData* data) {
529 if (data->priority == ArcNotificationPriority::NONE)
530 return true;
531
532 // Notifications from Play Store are ignored in Public Session and Kiosk mode.
533 // TODO: Use centralized const for Play Store package.
534 if (data->package_name.has_value() &&
535 *data->package_name == kPlayStorePackageName &&
536 delegate_->IsPublicSessionOrKiosk()) {
537 return true;
538 }
539
540 // Media Notifications may be ignored if we have the native views based media
541 // session notifications enabled.
542 if (data->is_media_notification &&
543 features::IsHideArcMediaNotificationsEnabled()) {
544 return true;
545 }
546
547 return false;
548 }
549
OnDoNotDisturbStatusUpdated(ArcDoNotDisturbStatusPtr status)550 void ArcNotificationManager::OnDoNotDisturbStatusUpdated(
551 ArcDoNotDisturbStatusPtr status) {
552 // Remove the observer to prevent from sending the command to Android since
553 // this request came from Android.
554 message_center_->RemoveObserver(do_not_disturb_manager_.get());
555
556 if (message_center_->IsQuietMode() != status->enabled)
557 message_center_->SetQuietMode(status->enabled);
558
559 // Add back the observer.
560 message_center_->AddObserver(do_not_disturb_manager_.get());
561 }
562
SetDoNotDisturbStatusOnAndroid(bool enabled)563 void ArcNotificationManager::SetDoNotDisturbStatusOnAndroid(bool enabled) {
564 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
565 instance_owner_->holder(), SetDoNotDisturbStatusOnAndroid);
566
567 // On shutdown, the ARC channel may quit earlier than notifications.
568 if (!notifications_instance) {
569 VLOG(2) << "Trying to send the Do Not Disturb status (" << enabled
570 << "), but the ARC channel has already gone.";
571 return;
572 }
573
574 ArcDoNotDisturbStatusPtr status = ArcDoNotDisturbStatus::New();
575 status->enabled = enabled;
576
577 notifications_instance->SetDoNotDisturbStatusOnAndroid(std::move(status));
578 }
579
CancelPress(const std::string & key)580 void ArcNotificationManager::CancelPress(const std::string& key) {
581 auto* notifications_instance =
582 ARC_GET_INSTANCE_FOR_METHOD(instance_owner_->holder(), CancelPress);
583
584 // On shutdown, the ARC channel may quit earlier than notifications.
585 if (!notifications_instance) {
586 VLOG(2) << "Trying to cancel the long press operation, "
587 "but the ARC channel has already gone.";
588 return;
589 }
590
591 notifications_instance->CancelPress(key);
592 }
593
SetNotificationConfiguration()594 void ArcNotificationManager::SetNotificationConfiguration() {
595 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
596 instance_owner_->holder(), SetNotificationConfiguration);
597
598 if (!notifications_instance) {
599 VLOG(2) << "Trying to set notification expansion animations"
600 << ", but the ARC channel has already gone.";
601 return;
602 }
603
604 NotificationConfigurationPtr configuration = NotificationConfiguration::New();
605 configuration->expansion_animation =
606 features::IsNotificationExpansionAnimationEnabled();
607
608 notifications_instance->SetNotificationConfiguration(
609 std::move(configuration));
610 }
611
OnMessageCenterVisibilityChanged(MessageCenterVisibility visibility)612 void ArcNotificationManager::OnMessageCenterVisibilityChanged(
613 MessageCenterVisibility visibility) {
614 auto* notifications_instance = ARC_GET_INSTANCE_FOR_METHOD(
615 instance_owner_->holder(), OnMessageCenterVisibilityChanged);
616
617 if (!notifications_instance) {
618 VLOG(2) << "Trying to report message center visibility (" << visibility
619 << "), but the ARC channel has already gone.";
620 return;
621 }
622
623 notifications_instance->OnMessageCenterVisibilityChanged(visibility);
624 }
625
AddObserver(Observer * observer)626 void ArcNotificationManager::AddObserver(Observer* observer) {
627 observers_.AddObserver(observer);
628 }
629
RemoveObserver(Observer * observer)630 void ArcNotificationManager::RemoveObserver(Observer* observer) {
631 observers_.RemoveObserver(observer);
632 }
633
Init(std::unique_ptr<ArcNotificationManagerDelegate> delegate,const AccountId & main_profile_id,message_center::MessageCenter * message_center)634 void ArcNotificationManager::Init(
635 std::unique_ptr<ArcNotificationManagerDelegate> delegate,
636 const AccountId& main_profile_id,
637 message_center::MessageCenter* message_center) {
638 DCHECK(message_center);
639 delegate_ = std::move(delegate);
640 main_profile_id_ = main_profile_id;
641 message_center_ = message_center;
642 do_not_disturb_manager_ = std::make_unique<DoNotDisturbManager>(this);
643 visibility_manager_ = std::make_unique<VisibilityManager>(this);
644
645 instance_owner_->holder()->SetHost(this);
646 instance_owner_->holder()->AddObserver(this);
647 if (!message_center::MessageViewFactory::HasCustomNotificationViewFactory(
648 kArcNotificationCustomViewType)) {
649 SetCustomNotificationViewFactory();
650 }
651 message_center_->AddObserver(do_not_disturb_manager_.get());
652 message_center_->AddObserver(visibility_manager_.get());
653 }
654
655 } // namespace ash
656