From 1bf1084f2b10c3b47fd1a588d85d21ed0eb41d0c Mon Sep 17 00:00:00 2001 From: Lorry Tar Creator Date: Tue, 27 Jun 2017 06:07:23 +0000 Subject: webkitgtk-2.16.5 --- .../Modules/notifications/NotificationCenter.cpp | 101 ++++++++++++--------- 1 file changed, 59 insertions(+), 42 deletions(-) (limited to 'Source/WebCore/Modules/notifications/NotificationCenter.cpp') diff --git a/Source/WebCore/Modules/notifications/NotificationCenter.cpp b/Source/WebCore/Modules/notifications/NotificationCenter.cpp index 13f77de4a..a9298f752 100644 --- a/Source/WebCore/Modules/notifications/NotificationCenter.cpp +++ b/Source/WebCore/Modules/notifications/NotificationCenter.cpp @@ -1,6 +1,6 @@ /* * Copyright (C) 2009 Google Inc. All rights reserved. - * Copyright (C) 2012 Apple Inc. All rights reserved. + * Copyright (C) 2012, 2015 Apple Inc. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions are @@ -35,30 +35,40 @@ #include "NotificationCenter.h" -#include "Document.h" -#include "NotificationClient.h" +#include "ExceptionCode.h" +#include "Notification.h" +#include "ScriptExecutionContext.h" #include "SecurityOrigin.h" -#include "WorkerGlobalScope.h" +#include "VoidCallback.h" namespace WebCore { -PassRefPtr NotificationCenter::create(ScriptExecutionContext* context, NotificationClient* client) +Ref NotificationCenter::create(ScriptExecutionContext& context, NotificationClient* client) { - RefPtr notificationCenter(adoptRef(new NotificationCenter(context, client))); + auto notificationCenter = adoptRef(*new NotificationCenter(context, client)); notificationCenter->suspendIfNeeded(); - return notificationCenter.release(); + return notificationCenter; } -NotificationCenter::NotificationCenter(ScriptExecutionContext* context, NotificationClient* client) - : ActiveDOMObject(context) +NotificationCenter::NotificationCenter(ScriptExecutionContext& context, NotificationClient* client) + : ActiveDOMObject(&context) , m_client(client) + , m_timer([this]() { timerFired(); }) { } #if ENABLE(LEGACY_NOTIFICATIONS) + +ExceptionOr> 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 (!client() || !scriptExecutionContext()) + if (!m_client || !scriptExecutionContext()) return NotificationClient::PermissionDenied; switch (scriptExecutionContext()->securityOrigin()->canShowNotifications()) { @@ -73,67 +83,74 @@ int NotificationCenter::checkPermission() ASSERT_NOT_REACHED(); return m_client->checkPermission(scriptExecutionContext()); } -#endif -#if ENABLE(LEGACY_NOTIFICATIONS) -void NotificationCenter::requestPermission(PassRefPtr callback) +void NotificationCenter::requestPermission(RefPtr&& callback) { - if (!client() || !scriptExecutionContext()) + if (!m_client || !scriptExecutionContext()) return; switch (scriptExecutionContext()->securityOrigin()->canShowNotifications()) { case SecurityOrigin::AlwaysAllow: - case SecurityOrigin::AlwaysDeny: { - m_callbacks.add(NotificationRequestCallback::createAndStartTimer(this, callback)); + case SecurityOrigin::AlwaysDeny: + if (m_callbacks.isEmpty()) { + ref(); // Balanced by the derefs in NotificationCenter::stop and NotificationCenter::timerFired. + m_timer.startOneShot(0); + } + m_callbacks.append([callback]() { + if (callback) + callback->handleEvent(); + }); return; - } case SecurityOrigin::Ask: - return m_client->requestPermission(scriptExecutionContext(), callback); + m_client->requestPermission(scriptExecutionContext(), WTFMove(callback)); + return; } ASSERT_NOT_REACHED(); - m_client->requestPermission(scriptExecutionContext(), callback); + m_client->requestPermission(scriptExecutionContext(), WTFMove(callback)); } + #endif void NotificationCenter::stop() { if (!m_client) return; - m_client->cancelRequestsForPermission(scriptExecutionContext()); - m_client->clearNotifications(scriptExecutionContext()); - m_client = 0; -} -void NotificationCenter::requestTimedOut(NotificationCenter::NotificationRequestCallback* request) -{ - m_callbacks.remove(request); -} + // Clear m_client immediately to guarantee reentrant calls to NotificationCenter do nothing. + // Also protect |this| so it's not indirectly destroyed under us by work done by the client. + auto& client = *std::exchange(m_client, nullptr); + Ref protectedThis(*this); -PassRefPtr NotificationCenter::NotificationRequestCallback::createAndStartTimer(NotificationCenter* center, PassRefPtr callback) -{ - RefPtr requestCallback = adoptRef(new NotificationCenter::NotificationRequestCallback(center, callback)); - requestCallback->startTimer(); - return requestCallback.release(); + if (!m_callbacks.isEmpty()) + deref(); // Balanced by the ref in NotificationCenter::requestPermission. + + m_timer.stop(); + m_callbacks.clear(); + + client.cancelRequestsForPermission(scriptExecutionContext()); + client.clearNotifications(scriptExecutionContext()); } -NotificationCenter::NotificationRequestCallback::NotificationRequestCallback(NotificationCenter* center, PassRefPtr callback) - : m_notificationCenter(center) - , m_timer(this, &NotificationCenter::NotificationRequestCallback::timerFired) - , m_callback(callback) +const char* NotificationCenter::activeDOMObjectName() const { + return "NotificationCenter"; } -void NotificationCenter::NotificationRequestCallback::startTimer() +bool NotificationCenter::canSuspendForDocumentSuspension() const { - m_timer.startOneShot(0); + // We don't need to worry about Notifications because those are ActiveDOMObject too. + // The NotificationCenter can safely be suspended if there are no pending permission requests. + return m_callbacks.isEmpty() && (!m_client || !m_client->hasPendingPermissionRequests(scriptExecutionContext())); } -void NotificationCenter::NotificationRequestCallback::timerFired(Timer&) +void NotificationCenter::timerFired() { - if (m_callback) - m_callback->handleEvent(); - m_notificationCenter->requestTimedOut(this); + ASSERT(m_client); + auto callbacks = WTFMove(m_callbacks); + for (auto& callback : callbacks) + callback(); + deref(); // Balanced by the ref in NotificationCenter::requestPermission. } } // namespace WebCore -- cgit v1.2.1