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

Side by Side Diff: chrome/browser/extensions/api/notifications/notifications_api.cc

Issue 2703213004: Migrate extension notifications to the new NotificationDisplayService (Closed)
Patch Set: Finish functionality Created 3 years, 10 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 (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 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/extensions/api/notifications/notifications_api.h" 5 #include "chrome/browser/extensions/api/notifications/notifications_api.h"
6 6
7 #include <stddef.h> 7 #include <stddef.h>
8 8
9 #include <utility> 9 #include <utility>
10 10
11 #include "base/callback.h" 11 #include "base/callback.h"
12 #include "base/feature_list.h" 12 #include "base/feature_list.h"
13 #include "base/guid.h" 13 #include "base/guid.h"
14 #include "base/macros.h" 14 #include "base/macros.h"
15 #include "base/memory/ptr_util.h" 15 #include "base/memory/ptr_util.h"
16 #include "base/metrics/histogram_macros.h" 16 #include "base/metrics/histogram_macros.h"
17 #include "base/rand_util.h" 17 #include "base/rand_util.h"
18 #include "base/strings/string_number_conversions.h" 18 #include "base/strings/string_number_conversions.h"
19 #include "base/strings/utf_string_conversions.h" 19 #include "base/strings/utf_string_conversions.h"
20 #include "base/time/time.h" 20 #include "base/time/time.h"
21 #include "build/build_config.h" 21 #include "build/build_config.h"
22 #include "chrome/browser/browser_process.h" 22 #include "chrome/browser/extensions/api/notifications/extension_notification_dis play_helper.h"
23 #include "chrome/browser/extensions/api/notifications/extension_notification_dis play_helper_factory.h"
23 #include "chrome/browser/notifications/notification.h" 24 #include "chrome/browser/notifications/notification.h"
24 #include "chrome/browser/notifications/notification_ui_manager.h"
25 #include "chrome/browser/notifications/notifier_state_tracker.h" 25 #include "chrome/browser/notifications/notifier_state_tracker.h"
26 #include "chrome/browser/notifications/notifier_state_tracker_factory.h" 26 #include "chrome/browser/notifications/notifier_state_tracker_factory.h"
27 #include "chrome/browser/profiles/profile.h" 27 #include "chrome/browser/profiles/profile.h"
28 #include "chrome/common/extensions/api/notifications/notification_style.h" 28 #include "chrome/common/extensions/api/notifications/notification_style.h"
29 #include "components/keyed_service/content/browser_context_keyed_service_shutdow n_notifier_factory.h" 29 #include "components/keyed_service/content/browser_context_keyed_service_shutdow n_notifier_factory.h"
30 #include "components/keyed_service/core/keyed_service_shutdown_notifier.h" 30 #include "components/keyed_service/core/keyed_service_shutdown_notifier.h"
31 #include "content/public/browser/render_process_host.h" 31 #include "content/public/browser/render_process_host.h"
32 #include "content/public/browser/render_view_host.h" 32 #include "content/public/browser/render_view_host.h"
33 #include "content/public/browser/web_contents.h" 33 #include "content/public/browser/web_contents.h"
34 #include "extensions/browser/app_window/app_window.h" 34 #include "extensions/browser/app_window/app_window.h"
(...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after
205 }; 205 };
206 206
207 class NotificationsApiDelegate : public NotificationDelegate { 207 class NotificationsApiDelegate : public NotificationDelegate {
208 public: 208 public:
209 NotificationsApiDelegate(ChromeAsyncExtensionFunction* api_function, 209 NotificationsApiDelegate(ChromeAsyncExtensionFunction* api_function,
210 Profile* profile, 210 Profile* profile,
211 const std::string& extension_id, 211 const std::string& extension_id,
212 const std::string& id) 212 const std::string& id)
213 : api_function_(api_function), 213 : api_function_(api_function),
214 event_router_(EventRouter::Get(profile)), 214 event_router_(EventRouter::Get(profile)),
215 profile_(profile),
215 extension_id_(extension_id), 216 extension_id_(extension_id),
216 id_(id), 217 id_(id),
217 scoped_id_(CreateScopedIdentifier(extension_id, id)) { 218 scoped_id_(CreateScopedIdentifier(extension_id, id)) {
218 DCHECK(api_function_); 219 DCHECK(api_function_);
219 shutdown_notifier_subscription_ = 220 shutdown_notifier_subscription_ =
220 ShutdownNotifierFactory::GetInstance()->Get(profile)->Subscribe( 221 ShutdownNotifierFactory::GetInstance()->Get(profile)->Subscribe(
221 base::Bind(&NotificationsApiDelegate::Shutdown, 222 base::Bind(&NotificationsApiDelegate::Shutdown,
222 base::Unretained(this))); 223 base::Unretained(this)));
223 } 224 }
224 225
225 void Close(bool by_user) override { 226 void Close(bool by_user) override {
226 EventRouter::UserGestureState gesture = 227 EventRouter::UserGestureState gesture =
227 by_user ? EventRouter::USER_GESTURE_ENABLED 228 by_user ? EventRouter::USER_GESTURE_ENABLED
228 : EventRouter::USER_GESTURE_NOT_ENABLED; 229 : EventRouter::USER_GESTURE_NOT_ENABLED;
229 std::unique_ptr<base::ListValue> args(CreateBaseEventArgs()); 230 std::unique_ptr<base::ListValue> args(CreateBaseEventArgs());
230 args->AppendBoolean(by_user); 231 args->AppendBoolean(by_user);
231 SendEvent(events::NOTIFICATIONS_ON_CLOSED, 232 SendEvent(events::NOTIFICATIONS_ON_CLOSED,
232 notifications::OnClosed::kEventName, gesture, std::move(args)); 233 notifications::OnClosed::kEventName, gesture, std::move(args));
234
235 DCHECK(profile_);
236 ExtensionNotificationDisplayHelperFactory::GetForProfile(profile_)
237 ->EraseDataForNotificationId(scoped_id_);
233 } 238 }
234 239
235 void Click() override { 240 void Click() override {
236 std::unique_ptr<base::ListValue> args(CreateBaseEventArgs()); 241 std::unique_ptr<base::ListValue> args(CreateBaseEventArgs());
237 SendEvent(events::NOTIFICATIONS_ON_CLICKED, 242 SendEvent(events::NOTIFICATIONS_ON_CLICKED,
238 notifications::OnClicked::kEventName, 243 notifications::OnClicked::kEventName,
239 EventRouter::USER_GESTURE_ENABLED, std::move(args)); 244 EventRouter::USER_GESTURE_ENABLED, std::move(args));
240 } 245 }
241 246
242 bool HasClickedListener() override { 247 bool HasClickedListener() override {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
295 if (!event_router_) 300 if (!event_router_)
296 return; 301 return;
297 302
298 std::unique_ptr<Event> event( 303 std::unique_ptr<Event> event(
299 new Event(histogram_value, name, std::move(args))); 304 new Event(histogram_value, name, std::move(args)));
300 event->user_gesture = user_gesture; 305 event->user_gesture = user_gesture;
301 event_router_->DispatchEventToExtension(extension_id_, std::move(event)); 306 event_router_->DispatchEventToExtension(extension_id_, std::move(event));
302 } 307 }
303 308
304 void Shutdown() { 309 void Shutdown() {
310 // Make a copy of |profile_| so that the member can be nulled out.
311 Profile* profile = profile_;
312
313 shutdown_notifier_subscription_.reset();
305 event_router_ = nullptr; 314 event_router_ = nullptr;
306 shutdown_notifier_subscription_.reset(); 315 profile_ = nullptr;
316
317 // The following call will result in deleting |this|. Do not access members
318 // after this, as you will be accessing invalid memory.
319 ExtensionNotificationDisplayHelperFactory::GetForProfile(profile)->Close(
Miguel Garcia 2017/02/21 10:56:43 Wouldn't it be safer to post it as a task then?
Peter Beverloo 2017/02/21 17:23:50 The issue there is that Shutdown() will be called
320 scoped_id_);
307 } 321 }
308 322
309 std::unique_ptr<base::ListValue> CreateBaseEventArgs() { 323 std::unique_ptr<base::ListValue> CreateBaseEventArgs() {
310 std::unique_ptr<base::ListValue> args(new base::ListValue()); 324 std::unique_ptr<base::ListValue> args(new base::ListValue());
311 args->AppendString(id_); 325 args->AppendString(id_);
312 return args; 326 return args;
313 } 327 }
314 328
315 scoped_refptr<ChromeAsyncExtensionFunction> api_function_; 329 scoped_refptr<ChromeAsyncExtensionFunction> api_function_;
316 330
317 // Since this class is refcounted it may outlive the profile. We listen for 331 // Since this class is refcounted it may outlive the profile. We listen for
318 // profile-keyed service shutdown events and reset to nullptr at that time, 332 // profile-keyed service shutdown events and reset to nullptr at that time,
319 // so make sure to check for a valid pointer before use. 333 // so make sure to check for a valid pointer before use.
320 EventRouter* event_router_; 334 EventRouter* event_router_;
335 Profile* profile_;
321 336
322 const std::string extension_id_; 337 const std::string extension_id_;
323 const std::string id_; 338 const std::string id_;
324 const std::string scoped_id_; 339 const std::string scoped_id_;
325 340
326 std::unique_ptr<KeyedServiceShutdownNotifier::Subscription> 341 std::unique_ptr<KeyedServiceShutdownNotifier::Subscription>
327 shutdown_notifier_subscription_; 342 shutdown_notifier_subscription_;
328 343
329 DISALLOW_COPY_AND_ASSIGN(NotificationsApiDelegate); 344 DISALLOW_COPY_AND_ASSIGN(NotificationsApiDelegate);
330 }; 345 };
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after
489 type, title, message, icon, 504 type, title, message, icon,
490 message_center::NotifierId(message_center::NotifierId::APPLICATION, 505 message_center::NotifierId(message_center::NotifierId::APPLICATION,
491 extension_->id()), 506 extension_->id()),
492 base::UTF8ToUTF16(extension_->name()), extension_->url(), 507 base::UTF8ToUTF16(extension_->name()), extension_->url(),
493 api_delegate->id(), optional_fields, api_delegate); 508 api_delegate->id(), optional_fields, api_delegate);
494 509
495 // Apply the "requireInteraction" flag. The value defaults to false. 510 // Apply the "requireInteraction" flag. The value defaults to false.
496 notification.set_never_timeout(options->require_interaction && 511 notification.set_never_timeout(options->require_interaction &&
497 *options->require_interaction); 512 *options->require_interaction);
498 513
499 g_browser_process->notification_ui_manager()->Add(notification, GetProfile()); 514 GetDisplayHelper()->Display(notification);
500 return true; 515 return true;
501 } 516 }
502 517
503 bool NotificationsApiFunction::UpdateNotification( 518 bool NotificationsApiFunction::UpdateNotification(
504 const std::string& id, 519 const std::string& id,
505 api::notifications::NotificationOptions* options, 520 api::notifications::NotificationOptions* options,
506 Notification* notification) { 521 Notification* notification) {
507 #if !defined(OS_CHROMEOS) 522 #if !defined(OS_CHROMEOS)
508 if (options->priority && 523 if (options->priority &&
509 *options->priority < message_center::DEFAULT_PRIORITY) { 524 *options->priority < message_center::DEFAULT_PRIORITY) {
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
623 base::UTF8ToUTF16(api_item.title), 638 base::UTF8ToUTF16(api_item.title),
624 base::UTF8ToUTF16(api_item.message))); 639 base::UTF8ToUTF16(api_item.message)));
625 } 640 }
626 notification->set_items(items); 641 notification->set_items(items);
627 } 642 }
628 643
629 // Then override if it's already set. 644 // Then override if it's already set.
630 if (options->is_clickable.get()) 645 if (options->is_clickable.get())
631 notification->set_clickable(*options->is_clickable); 646 notification->set_clickable(*options->is_clickable);
632 647
633 g_browser_process->notification_ui_manager()->Update(*notification, 648 // It's safe to follow the regular path for adding a new notification as it's
634 GetProfile()); 649 // already been verified that there is a notification that can be updated.
650 GetDisplayHelper()->Display(*notification);
651
635 return true; 652 return true;
636 } 653 }
637 654
638 bool NotificationsApiFunction::AreExtensionNotificationsAllowed() const { 655 bool NotificationsApiFunction::AreExtensionNotificationsAllowed() const {
639 NotifierStateTracker* notifier_state_tracker = 656 NotifierStateTracker* notifier_state_tracker =
640 NotifierStateTrackerFactory::GetForProfile(GetProfile()); 657 NotifierStateTrackerFactory::GetForProfile(GetProfile());
641 658
642 return notifier_state_tracker->IsNotifierEnabled( 659 return notifier_state_tracker->IsNotifierEnabled(
643 message_center::NotifierId(message_center::NotifierId::APPLICATION, 660 message_center::NotifierId(message_center::NotifierId::APPLICATION,
644 extension_->id())); 661 extension_->id()));
645 } 662 }
646 663
647 bool NotificationsApiFunction::IsNotificationsApiEnabled() const { 664 bool NotificationsApiFunction::IsNotificationsApiEnabled() const {
648 return CanRunWhileDisabled() || AreExtensionNotificationsAllowed(); 665 return CanRunWhileDisabled() || AreExtensionNotificationsAllowed();
649 } 666 }
650 667
651 bool NotificationsApiFunction::CanRunWhileDisabled() const { 668 bool NotificationsApiFunction::CanRunWhileDisabled() const {
652 return false; 669 return false;
653 } 670 }
654 671
672 ExtensionNotificationDisplayHelper* NotificationsApiFunction::GetDisplayHelper()
673 const {
674 return ExtensionNotificationDisplayHelperFactory::GetForProfile(GetProfile());
675 }
676
655 bool NotificationsApiFunction::RunAsync() { 677 bool NotificationsApiFunction::RunAsync() {
656 if (IsNotificationsApiAvailable() && IsNotificationsApiEnabled()) { 678 if (IsNotificationsApiAvailable() && IsNotificationsApiEnabled()) {
657 return RunNotificationsApi(); 679 return RunNotificationsApi();
658 } else { 680 } else {
659 SendResponse(false); 681 SendResponse(false);
660 return true; 682 return true;
661 } 683 }
662 } 684 }
663 685
664 message_center::NotificationType 686 message_center::NotificationType
(...skipping 56 matching lines...) Expand 10 before | Expand all | Expand 10 after
721 NotificationsUpdateFunction::~NotificationsUpdateFunction() { 743 NotificationsUpdateFunction::~NotificationsUpdateFunction() {
722 } 744 }
723 745
724 bool NotificationsUpdateFunction::RunNotificationsApi() { 746 bool NotificationsUpdateFunction::RunNotificationsApi() {
725 params_ = api::notifications::Update::Params::Create(*args_); 747 params_ = api::notifications::Update::Params::Create(*args_);
726 EXTENSION_FUNCTION_VALIDATE(params_.get()); 748 EXTENSION_FUNCTION_VALIDATE(params_.get());
727 749
728 // We are in update. If the ID doesn't exist, succeed but call the callback 750 // We are in update. If the ID doesn't exist, succeed but call the callback
729 // with "false". 751 // with "false".
730 const Notification* matched_notification = 752 const Notification* matched_notification =
731 g_browser_process->notification_ui_manager()->FindById( 753 GetDisplayHelper()->GetByNotificationId(
732 CreateScopedIdentifier(extension_->id(), params_->notification_id), 754 CreateScopedIdentifier(extension_->id(), params_->notification_id));
733 NotificationUIManager::GetProfileID(GetProfile())); 755
734 if (!matched_notification) { 756 if (!matched_notification) {
735 SetResult(base::MakeUnique<base::FundamentalValue>(false)); 757 SetResult(base::MakeUnique<base::FundamentalValue>(false));
736 SendResponse(true); 758 SendResponse(true);
737 return true; 759 return true;
738 } 760 }
739 761
740 // Copy the existing notification to get a writable version of it. 762 // Copy the existing notification to get a writable version of it.
741 Notification notification = *matched_notification; 763 Notification notification = *matched_notification;
742 764
743 // If we have trouble updating the notification (could be improper use of API 765 // If we have trouble updating the notification (could be improper use of API
(...skipping 16 matching lines...) Expand all
760 NotificationsClearFunction::NotificationsClearFunction() { 782 NotificationsClearFunction::NotificationsClearFunction() {
761 } 783 }
762 784
763 NotificationsClearFunction::~NotificationsClearFunction() { 785 NotificationsClearFunction::~NotificationsClearFunction() {
764 } 786 }
765 787
766 bool NotificationsClearFunction::RunNotificationsApi() { 788 bool NotificationsClearFunction::RunNotificationsApi() {
767 params_ = api::notifications::Clear::Params::Create(*args_); 789 params_ = api::notifications::Clear::Params::Create(*args_);
768 EXTENSION_FUNCTION_VALIDATE(params_.get()); 790 EXTENSION_FUNCTION_VALIDATE(params_.get());
769 791
770 bool cancel_result = g_browser_process->notification_ui_manager()->CancelById( 792 bool cancel_result = GetDisplayHelper()->Close(
771 CreateScopedIdentifier(extension_->id(), params_->notification_id), 793 CreateScopedIdentifier(extension_->id(), params_->notification_id));
772 NotificationUIManager::GetProfileID(GetProfile()));
773 794
774 SetResult(base::MakeUnique<base::FundamentalValue>(cancel_result)); 795 SetResult(base::MakeUnique<base::FundamentalValue>(cancel_result));
775 SendResponse(true); 796 SendResponse(true);
776 797
777 return true; 798 return true;
778 } 799 }
779 800
780 NotificationsGetAllFunction::NotificationsGetAllFunction() {} 801 NotificationsGetAllFunction::NotificationsGetAllFunction() {}
781 802
782 NotificationsGetAllFunction::~NotificationsGetAllFunction() {} 803 NotificationsGetAllFunction::~NotificationsGetAllFunction() {}
783 804
784 bool NotificationsGetAllFunction::RunNotificationsApi() { 805 bool NotificationsGetAllFunction::RunNotificationsApi() {
785 NotificationUIManager* notification_ui_manager =
786 g_browser_process->notification_ui_manager();
787 std::set<std::string> notification_ids = 806 std::set<std::string> notification_ids =
788 notification_ui_manager->GetAllIdsByProfileAndSourceOrigin( 807 GetDisplayHelper()->GetNotificationIdsForExtension(extension_->url());
789 NotificationUIManager::GetProfileID(GetProfile()), extension_->url());
790 808
791 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue()); 809 std::unique_ptr<base::DictionaryValue> result(new base::DictionaryValue());
792 810
793 for (std::set<std::string>::iterator iter = notification_ids.begin(); 811 for (std::set<std::string>::iterator iter = notification_ids.begin();
794 iter != notification_ids.end(); iter++) { 812 iter != notification_ids.end(); iter++) {
795 result->SetBooleanWithoutPathExpansion( 813 result->SetBooleanWithoutPathExpansion(
796 StripScopeFromIdentifier(extension_->id(), *iter), true); 814 StripScopeFromIdentifier(extension_->id(), *iter), true);
797 } 815 }
798 816
799 SetResult(std::move(result)); 817 SetResult(std::move(result));
(...skipping 19 matching lines...) Expand all
819 : api::notifications::PERMISSION_LEVEL_DENIED; 837 : api::notifications::PERMISSION_LEVEL_DENIED;
820 838
821 SetResult(base::MakeUnique<base::StringValue>( 839 SetResult(base::MakeUnique<base::StringValue>(
822 api::notifications::ToString(result))); 840 api::notifications::ToString(result)));
823 SendResponse(true); 841 SendResponse(true);
824 842
825 return true; 843 return true;
826 } 844 }
827 845
828 } // namespace extensions 846 } // namespace extensions
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698