OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2013 Google Inc. All rights reserved. | 2 * Copyright (C) 2013 Google Inc. All rights reserved. |
3 * | 3 * |
4 * Redistribution and use in source and binary forms, with or without | 4 * Redistribution and use in source and binary forms, with or without |
5 * modification, are permitted provided that the following conditions are | 5 * modification, are permitted provided that the following conditions are |
6 * met: | 6 * met: |
7 * | 7 * |
8 * * Redistributions of source code must retain the above copyright | 8 * * Redistributions of source code must retain the above copyright |
9 * notice, this list of conditions and the following disclaimer. | 9 * notice, this list of conditions and the following disclaimer. |
10 * * Redistributions in binary form must reproduce the above | 10 * * Redistributions in binary form must reproduce the above |
(...skipping 75 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
86 return nullptr; | 86 return nullptr; |
87 } | 87 } |
88 | 88 |
89 RefPtr<SerializedScriptValue> data; | 89 RefPtr<SerializedScriptValue> data; |
90 if (options.hasData()) { | 90 if (options.hasData()) { |
91 data = SerializedScriptValueFactory::instance().create(options.data().is
olate(), options.data(), nullptr, exceptionState); | 91 data = SerializedScriptValueFactory::instance().create(options.data().is
olate(), options.data(), nullptr, exceptionState); |
92 if (exceptionState.hadException()) | 92 if (exceptionState.hadException()) |
93 return nullptr; | 93 return nullptr; |
94 } | 94 } |
95 | 95 |
| 96 for (const NotificationAction& action : options.actions()) { |
| 97 if (action.title().isEmpty()) { |
| 98 exceptionState.throwTypeError("Notification action titles must not b
e empty."); |
| 99 return nullptr; |
| 100 } |
| 101 } |
| 102 |
96 Notification* notification = new Notification(title, context); | 103 Notification* notification = new Notification(title, context); |
97 | 104 |
98 notification->setBody(options.body()); | 105 notification->setBody(options.body()); |
99 notification->setTag(options.tag()); | 106 notification->setTag(options.tag()); |
100 notification->setLang(options.lang()); | 107 notification->setLang(options.lang()); |
101 notification->setDir(options.dir()); | 108 notification->setDir(options.dir()); |
102 notification->setVibrate(NavigatorVibration::sanitizeVibrationPattern(option
s.vibrate())); | 109 notification->setVibrate(NavigatorVibration::sanitizeVibrationPattern(option
s.vibrate())); |
103 notification->setSilent(options.silent()); | 110 notification->setSilent(options.silent()); |
104 notification->setSerializedData(data.release()); | 111 notification->setSerializedData(data.release()); |
105 if (options.hasIcon()) { | 112 if (options.hasIcon()) { |
106 KURL iconUrl = options.icon().isEmpty() ? KURL() : context->completeURL(
options.icon()); | 113 KURL iconUrl = options.icon().isEmpty() ? KURL() : context->completeURL(
options.icon()); |
107 if (!iconUrl.isEmpty() && iconUrl.isValid()) | 114 if (!iconUrl.isEmpty() && iconUrl.isValid()) |
108 notification->setIconUrl(iconUrl); | 115 notification->setIconUrl(iconUrl); |
109 } | 116 } |
| 117 HeapVector<NotificationAction> actions; |
| 118 actions.appendRange(options.actions().begin(), options.actions().begin() + s
td::min(maxActions(), options.actions().size())); |
| 119 notification->setActions(actions); |
110 | 120 |
111 String insecureOriginMessage; | 121 String insecureOriginMessage; |
112 UseCounter::Feature feature = context->isPrivilegedContext(insecureOriginMes
sage) | 122 UseCounter::Feature feature = context->isPrivilegedContext(insecureOriginMes
sage) |
113 ? UseCounter::NotificationSecureOrigin | 123 ? UseCounter::NotificationSecureOrigin |
114 : UseCounter::NotificationInsecureOrigin; | 124 : UseCounter::NotificationInsecureOrigin; |
115 UseCounter::count(context, feature); | 125 UseCounter::count(context, feature); |
116 | 126 |
117 notification->scheduleShow(); | 127 notification->scheduleShow(); |
118 notification->suspendIfNeeded(); | 128 notification->suspendIfNeeded(); |
119 return notification; | 129 return notification; |
(...skipping 18 matching lines...) Expand all Loading... |
138 pattern.appendRange(data.vibrate.begin(), data.vibrate.end()); | 148 pattern.appendRange(data.vibrate.begin(), data.vibrate.end()); |
139 notification->setVibrate(pattern); | 149 notification->setVibrate(pattern); |
140 } | 150 } |
141 | 151 |
142 const WebVector<char>& dataBytes = data.data; | 152 const WebVector<char>& dataBytes = data.data; |
143 if (!dataBytes.isEmpty()) { | 153 if (!dataBytes.isEmpty()) { |
144 notification->setSerializedData(SerializedScriptValueFactory::instance()
.createFromWireBytes(dataBytes.data(), dataBytes.size())); | 154 notification->setSerializedData(SerializedScriptValueFactory::instance()
.createFromWireBytes(dataBytes.data(), dataBytes.size())); |
145 notification->serializedData()->registerMemoryAllocatedWithCurrentScript
Context(); | 155 notification->serializedData()->registerMemoryAllocatedWithCurrentScript
Context(); |
146 } | 156 } |
147 | 157 |
| 158 HeapVector<NotificationAction> actions; |
| 159 webActionsToActions(data.actions, &actions); |
| 160 notification->setActions(actions); |
| 161 |
148 notification->setState(NotificationStateShowing); | 162 notification->setState(NotificationStateShowing); |
149 notification->suspendIfNeeded(); | 163 notification->suspendIfNeeded(); |
150 return notification; | 164 return notification; |
151 } | 165 } |
152 | 166 |
153 Notification::Notification(const String& title, ExecutionContext* context) | 167 Notification::Notification(const String& title, ExecutionContext* context) |
154 : ActiveDOMObject(context) | 168 : ActiveDOMObject(context) |
155 , m_title(title) | 169 , m_title(title) |
156 , m_dir("auto") | 170 , m_dir("auto") |
157 , m_silent(false) | 171 , m_silent(false) |
(...skipping 27 matching lines...) Expand all Loading... |
185 SecurityOrigin* origin = executionContext()->securityOrigin(); | 199 SecurityOrigin* origin = executionContext()->securityOrigin(); |
186 ASSERT(origin); | 200 ASSERT(origin); |
187 | 201 |
188 // FIXME: Do CSP checks on the associated notification icon. | 202 // FIXME: Do CSP checks on the associated notification icon. |
189 WebNotificationData::Direction dir = m_dir == "rtl" ? WebNotificationData::D
irectionRightToLeft : WebNotificationData::DirectionLeftToRight; | 203 WebNotificationData::Direction dir = m_dir == "rtl" ? WebNotificationData::D
irectionRightToLeft : WebNotificationData::DirectionLeftToRight; |
190 | 204 |
191 // The lifetime and availability of non-persistent notifications is tied to
the page | 205 // The lifetime and availability of non-persistent notifications is tied to
the page |
192 // they were created by, and thus the data doesn't have to be known to the e
mbedder. | 206 // they were created by, and thus the data doesn't have to be known to the e
mbedder. |
193 Vector<char> emptyDataWireBytes; | 207 Vector<char> emptyDataWireBytes; |
194 | 208 |
195 WebNotificationData notificationData(m_title, dir, m_lang, m_body, m_tag, m_
iconUrl, m_vibrate, m_silent, emptyDataWireBytes); | 209 WebVector<WebNotificationAction> webActions; |
| 210 actionsToWebActions(m_actions, &webActions); |
| 211 |
| 212 WebNotificationData notificationData(m_title, dir, m_lang, m_body, m_tag, m_
iconUrl, m_vibrate, m_silent, emptyDataWireBytes, webActions); |
196 notificationManager()->show(WebSecurityOrigin(origin), notificationData, thi
s); | 213 notificationManager()->show(WebSecurityOrigin(origin), notificationData, thi
s); |
197 | 214 |
198 m_state = NotificationStateShowing; | 215 m_state = NotificationStateShowing; |
199 } | 216 } |
200 | 217 |
201 void Notification::close() | 218 void Notification::close() |
202 { | 219 { |
203 if (m_state != NotificationStateShowing) | 220 if (m_state != NotificationStateShowing) |
204 return; | 221 return; |
205 | 222 |
(...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
240 { | 257 { |
241 // The notification will be showing when the user initiated the close, or it
will be | 258 // The notification will be showing when the user initiated the close, or it
will be |
242 // closing if the developer initiated the close. | 259 // closing if the developer initiated the close. |
243 if (m_state != NotificationStateShowing && m_state != NotificationStateClosi
ng) | 260 if (m_state != NotificationStateShowing && m_state != NotificationStateClosi
ng) |
244 return; | 261 return; |
245 | 262 |
246 m_state = NotificationStateClosed; | 263 m_state = NotificationStateClosed; |
247 dispatchEvent(Event::create(EventTypeNames::close)); | 264 dispatchEvent(Event::create(EventTypeNames::close)); |
248 } | 265 } |
249 | 266 |
250 NavigatorVibration::VibrationPattern Notification::vibrate(bool& isNull) const | 267 const NavigatorVibration::VibrationPattern& Notification::vibrate(bool& isNull)
const |
251 { | 268 { |
252 isNull = m_vibrate.isEmpty(); | 269 isNull = m_vibrate.isEmpty(); |
253 return m_vibrate; | 270 return m_vibrate; |
254 } | 271 } |
255 | 272 |
256 TextDirection Notification::direction() const | 273 TextDirection Notification::direction() const |
257 { | 274 { |
258 // FIXME: Resolve dir()=="auto" against the document. | 275 // FIXME: Resolve dir()=="auto" against the document. |
259 return dir() == "rtl" ? RTL : LTR; | 276 return dir() == "rtl" ? RTL : LTR; |
260 } | 277 } |
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
293 NotificationPermissionClient* permissionClient = NotificationPermissionClien
t::from(context); | 310 NotificationPermissionClient* permissionClient = NotificationPermissionClien
t::from(context); |
294 if (!permissionClient) { | 311 if (!permissionClient) { |
295 // TODO(peter): Assert that this code-path will only be reached for Docu
ment environments when Blink | 312 // TODO(peter): Assert that this code-path will only be reached for Docu
ment environments when Blink |
296 // supports [Exposed] annotations on class members in IDL definitions. S
ee https://crbug.com/442139. | 313 // supports [Exposed] annotations on class members in IDL definitions. S
ee https://crbug.com/442139. |
297 return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(),
permission(context))); | 314 return ScriptPromise::cast(scriptState, v8String(scriptState->isolate(),
permission(context))); |
298 } | 315 } |
299 | 316 |
300 return permissionClient->requestPermission(scriptState, deprecatedCallback); | 317 return permissionClient->requestPermission(scriptState, deprecatedCallback); |
301 } | 318 } |
302 | 319 |
303 unsigned Notification::maxActions() | 320 size_t Notification::maxActions() |
304 { | 321 { |
305 return notificationManager()->maxActions(); | 322 return notificationManager()->maxActions(); |
306 } | 323 } |
307 | 324 |
| 325 void Notification::actionsToWebActions(const HeapVector<NotificationAction>& act
ions, WebVector<WebNotificationAction>* webActions) |
| 326 { |
| 327 size_t count = std::min(maxActions(), actions.size()); |
| 328 WebVector<WebNotificationAction> clearedAndResized(count); |
| 329 webActions->swap(clearedAndResized); |
| 330 for (size_t i = 0; i < count; ++i) |
| 331 (*webActions)[i].title = actions[i].title(); |
| 332 } |
| 333 |
| 334 void Notification::webActionsToActions(const WebVector<WebNotificationAction>& w
ebActions, HeapVector<NotificationAction>* actions) |
| 335 { |
| 336 actions->clear(); |
| 337 actions->grow(webActions.size()); |
| 338 for (size_t i = 0; i < webActions.size(); ++i) |
| 339 (*actions)[i].setTitle(webActions[i].title); |
| 340 } |
| 341 |
308 bool Notification::dispatchEventInternal(PassRefPtrWillBeRawPtr<Event> event) | 342 bool Notification::dispatchEventInternal(PassRefPtrWillBeRawPtr<Event> event) |
309 { | 343 { |
310 ASSERT(executionContext()->isContextThread()); | 344 ASSERT(executionContext()->isContextThread()); |
311 return EventTarget::dispatchEventInternal(event); | 345 return EventTarget::dispatchEventInternal(event); |
312 } | 346 } |
313 | 347 |
314 const AtomicString& Notification::interfaceName() const | 348 const AtomicString& Notification::interfaceName() const |
315 { | 349 { |
316 return EventTargetNames::Notification; | 350 return EventTargetNames::Notification; |
317 } | 351 } |
(...skipping 15 matching lines...) Expand all Loading... |
333 ScriptValue Notification::data(ScriptState* scriptState) const | 367 ScriptValue Notification::data(ScriptState* scriptState) const |
334 { | 368 { |
335 if (!m_serializedData) | 369 if (!m_serializedData) |
336 return ScriptValue::createNull(scriptState); | 370 return ScriptValue::createNull(scriptState); |
337 | 371 |
338 return ScriptValue(scriptState, m_serializedData->deserialize(scriptState->i
solate())); | 372 return ScriptValue(scriptState, m_serializedData->deserialize(scriptState->i
solate())); |
339 } | 373 } |
340 | 374 |
341 DEFINE_TRACE(Notification) | 375 DEFINE_TRACE(Notification) |
342 { | 376 { |
| 377 visitor->trace(m_actions); |
343 RefCountedGarbageCollectedEventTargetWithInlineData<Notification>::trace(vis
itor); | 378 RefCountedGarbageCollectedEventTargetWithInlineData<Notification>::trace(vis
itor); |
344 ActiveDOMObject::trace(visitor); | 379 ActiveDOMObject::trace(visitor); |
345 } | 380 } |
346 | 381 |
347 } // namespace blink | 382 } // namespace blink |
OLD | NEW |