Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1860)

Unified Diff: Source/modules/notifications/Notification.cpp

Issue 1260793007: Generalize validation of developer input for Web Notifications (Closed) Base URL: svn://svn.chromium.org/blink/trunk
Patch Set: Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: Source/modules/notifications/Notification.cpp
diff --git a/Source/modules/notifications/Notification.cpp b/Source/modules/notifications/Notification.cpp
index e11876a229e2dc3dcfaf38e0dc10e15f8a5d1ece..76c6bd50804641c86858939b633a4700b68e8343 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,95 +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.title().isEmpty()) {
- exceptionState.throwTypeError("Notification action titles 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)
@@ -199,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;
}
@@ -264,16 +197,84 @@ void Notification::dispatchCloseEvent()
dispatchEvent(Event::create(EventTypeNames::close));
}
-const NavigatorVibration::VibrationPattern& Notification::vibrate(bool& isNull) const
+String Notification::title() const
+{
+ return m_data.title;
+}
+
+String Notification::dir() const
+{
+ switch (m_data.direction) {
+ case WebNotificationData::DirectionLeftToRight:
+ return "ltr";
+ case WebNotificationData::DirectionRightToLeft:
+ return "rtl";
+ }
+
+ 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)
{
- isNull = m_vibrate.isEmpty();
- return m_vibrate;
+ // TODO(peter): The specification requires this to be [SameObject] - match this.
johnme 2015/08/03 15:41:36 Is this a change from before, or an old TODO that
Peter Beverloo 2015/08/03 17:29:30 TODO that still applies. I don't think we're doing
+
+ 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()));
}
-TextDirection Notification::direction() const
+HeapVector<NotificationAction> Notification::actions() const
{
- // FIXME: Resolve dir()=="auto" against the document.
- return dir() == "rtl" ? RTL : LTR;
+ HeapVector<NotificationAction> actions;
+ actions.grow(m_data.actions.size());
+
+ for (size_t i = 0; i < m_data.actions.size(); ++i)
+ actions[i].setTitle(m_data.actions[i].title);
+
+ return actions;
}
String Notification::permissionString(WebNotificationPermission permission)
@@ -319,24 +320,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].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].setTitle(webActions[i].title);
+ return notificationManager()->maxActions();
}
bool Notification::dispatchEventInternal(PassRefPtrWillBeRawPtr<Event> event)
@@ -364,17 +352,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);
}

Powered by Google App Engine
This is Rietveld 408576698