| // Copyright 2015 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| #include "modules/notifications/NotificationData.h" |
| |
| #include "bindings/core/v8/ExceptionState.h" |
| #include "bindings/core/v8/serialization/SerializedScriptValue.h" |
| #include "bindings/core/v8/serialization/SerializedScriptValueFactory.h" |
| #include "core/dom/ExecutionContext.h" |
| #include "modules/notifications/Notification.h" |
| #include "modules/notifications/NotificationOptions.h" |
| #include "modules/vibration/VibrationController.h" |
| #include "platform/wtf/CurrentTime.h" |
| #include "public/platform/WebURL.h" |
| |
| namespace blink { |
| namespace { |
| |
| WebNotificationData::Direction ToDirectionEnumValue(const String& direction) { |
| if (direction == "ltr") |
| return WebNotificationData::kDirectionLeftToRight; |
| if (direction == "rtl") |
| return WebNotificationData::kDirectionRightToLeft; |
| |
| return WebNotificationData::kDirectionAuto; |
| } |
| |
| WebURL CompleteURL(ExecutionContext* execution_context, |
| const String& string_url) { |
| WebURL url = execution_context->CompleteURL(string_url); |
| if (url.IsValid()) |
| return url; |
| return WebURL(); |
| } |
| |
| } // namespace |
| |
| WebNotificationData CreateWebNotificationData( |
| ExecutionContext* execution_context, |
| const String& title, |
| const NotificationOptions& options, |
| ExceptionState& exception_state) { |
| // If silent is true, the notification must not have a vibration pattern. |
| if (options.hasVibrate() && options.silent()) { |
| exception_state.ThrowTypeError( |
| "Silent notifications must not specify vibration patterns."); |
| return WebNotificationData(); |
| } |
| |
| // If renotify is true, the notification must have a tag. |
| if (options.renotify() && options.tag().IsEmpty()) { |
| exception_state.ThrowTypeError( |
| "Notifications which set the renotify flag must specify a non-empty " |
| "tag."); |
| return WebNotificationData(); |
| } |
| |
| WebNotificationData web_data; |
| |
| web_data.title = title; |
| web_data.direction = ToDirectionEnumValue(options.dir()); |
| web_data.lang = options.lang(); |
| web_data.body = options.body(); |
| web_data.tag = options.tag(); |
| |
| if (options.hasImage() && !options.image().IsEmpty()) |
| web_data.image = CompleteURL(execution_context, options.image()); |
| |
| if (options.hasIcon() && !options.icon().IsEmpty()) |
| web_data.icon = CompleteURL(execution_context, options.icon()); |
| |
| if (options.hasBadge() && !options.badge().IsEmpty()) |
| web_data.badge = CompleteURL(execution_context, options.badge()); |
| |
| web_data.vibrate = |
| VibrationController::SanitizeVibrationPattern(options.vibrate()); |
| web_data.timestamp = options.hasTimestamp() |
| ? static_cast<double>(options.timestamp()) |
| : WTF::CurrentTimeMS(); |
| web_data.renotify = options.renotify(); |
| web_data.silent = options.silent(); |
| web_data.require_interaction = options.requireInteraction(); |
| |
| if (options.hasData()) { |
| const ScriptValue& data = options.data(); |
| v8::Isolate* isolate = data.GetIsolate(); |
| DCHECK(isolate->InContext()); |
| SerializedScriptValue::SerializeOptions options; |
| options.for_storage = SerializedScriptValue::kForStorage; |
| scoped_refptr<SerializedScriptValue> serialized_script_value = |
| SerializedScriptValue::Serialize(isolate, data.V8Value(), options, |
| exception_state); |
| if (exception_state.HadException()) |
| return WebNotificationData(); |
| |
| Vector<char> serialized_data; |
| serialized_script_value->ToWireBytes(serialized_data); |
| |
| web_data.data = serialized_data; |
| } |
| |
| Vector<WebNotificationAction> actions; |
| |
| const size_t max_actions = Notification::maxActions(); |
| for (const NotificationAction& action : options.actions()) { |
| if (actions.size() >= max_actions) |
| break; |
| |
| WebNotificationAction web_action; |
| web_action.action = action.action(); |
| web_action.title = action.title(); |
| |
| if (action.type() == "button") |
| web_action.type = WebNotificationAction::kButton; |
| else if (action.type() == "text") |
| web_action.type = WebNotificationAction::kText; |
| else |
| NOTREACHED() << "Unknown action type: " << action.type(); |
| |
| if (action.hasPlaceholder() && |
| web_action.type == WebNotificationAction::kButton) { |
| exception_state.ThrowTypeError( |
| "Notifications of type \"button\" cannot specify a placeholder."); |
| return WebNotificationData(); |
| } |
| |
| web_action.placeholder = action.placeholder(); |
| |
| if (action.hasIcon() && !action.icon().IsEmpty()) |
| web_action.icon = CompleteURL(execution_context, action.icon()); |
| |
| actions.push_back(web_action); |
| } |
| |
| web_data.actions = actions; |
| |
| return web_data; |
| } |
| |
| } // namespace blink |