Notification.h (6818B)
1 /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ 2 /* vim: set ts=8 sts=2 et sw=2 tw=80: */ 3 /* This Source Code Form is subject to the terms of the Mozilla Public 4 * License, v. 2.0. If a copy of the MPL was not distributed with this 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 6 7 #ifndef mozilla_dom_notification_h__ 8 #define mozilla_dom_notification_h__ 9 10 #include "mozilla/DOMEventTargetHelper.h" 11 #include "mozilla/dom/DOMTypes.h" 12 #include "mozilla/dom/NotificationBinding.h" 13 #include "mozilla/dom/notification/NotificationChild.h" 14 #include "nsCycleCollectionParticipant.h" 15 #include "nsISupports.h" 16 #include "nsString.h" 17 18 class nsIPrincipal; 19 class nsIVariant; 20 21 namespace mozilla::dom { 22 23 class NotificationRef; 24 class WorkerNotificationObserver; 25 class Promise; 26 class StrongWorkerRef; 27 28 namespace notification { 29 enum class PermissionCheckPurpose : uint8_t; 30 } 31 32 /* 33 * A Notification gets a corresponding IPC actor after successful construction. 34 * The notification object and the actor do not own each other and their 35 * lifetimes are controlled semi-independently. 36 * 37 * The Notification object can be cycle collected when either: 38 * - no one is listening for the events, or 39 * - the backend notification is closed. 40 * 41 * The actor goes away when either: 42 * - the backend notification is closed, or 43 * - the tab is closed or bfcached. 44 * 45 * (It cannot just go away on cycle collection because nsIAlertsService wants to 46 * know whether the triggered page is still open to decide whether to open a new 47 * tab or focus on the existing tab.) 48 */ 49 class Notification : public DOMEventTargetHelper, public SupportsWeakPtr { 50 friend class CloseNotificationRunnable; 51 friend class NotificationTask; 52 friend class NotificationPermissionRequest; 53 friend class MainThreadNotificationObserver; 54 friend class NotificationStorageCallback; 55 friend class ServiceWorkerNotificationObserver; 56 friend class WorkerGetRunnable; 57 friend class WorkerNotificationObserver; 58 59 public: 60 IMPL_EVENT_HANDLER(click) 61 IMPL_EVENT_HANDLER(show) 62 IMPL_EVENT_HANDLER(error) 63 IMPL_EVENT_HANDLER(close) 64 65 NS_DECL_ISUPPORTS_INHERITED 66 NS_DECL_CYCLE_COLLECTION_SCRIPT_HOLDER_CLASS_INHERITED(Notification, 67 DOMEventTargetHelper) 68 69 static bool PrefEnabled(JSContext* aCx, JSObject* aObj); 70 71 static already_AddRefed<Notification> Constructor( 72 const GlobalObject& aGlobal, const nsAString& aTitle, 73 const NotificationOptions& aOption, ErrorResult& aRv); 74 75 /** 76 * Used when retrieving notification objects from the parent process. 77 */ 78 static Result<already_AddRefed<Notification>, nsresult> ConstructFromIPC( 79 nsIGlobalObject* aGlobal, const IPCNotification& aIPCNotification, 80 const nsAString& aServiceWorkerRegistrationScope); 81 82 void GetID(nsAString& aRetval) { aRetval = mIPCNotification.id(); } 83 84 void GetTitle(nsAString& aRetval) { 85 aRetval = mIPCNotification.options().title(); 86 } 87 88 NotificationDirection Dir() { return mIPCNotification.options().dir(); } 89 90 void GetLang(nsAString& aRetval) { 91 aRetval = mIPCNotification.options().lang(); 92 } 93 94 void GetBody(nsAString& aRetval) { 95 aRetval = mIPCNotification.options().body(); 96 } 97 98 void GetTag(nsAString& aRetval) { 99 aRetval = mIPCNotification.options().tag(); 100 } 101 102 void GetIcon(nsACString& aRetval) { 103 nsIURI* iconUri = mIPCNotification.options().icon(); 104 if (!iconUri) { 105 aRetval.Truncate(); 106 return; 107 } 108 iconUri->GetSpec(aRetval); 109 } 110 111 void MaybeNotifyClose(); 112 113 static bool RequestPermissionEnabledForScope(JSContext* aCx, 114 JSObject* /* unused */); 115 116 static already_AddRefed<Promise> RequestPermission( 117 const GlobalObject& aGlobal, 118 const Optional<OwningNonNull<NotificationPermissionCallback>>& aCallback, 119 ErrorResult& aRv); 120 121 static NotificationPermission GetPermission(const GlobalObject& aGlobal, 122 ErrorResult& aRv); 123 124 static uint32_t MaxActions(const GlobalObject& aGlobal); 125 126 // Notification implementation of 127 // ServiceWorkerRegistration.showNotification. 128 // 129 // 130 // Note that aCx may not be in the compartment of aGlobal, but aOptions will 131 // have its JS things in the compartment of aCx. 132 static already_AddRefed<Promise> ShowPersistentNotification( 133 JSContext* aCx, nsIGlobalObject* aGlobal, const nsAString& aScope, 134 const nsAString& aTitle, const NotificationOptions& aOptions, 135 const ServiceWorkerRegistrationDescriptor& aDescriptor, ErrorResult& aRv); 136 137 void Close(); 138 139 nsIGlobalObject* GetParentObject() const { return GetOwnerGlobal(); } 140 141 JSObject* WrapObject(JSContext*, JS::Handle<JSObject*> aGivenProto) override; 142 143 bool RequireInteraction() const; 144 145 bool Silent() const; 146 147 void GetVibrate(nsTArray<uint32_t>& aRetval) const; 148 149 void GetData(JSContext* aCx, JS::MutableHandle<JS::Value> aRetval); 150 151 void GetActions(nsTArray<NotificationAction>& aRetVal); 152 153 static NotificationPermission GetPermission( 154 nsIGlobalObject* aGlobal, notification::PermissionCheckPurpose aPurpose, 155 ErrorResult& aRv); 156 157 bool DispatchClickEvent(); 158 159 nsresult DispatchToMainThread(already_AddRefed<nsIRunnable>&& aRunnable); 160 161 protected: 162 Notification(nsIGlobalObject* aGlobal, 163 const IPCNotification& aIPCNotification, 164 const nsAString& aScope); 165 166 void Deactivate(); 167 168 static NotificationPermission GetPermissionInternal( 169 nsPIDOMWindowInner* aWindow, 170 notification::PermissionCheckPurpose aPurpose, ErrorResult& rv); 171 172 WeakPtr<notification::NotificationChild> mActor; 173 174 const IPCNotification mIPCNotification; 175 176 // It's null until GetData is first called 177 JS::Heap<JS::Value> mData; 178 179 nsString mScope; 180 181 bool mIsClosed = false; 182 183 private: 184 virtual ~Notification(); 185 186 // Creates a Notification and shows it. Returns a reference to the 187 // Notification if result is NS_OK. The lifetime of this Notification is tied 188 // to an underlying NotificationRef. Do not hold a non-stack raw pointer to 189 // it. Be careful about thread safety if acquiring a strong reference. 190 // 191 // Note that aCx may not be in the compartment of aGlobal, but aOptions will 192 // have its JS things in the compartment of aCx. 193 static already_AddRefed<Notification> ValidateAndCreate( 194 JSContext* aCx, nsIGlobalObject* aGlobal, const nsAString& aTitle, 195 const NotificationOptions& aOptions, const nsAString& aScope, 196 ErrorResult& aRv); 197 198 bool CreateActor(); 199 bool SendShow(Promise* aPromise); 200 201 static already_AddRefed<nsIURI> ResolveIconURL(nsIGlobalObject* aGlobal, 202 const nsACString& aIconUrl); 203 }; 204 205 } // namespace mozilla::dom 206 207 #endif // mozilla_dom_notification_h__