NotificationCenter.cpp [plain text]
#include "config.h"
#if ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)
#include "NotificationCenter.h"
#include "ExceptionCode.h"
#include "Notification.h"
#include "ScriptExecutionContext.h"
#include "SecurityOrigin.h"
#include "VoidCallback.h"
namespace WebCore {
Ref<NotificationCenter> NotificationCenter::create(ScriptExecutionContext& context, NotificationClient* client)
{
auto notificationCenter = adoptRef(*new NotificationCenter(context, client));
notificationCenter->suspendIfNeeded();
return notificationCenter;
}
NotificationCenter::NotificationCenter(ScriptExecutionContext& context, NotificationClient* client)
: ActiveDOMObject(&context)
, m_client(client)
, m_timer([this]() { timerFired(); })
{
}
#if ENABLE(LEGACY_NOTIFICATIONS)
ExceptionOr<Ref<Notification>> NotificationCenter::createNotification(const String& iconURI, const String& title, const String& body)
{
if (!m_client || !scriptExecutionContext())
return Exception { INVALID_STATE_ERR };
return Notification::create(title, body, iconURI, *scriptExecutionContext(), *this);
}
int NotificationCenter::checkPermission()
{
if (!m_client || !scriptExecutionContext())
return NotificationClient::PermissionDenied;
switch (scriptExecutionContext()->securityOrigin()->canShowNotifications()) {
case SecurityOrigin::AlwaysAllow:
return NotificationClient::PermissionAllowed;
case SecurityOrigin::AlwaysDeny:
return NotificationClient::PermissionDenied;
case SecurityOrigin::Ask:
return m_client->checkPermission(scriptExecutionContext());
}
ASSERT_NOT_REACHED();
return m_client->checkPermission(scriptExecutionContext());
}
void NotificationCenter::requestPermission(RefPtr<VoidCallback>&& callback)
{
if (!m_client || !scriptExecutionContext())
return;
switch (scriptExecutionContext()->securityOrigin()->canShowNotifications()) {
case SecurityOrigin::AlwaysAllow:
case SecurityOrigin::AlwaysDeny:
if (m_callbacks.isEmpty()) {
ref(); m_timer.startOneShot(0);
}
m_callbacks.append([callback]() {
if (callback)
callback->handleEvent();
});
return;
case SecurityOrigin::Ask:
m_client->requestPermission(scriptExecutionContext(), WTFMove(callback));
return;
}
ASSERT_NOT_REACHED();
m_client->requestPermission(scriptExecutionContext(), WTFMove(callback));
}
#endif
void NotificationCenter::stop()
{
if (!m_client)
return;
auto& client = *std::exchange(m_client, nullptr);
Ref<NotificationCenter> protectedThis(*this);
if (!m_callbacks.isEmpty())
deref();
m_timer.stop();
m_callbacks.clear();
client.cancelRequestsForPermission(scriptExecutionContext());
client.clearNotifications(scriptExecutionContext());
}
const char* NotificationCenter::activeDOMObjectName() const
{
return "NotificationCenter";
}
bool NotificationCenter::canSuspendForDocumentSuspension() const
{
return m_callbacks.isEmpty() && (!m_client || !m_client->hasPendingPermissionRequests(scriptExecutionContext()));
}
void NotificationCenter::timerFired()
{
ASSERT(m_client);
auto callbacks = WTFMove(m_callbacks);
for (auto& callback : callbacks)
callback();
deref(); }
}
#endif // ENABLE(NOTIFICATIONS) || ENABLE(LEGACY_NOTIFICATIONS)