[WTF] Add makeUnique<T>, which ensures T is fast-allocated, makeUnique / makeUniqueWi...
[WebKit-https.git] / Source / WebCore / Modules / notifications / Notification.cpp
index bb8719d..0ebaff8 100644 (file)
 
 #include "config.h"
 
-#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
+#if ENABLE(NOTIFICATIONS)
 
 #include "Notification.h"
 
-#include "DOMWindow.h"
-#include "DOMWindowNotifications.h"
 #include "Document.h"
 #include "Event.h"
 #include "EventNames.h"
-#include "ExceptionCode.h"
-#include "NotificationCenter.h"
+#include "NotificationClient.h"
 #include "NotificationController.h"
 #include "NotificationPermissionCallback.h"
-#include "VoidCallback.h"
 #include "WindowFocusAllowedIndicator.h"
+#include <wtf/IsoMallocInlines.h>
 
 namespace WebCore {
 
-#if ENABLE(LEGACY_NOTIFICATIONS)
+WTF_MAKE_ISO_ALLOCATED_IMPL(Notification);
 
-Notification::Notification(const String& title, const String& body, URL&& iconURL, ScriptExecutionContext& context, NotificationCenter& notificationCenter)
-    : ActiveDOMObject(&context)
-    , m_icon(WTFMove(iconURL))
-    , m_title(title)
-    , m_body(body)
-    , m_notificationCenter(&notificationCenter)
+Ref<Notification> Notification::create(Document& context, const String& title, const Options& options)
 {
+    auto notification = adoptRef(*new Notification(context, title, options));
+    notification->suspendIfNeeded();
+    return notification;
 }
 
-#endif
-
-#if ENABLE(NOTIFICATIONS)
-
-Notification::Notification(Document& document, const String& title)
-    : ActiveDOMObject(&document)
+Notification::Notification(Document& document, const String& title, const Options& options)
+    : ActiveDOMObject(document)
     , m_title(title)
+    , m_direction(options.dir)
+    , m_lang(options.lang)
+    , m_body(options.body)
+    , m_tag(options.tag)
     , m_state(Idle)
-    , m_notificationCenter(DOMWindowNotifications::webkitNotifications(*document.domWindow()))
-    , m_taskTimer(std::make_unique<Timer>([this] () { show(); }))
+    , m_taskTimer(makeUnique<Timer>([this] () { show(); }))
 {
-    // FIXME: Seems that m_notificationCenter can be null so should not be changed from RefPtr to Ref.
-    // But the rest of the code in this class isn't trying to handle that case.
-    ASSERT(m_notificationCenter->client());
+    if (!options.icon.isEmpty()) {
+        auto iconURL = document.completeURL(options.icon);
+        if (iconURL.isValid())
+            m_icon = iconURL;
+    }
+
     m_taskTimer->startOneShot(0_s);
 }
 
-#endif
+Notification::~Notification()  = default;
 
-Notification::~Notification() 
+void Notification::show()
 {
-}
-
-#if ENABLE(LEGACY_NOTIFICATIONS)
-
-ExceptionOr<Ref<Notification>> Notification::create(const String& title, const String& body, const String& iconURL, ScriptExecutionContext& context, NotificationCenter& provider)
-{ 
-    if (provider.checkPermission() != NotificationClient::PermissionAllowed)
-        return Exception { SECURITY_ERR };
-
-    URL completedIconURL = iconURL.isEmpty() ? URL() : context.completeURL(iconURL);
-    if (!completedIconURL.isEmpty() && !completedIconURL.isValid())
-        return Exception { SYNTAX_ERR };
-
-    auto notification = adoptRef(*new Notification(title, body, WTFMove(completedIconURL), context, provider));
-    notification.get().suspendIfNeeded();
-    return WTFMove(notification);
-}
-
-#endif
+    // prevent double-showing
+    if (m_state != Idle)
+        return;
 
-#if ENABLE(NOTIFICATIONS)
+    auto* page = downcast<Document>(*scriptExecutionContext()).page();
+    if (!page)
+        return;
 
-static String directionString(Notification::Direction direction)
-{
-    // FIXME: Storing this as a string is not the right way to do it.
-    // FIXME: Seems highly unlikely that this does the right thing for Auto.
-    switch (direction) {
-    case Notification::Direction::Auto:
-        return ASCIILiteral("auto");
-    case Notification::Direction::Ltr:
-        return ASCIILiteral("ltr");
-    case Notification::Direction::Rtl:
-        return ASCIILiteral("rtl");
-    }
-    ASSERT_NOT_REACHED();
-    return { };
-}
+    auto& client = NotificationController::from(page)->client();
 
-Ref<Notification> Notification::create(Document& context, const String& title, const Options& options)
-{
-    auto notification = adoptRef(*new Notification(context, title));
-    notification.get().m_body = options.body;
-    notification.get().m_tag = options.tag;
-    notification.get().m_lang = options.lang;
-    notification.get().m_direction = directionString(options.dir);
-    if (!options.icon.isEmpty()) {
-        auto iconURL = context.completeURL(options.icon);
-        if (iconURL.isValid())
-            notification.get().m_icon = iconURL;
+    if (client.checkPermission(scriptExecutionContext()) != Permission::Granted) {
+        dispatchErrorEvent();
+        return;
     }
-    notification.get().suspendIfNeeded();
-    return notification;
-}
-
-#endif
-
-void Notification::show() 
-{
-    // prevent double-showing
-    if (m_state == Idle && m_notificationCenter->client()) {
-#if ENABLE(NOTIFICATIONS)
-        auto* page = downcast<Document>(*scriptExecutionContext()).page();
-        if (!page)
-            return;
-        if (NotificationController::from(page)->client().checkPermission(scriptExecutionContext()) != NotificationClient::PermissionAllowed) {
-            dispatchErrorEvent();
-            return;
-        }
-#endif
-        if (m_notificationCenter->client()->show(this)) {
-            m_state = Showing;
-            setPendingActivity(this);
-        }
+    if (client.show(this)) {
+        m_state = Showing;
+        setPendingActivity(*this);
     }
 }
 
@@ -162,22 +103,17 @@ void Notification::close()
     switch (m_state) {
     case Idle:
         break;
-    case Showing:
-        if (m_notificationCenter->client())
-            m_notificationCenter->client()->cancel(this);
+    case Showing: {
+        auto* page = downcast<Document>(*scriptExecutionContext()).page();
+        if (page)
+            NotificationController::from(page)->client().cancel(this);
         break;
+    }
     case Closed:
         break;
     }
 }
 
-void Notification::contextDestroyed()
-{
-    ActiveDOMObject::contextDestroyed();
-    if (m_notificationCenter->client())
-        m_notificationCenter->client()->notificationObjectDestroyed(this);
-}
-
 const char* Notification::activeDOMObjectName() const
 {
     return "Notification";
@@ -189,55 +125,48 @@ bool Notification::canSuspendForDocumentSuspension() const
     return m_state == Idle || m_state == Closed;
 }
 
+void Notification::stop()
+{
+    ActiveDOMObject::stop();
+
+    auto* page = downcast<Document>(*scriptExecutionContext()).page();
+    if (page)
+        NotificationController::from(page)->client().notificationObjectDestroyed(this);
+}
+
 void Notification::finalize()
 {
     if (m_state == Closed)
         return;
     m_state = Closed;
-    unsetPendingActivity(this);
+    unsetPendingActivity(*this);
 }
 
 void Notification::dispatchShowEvent()
 {
-    dispatchEvent(Event::create(eventNames().showEvent, false, false));
+    dispatchEvent(Event::create(eventNames().showEvent, Event::CanBubble::No, Event::IsCancelable::No));
 }
 
 void Notification::dispatchClickEvent()
 {
     WindowFocusAllowedIndicator windowFocusAllowed;
-    dispatchEvent(Event::create(eventNames().clickEvent, false, false));
+    dispatchEvent(Event::create(eventNames().clickEvent, Event::CanBubble::No, Event::IsCancelable::No));
 }
 
 void Notification::dispatchCloseEvent()
 {
-    dispatchEvent(Event::create(eventNames().closeEvent, false, false));
+    dispatchEvent(Event::create(eventNames().closeEvent, Event::CanBubble::No, Event::IsCancelable::No));
     finalize();
 }
 
 void Notification::dispatchErrorEvent()
 {
-    dispatchEvent(Event::create(eventNames().errorEvent, false, false));
+    dispatchEvent(Event::create(eventNames().errorEvent, Event::CanBubble::No, Event::IsCancelable::No));
 }
 
-#if ENABLE(NOTIFICATIONS)
-
-String Notification::permission(Document& document)
-{
-    return permissionString(NotificationController::from(document.page())->client().checkPermission(&document));
-}
-
-String Notification::permissionString(NotificationClient::Permission permission)
+auto Notification::permission(Document& document) -> Permission
 {
-    switch (permission) {
-    case NotificationClient::PermissionAllowed:
-        return ASCIILiteral("granted");
-    case NotificationClient::PermissionDenied:
-        return ASCIILiteral("denied");
-    case NotificationClient::PermissionNotAllowed:
-        return ASCIILiteral("default");
-    }
-    ASSERT_NOT_REACHED();
-    return { };
+    return NotificationController::from(document.page())->client().checkPermission(&document);
 }
 
 void Notification::requestPermission(Document& document, RefPtr<NotificationPermissionCallback>&& callback)
@@ -245,8 +174,6 @@ void Notification::requestPermission(Document& document, RefPtr<NotificationPerm
     NotificationController::from(document.page())->client().requestPermission(&document, WTFMove(callback));
 }
 
-#endif
-
 } // namespace WebCore
 
-#endif // ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
+#endif // ENABLE(NOTIFICATIONS)