| Index: Source/modules/notifications/Notification.cpp
|
| diff --git a/Source/modules/notifications/Notification.cpp b/Source/modules/notifications/Notification.cpp
|
| index cb95b15625b0b8f6661ed312321f923e6d905d7f..7f757ac521d3ba5077a7c6bc55fecfdf80782aa0 100644
|
| --- a/Source/modules/notifications/Notification.cpp
|
| +++ b/Source/modules/notifications/Notification.cpp
|
| @@ -43,6 +43,8 @@
|
| #include "core/dom/ScopedWindowFocusAllowedIndicator.h"
|
| #include "core/events/Event.h"
|
| #include "core/frame/UseCounter.h"
|
| +#include "modules/notifications/NotificationAction.h"
|
| +#include "modules/notifications/NotificationData.h"
|
| #include "modules/notifications/NotificationOptions.h"
|
| #include "modules/notifications/NotificationPermissionClient.h"
|
| #include "platform/RuntimeEnabledFeatures.h"
|
| @@ -50,7 +52,7 @@
|
| #include "public/platform/Platform.h"
|
| #include "public/platform/WebSecurityOrigin.h"
|
| #include "public/platform/WebString.h"
|
| -#include "public/platform/modules/notifications/WebNotificationData.h"
|
| +#include "public/platform/modules/notifications/WebNotificationAction.h"
|
| #include "public/platform/modules/notifications/WebNotificationManager.h"
|
|
|
| namespace blink {
|
| @@ -80,99 +82,37 @@ Notification* Notification::create(ExecutionContext* context, const String& titl
|
| return nullptr;
|
| }
|
|
|
| - // If options's silent is true, and options's vibrate is present, throw a TypeError exception.
|
| - if (options.hasVibrate() && options.silent()) {
|
| - exceptionState.throwTypeError("Silent notifications must not specify vibration patterns.");
|
| - return nullptr;
|
| - }
|
| -
|
| - RefPtr<SerializedScriptValue> data;
|
| - if (options.hasData()) {
|
| - data = SerializedScriptValueFactory::instance().create(options.data().isolate(), options.data(), nullptr, exceptionState);
|
| - if (exceptionState.hadException())
|
| - return nullptr;
|
| - }
|
| -
|
| - for (const NotificationAction& action : options.actions()) {
|
| - if (action.action().isEmpty()) {
|
| - exceptionState.throwTypeError("NotificationAction action must not be empty.");
|
| - return nullptr;
|
| - }
|
| - if (action.title().isEmpty()) {
|
| - exceptionState.throwTypeError("NotificationAction title must not be empty.");
|
| - return nullptr;
|
| - }
|
| - }
|
| -
|
| - Notification* notification = new Notification(title, context);
|
| -
|
| - notification->setBody(options.body());
|
| - notification->setTag(options.tag());
|
| - notification->setLang(options.lang());
|
| - notification->setDir(options.dir());
|
| - notification->setVibrate(NavigatorVibration::sanitizeVibrationPattern(options.vibrate()));
|
| - notification->setSilent(options.silent());
|
| - notification->setSerializedData(data.release());
|
| - if (options.hasIcon()) {
|
| - KURL iconUrl = options.icon().isEmpty() ? KURL() : context->completeURL(options.icon());
|
| - if (!iconUrl.isEmpty() && iconUrl.isValid())
|
| - notification->setIconUrl(iconUrl);
|
| - }
|
| - HeapVector<NotificationAction> actions;
|
| - actions.appendRange(options.actions().begin(), options.actions().begin() + std::min(maxActions(), options.actions().size()));
|
| - notification->setActions(actions);
|
| -
|
| String insecureOriginMessage;
|
| UseCounter::Feature feature = context->isPrivilegedContext(insecureOriginMessage)
|
| ? UseCounter::NotificationSecureOrigin
|
| : UseCounter::NotificationInsecureOrigin;
|
| +
|
| UseCounter::count(context, feature);
|
|
|
| + WebNotificationData data = createWebNotificationData(context, title, options, exceptionState);
|
| + if (exceptionState.hadException())
|
| + return nullptr;
|
| +
|
| + Notification* notification = new Notification(context, data);
|
| notification->scheduleShow();
|
| notification->suspendIfNeeded();
|
| +
|
| return notification;
|
| }
|
|
|
| Notification* Notification::create(ExecutionContext* context, int64_t persistentId, const WebNotificationData& data)
|
| {
|
| - Notification* notification = new Notification(data.title, context);
|
| -
|
| + Notification* notification = new Notification(context, data);
|
| notification->setPersistentId(persistentId);
|
| - notification->setDir(data.direction == WebNotificationData::DirectionLeftToRight ? "ltr" : "rtl");
|
| - notification->setLang(data.lang);
|
| - notification->setBody(data.body);
|
| - notification->setTag(data.tag);
|
| - notification->setSilent(data.silent);
|
| -
|
| - if (!data.icon.isEmpty())
|
| - notification->setIconUrl(data.icon);
|
| -
|
| - if (!data.vibrate.isEmpty()) {
|
| - NavigatorVibration::VibrationPattern pattern;
|
| - pattern.appendRange(data.vibrate.begin(), data.vibrate.end());
|
| - notification->setVibrate(pattern);
|
| - }
|
| -
|
| - const WebVector<char>& dataBytes = data.data;
|
| - if (!dataBytes.isEmpty()) {
|
| - notification->setSerializedData(SerializedScriptValueFactory::instance().createFromWireBytes(dataBytes.data(), dataBytes.size()));
|
| - notification->serializedData()->registerMemoryAllocatedWithCurrentScriptContext();
|
| - }
|
| -
|
| - HeapVector<NotificationAction> actions;
|
| - webActionsToActions(data.actions, &actions);
|
| - notification->setActions(actions);
|
| -
|
| notification->setState(NotificationStateShowing);
|
| notification->suspendIfNeeded();
|
| +
|
| return notification;
|
| }
|
|
|
| -Notification::Notification(const String& title, ExecutionContext* context)
|
| +Notification::Notification(ExecutionContext* context, const WebNotificationData& data)
|
| : ActiveDOMObject(context)
|
| - , m_title(title)
|
| - , m_dir("auto")
|
| - , m_silent(false)
|
| + , m_data(data)
|
| , m_persistentId(kInvalidPersistentId)
|
| , m_state(NotificationStateIdle)
|
| , m_asyncRunner(this, &Notification::show)
|
| @@ -203,18 +143,7 @@ void Notification::show()
|
| SecurityOrigin* origin = executionContext()->securityOrigin();
|
| ASSERT(origin);
|
|
|
| - // FIXME: Do CSP checks on the associated notification icon.
|
| - WebNotificationData::Direction dir = m_dir == "rtl" ? WebNotificationData::DirectionRightToLeft : WebNotificationData::DirectionLeftToRight;
|
| -
|
| - // The lifetime and availability of non-persistent notifications is tied to the page
|
| - // they were created by, and thus the data doesn't have to be known to the embedder.
|
| - Vector<char> emptyDataWireBytes;
|
| -
|
| - WebVector<WebNotificationAction> webActions;
|
| - actionsToWebActions(m_actions, &webActions);
|
| -
|
| - WebNotificationData notificationData(m_title, dir, m_lang, m_body, m_tag, m_iconUrl, m_vibrate, m_silent, emptyDataWireBytes, webActions);
|
| - notificationManager()->show(WebSecurityOrigin(origin), notificationData, this);
|
| + notificationManager()->show(WebSecurityOrigin(origin), m_data, this);
|
|
|
| m_state = NotificationStateShowing;
|
| }
|
| @@ -268,16 +197,88 @@ void Notification::dispatchCloseEvent()
|
| dispatchEvent(Event::create(EventTypeNames::close));
|
| }
|
|
|
| -const NavigatorVibration::VibrationPattern& Notification::vibrate(bool& isNull) const
|
| +String Notification::title() const
|
| {
|
| - isNull = m_vibrate.isEmpty();
|
| - return m_vibrate;
|
| + return m_data.title;
|
| }
|
|
|
| -TextDirection Notification::direction() const
|
| +String Notification::dir() const
|
| {
|
| - // FIXME: Resolve dir()=="auto" against the document.
|
| - return dir() == "rtl" ? RTL : LTR;
|
| + switch (m_data.direction) {
|
| + case WebNotificationData::DirectionLeftToRight:
|
| + return "ltr";
|
| + case WebNotificationData::DirectionRightToLeft:
|
| + return "rtl";
|
| + case WebNotificationData::DirectionAuto:
|
| + return "auto";
|
| + }
|
| +
|
| + ASSERT_NOT_REACHED();
|
| + return String();
|
| +}
|
| +
|
| +String Notification::lang() const
|
| +{
|
| + return m_data.lang;
|
| +}
|
| +
|
| +String Notification::body() const
|
| +{
|
| + return m_data.body;
|
| +}
|
| +
|
| +String Notification::tag() const
|
| +{
|
| + return m_data.tag;
|
| +}
|
| +
|
| +String Notification::icon() const
|
| +{
|
| + return m_data.icon.string();
|
| +}
|
| +
|
| +NavigatorVibration::VibrationPattern Notification::vibrate(bool& isNull) const
|
| +{
|
| + NavigatorVibration::VibrationPattern pattern;
|
| + pattern.appendRange(m_data.vibrate.begin(), m_data.vibrate.end());
|
| +
|
| + if (!pattern.size())
|
| + isNull = true;
|
| +
|
| + return pattern;
|
| +}
|
| +
|
| +bool Notification::silent() const
|
| +{
|
| + return m_data.silent;
|
| +}
|
| +
|
| +ScriptValue Notification::data(ScriptState* scriptState)
|
| +{
|
| + // TODO(peter): The specification requires this to be [SameObject] - match this.
|
| +
|
| + if (!m_serializedData) {
|
| + const WebVector<char> serializedData = m_data.data;
|
| + if (serializedData.size())
|
| + m_serializedData = SerializedScriptValueFactory::instance().createFromWireBytes(serializedData.data(), serializedData.size());
|
| + else
|
| + m_serializedData = SerializedScriptValueFactory::instance().create();
|
| + }
|
| +
|
| + return ScriptValue(scriptState, m_serializedData->deserialize(scriptState->isolate()));
|
| +}
|
| +
|
| +HeapVector<NotificationAction> Notification::actions() const
|
| +{
|
| + HeapVector<NotificationAction> actions;
|
| + actions.grow(m_data.actions.size());
|
| +
|
| + for (size_t i = 0; i < m_data.actions.size(); ++i) {
|
| + actions[i].setAction(m_data.actions[i].action);
|
| + actions[i].setTitle(m_data.actions[i].title);
|
| + }
|
| +
|
| + return actions;
|
| }
|
|
|
| String Notification::permissionString(WebNotificationPermission permission)
|
| @@ -323,28 +324,11 @@ ScriptPromise Notification::requestPermission(ScriptState* scriptState, Notifica
|
|
|
| size_t Notification::maxActions()
|
| {
|
| - return notificationManager()->maxActions();
|
| -}
|
| -
|
| -void Notification::actionsToWebActions(const HeapVector<NotificationAction>& actions, WebVector<WebNotificationAction>* webActions)
|
| -{
|
| - size_t count = std::min(maxActions(), actions.size());
|
| - WebVector<WebNotificationAction> clearedAndResized(count);
|
| - webActions->swap(clearedAndResized);
|
| - for (size_t i = 0; i < count; ++i) {
|
| - (*webActions)[i].action = actions[i].action();
|
| - (*webActions)[i].title = actions[i].title();
|
| - }
|
| -}
|
| + // Returns a fixed number for unit tests, which run without the availability of the Platform object.
|
| + if (!notificationManager())
|
| + return 2;
|
|
|
| -void Notification::webActionsToActions(const WebVector<WebNotificationAction>& webActions, HeapVector<NotificationAction>* actions)
|
| -{
|
| - actions->clear();
|
| - actions->grow(webActions.size());
|
| - for (size_t i = 0; i < webActions.size(); ++i) {
|
| - (*actions)[i].setAction(webActions[i].action);
|
| - (*actions)[i].setTitle(webActions[i].title);
|
| - }
|
| + return notificationManager()->maxActions();
|
| }
|
|
|
| bool Notification::dispatchEventInternal(PassRefPtrWillBeRawPtr<Event> event)
|
| @@ -372,17 +356,8 @@ bool Notification::hasPendingActivity() const
|
| return m_state == NotificationStateShowing || m_asyncRunner.isActive();
|
| }
|
|
|
| -ScriptValue Notification::data(ScriptState* scriptState) const
|
| -{
|
| - if (!m_serializedData)
|
| - return ScriptValue::createNull(scriptState);
|
| -
|
| - return ScriptValue(scriptState, m_serializedData->deserialize(scriptState->isolate()));
|
| -}
|
| -
|
| DEFINE_TRACE(Notification)
|
| {
|
| - visitor->trace(m_actions);
|
| RefCountedGarbageCollectedEventTargetWithInlineData<Notification>::trace(visitor);
|
| ActiveDOMObject::trace(visitor);
|
| }
|
|
|