| 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 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 93 } else { | 93 } else { |
| 94 UseCounter::count(context, UseCounter::NotificationInsecureOrigin); | 94 UseCounter::count(context, UseCounter::NotificationInsecureOrigin); |
| 95 if (context->isDocument()) | 95 if (context->isDocument()) |
| 96 UseCounter::countCrossOriginIframe(*toDocument(context), UseCounter
::NotificationAPIInsecureOriginIframe); | 96 UseCounter::countCrossOriginIframe(*toDocument(context), UseCounter
::NotificationAPIInsecureOriginIframe); |
| 97 } | 97 } |
| 98 | 98 |
| 99 WebNotificationData data = createWebNotificationData(context, title, options
, exceptionState); | 99 WebNotificationData data = createWebNotificationData(context, title, options
, exceptionState); |
| 100 if (exceptionState.hadException()) | 100 if (exceptionState.hadException()) |
| 101 return nullptr; | 101 return nullptr; |
| 102 | 102 |
| 103 Notification* notification = new Notification(context, data); | 103 Notification* notification = new Notification(context, Type::NonPersistent,
data); |
| 104 notification->schedulePrepareShow(); | 104 notification->schedulePrepareShow(); |
| 105 |
| 105 notification->suspendIfNeeded(); | 106 notification->suspendIfNeeded(); |
| 106 | |
| 107 return notification; | 107 return notification; |
| 108 } | 108 } |
| 109 | 109 |
| 110 Notification* Notification::create(ExecutionContext* context, const String& noti
ficationId, const WebNotificationData& data, bool showing) | 110 Notification* Notification::create(ExecutionContext* context, const String& noti
ficationId, const WebNotificationData& data, bool showing) |
| 111 { | 111 { |
| 112 Notification* notification = new Notification(context, data); | 112 Notification* notification = new Notification(context, Type::Persistent, dat
a); |
| 113 notification->setState(showing ? State::Showing : State::Closed); |
| 113 notification->setNotificationId(notificationId); | 114 notification->setNotificationId(notificationId); |
| 114 notification->setState(showing ? NotificationStateShowing : NotificationStat
eClosed); | 115 |
| 115 notification->suspendIfNeeded(); | 116 notification->suspendIfNeeded(); |
| 116 | |
| 117 return notification; | 117 return notification; |
| 118 } | 118 } |
| 119 | 119 |
| 120 Notification::Notification(ExecutionContext* context, const WebNotificationData&
data) | 120 Notification::Notification(ExecutionContext* context, Type type, const WebNotifi
cationData& data) |
| 121 : ActiveScriptWrappable(this) | 121 : ActiveScriptWrappable(this) |
| 122 , ActiveDOMObject(context) | 122 , ActiveDOMObject(context) |
| 123 , m_type(type) |
| 124 , m_state(State::Loading) |
| 123 , m_data(data) | 125 , m_data(data) |
| 124 , m_state(NotificationStateIdle) | |
| 125 , m_prepareShowMethodRunner(AsyncMethodRunner<Notification>::create(this, &N
otification::prepareShow)) | |
| 126 { | 126 { |
| 127 DCHECK(notificationManager()); | 127 DCHECK(notificationManager()); |
| 128 } | 128 } |
| 129 | 129 |
| 130 Notification::~Notification() | 130 Notification::~Notification() |
| 131 { | 131 { |
| 132 } | 132 } |
| 133 | 133 |
| 134 void Notification::schedulePrepareShow() | 134 void Notification::schedulePrepareShow() |
| 135 { | 135 { |
| 136 DCHECK_EQ(m_state, NotificationStateIdle); | 136 DCHECK_EQ(m_state, State::Loading); |
| 137 DCHECK(!m_prepareShowMethodRunner->isActive()); | 137 DCHECK(!m_prepareShowMethodRunner); |
| 138 | 138 |
| 139 m_prepareShowMethodRunner = AsyncMethodRunner<Notification>::create(this, &N
otification::prepareShow); |
| 139 m_prepareShowMethodRunner->runAsync(); | 140 m_prepareShowMethodRunner->runAsync(); |
| 140 } | 141 } |
| 141 | 142 |
| 142 void Notification::prepareShow() | 143 void Notification::prepareShow() |
| 143 { | 144 { |
| 144 DCHECK_EQ(m_state, NotificationStateIdle); | 145 DCHECK_EQ(m_state, State::Loading); |
| 145 if (NotificationManager::from(getExecutionContext())->permissionStatus() !=
mojom::blink::PermissionStatus::GRANTED) { | 146 if (NotificationManager::from(getExecutionContext())->permissionStatus() !=
mojom::blink::PermissionStatus::GRANTED) { |
| 146 dispatchErrorEvent(); | 147 dispatchErrorEvent(); |
| 147 return; | 148 return; |
| 148 } | 149 } |
| 149 | 150 |
| 150 m_loader = new NotificationResourcesLoader(WTF::bind(&Notification::didLoadR
esources, wrapWeakPersistent(this))); | 151 m_loader = new NotificationResourcesLoader(WTF::bind(&Notification::didLoadR
esources, wrapWeakPersistent(this))); |
| 151 m_loader->start(getExecutionContext(), m_data); | 152 m_loader->start(getExecutionContext(), m_data); |
| 152 } | 153 } |
| 153 | 154 |
| 154 void Notification::didLoadResources(NotificationResourcesLoader* loader) | 155 void Notification::didLoadResources(NotificationResourcesLoader* loader) |
| 155 { | 156 { |
| 156 DCHECK_EQ(loader, m_loader.get()); | 157 DCHECK_EQ(loader, m_loader.get()); |
| 157 | 158 |
| 158 SecurityOrigin* origin = getExecutionContext()->getSecurityOrigin(); | 159 SecurityOrigin* origin = getExecutionContext()->getSecurityOrigin(); |
| 159 DCHECK(origin); | 160 DCHECK(origin); |
| 160 | 161 |
| 161 notificationManager()->show(WebSecurityOrigin(origin), m_data, loader->getRe
sources(), this); | 162 notificationManager()->show(WebSecurityOrigin(origin), m_data, loader->getRe
sources(), this); |
| 162 m_loader.clear(); | 163 m_loader.clear(); |
| 163 | 164 |
| 164 m_state = NotificationStateShowing; | 165 m_state = State::Showing; |
| 165 } | 166 } |
| 166 | 167 |
| 167 void Notification::close() | 168 void Notification::close() |
| 168 { | 169 { |
| 169 if (m_state != NotificationStateShowing) | 170 if (m_state != State::Showing) |
| 170 return; | 171 return; |
| 171 | 172 |
| 172 if (m_notificationId.isNull()) { | 173 // Schedule the "close" event to be fired for non-persistent notifications. |
| 173 // Fire the close event asynchronously. | 174 // Persistent notifications won't get such events for programmatic closes. |
| 175 if (m_type == Type::NonPersistent) { |
| 174 getExecutionContext()->postTask(BLINK_FROM_HERE, createSameThreadTask(&N
otification::dispatchCloseEvent, wrapPersistent(this))); | 176 getExecutionContext()->postTask(BLINK_FROM_HERE, createSameThreadTask(&N
otification::dispatchCloseEvent, wrapPersistent(this))); |
| 177 m_state = State::Closing; |
| 175 | 178 |
| 176 m_state = NotificationStateClosing; | |
| 177 notificationManager()->close(this); | 179 notificationManager()->close(this); |
| 178 } else { | 180 return; |
| 179 m_state = NotificationStateClosed; | 181 } |
| 180 | 182 |
| 181 SecurityOrigin* origin = getExecutionContext()->getSecurityOrigin(); | 183 m_state = State::Closed; |
| 182 DCHECK(origin); | |
| 183 | 184 |
| 184 notificationManager()->closePersistent(WebSecurityOrigin(origin), m_data
.tag, m_notificationId); | 185 SecurityOrigin* origin = getExecutionContext()->getSecurityOrigin(); |
| 185 } | 186 DCHECK(origin); |
| 187 |
| 188 notificationManager()->closePersistent(WebSecurityOrigin(origin), m_data.tag
, m_notificationId); |
| 186 } | 189 } |
| 187 | 190 |
| 188 void Notification::dispatchShowEvent() | 191 void Notification::dispatchShowEvent() |
| 189 { | 192 { |
| 190 dispatchEvent(Event::create(EventTypeNames::show)); | 193 dispatchEvent(Event::create(EventTypeNames::show)); |
| 191 } | 194 } |
| 192 | 195 |
| 193 void Notification::dispatchClickEvent() | 196 void Notification::dispatchClickEvent() |
| 194 { | 197 { |
| 195 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); | 198 UserGestureIndicator gestureIndicator(DefinitelyProcessingNewUserGesture); |
| 196 ScopedWindowFocusAllowedIndicator windowFocusAllowed(getExecutionContext()); | 199 ScopedWindowFocusAllowedIndicator windowFocusAllowed(getExecutionContext()); |
| 197 dispatchEvent(Event::create(EventTypeNames::click)); | 200 dispatchEvent(Event::create(EventTypeNames::click)); |
| 198 } | 201 } |
| 199 | 202 |
| 200 void Notification::dispatchErrorEvent() | 203 void Notification::dispatchErrorEvent() |
| 201 { | 204 { |
| 202 dispatchEvent(Event::create(EventTypeNames::error)); | 205 dispatchEvent(Event::create(EventTypeNames::error)); |
| 203 } | 206 } |
| 204 | 207 |
| 205 void Notification::dispatchCloseEvent() | 208 void Notification::dispatchCloseEvent() |
| 206 { | 209 { |
| 207 // The notification will be showing when the user initiated the close, or it
will be | 210 // The notification will be showing when the user initiated the close, or it
will be |
| 208 // closing if the developer initiated the close. | 211 // closing if the developer initiated the close. |
| 209 if (m_state != NotificationStateShowing && m_state != NotificationStateClosi
ng) | 212 if (m_state != State::Showing && m_state != State::Closing) |
| 210 return; | 213 return; |
| 211 | 214 |
| 212 m_state = NotificationStateClosed; | 215 m_state = State::Closed; |
| 213 dispatchEvent(Event::create(EventTypeNames::close)); | 216 dispatchEvent(Event::create(EventTypeNames::close)); |
| 214 } | 217 } |
| 215 | 218 |
| 216 String Notification::title() const | 219 String Notification::title() const |
| 217 { | 220 { |
| 218 return m_data.title; | 221 return m_data.title; |
| 219 } | 222 } |
| 220 | 223 |
| 221 String Notification::dir() const | 224 String Notification::dir() const |
| 222 { | 225 { |
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 369 | 372 |
| 370 const AtomicString& Notification::interfaceName() const | 373 const AtomicString& Notification::interfaceName() const |
| 371 { | 374 { |
| 372 return EventTargetNames::Notification; | 375 return EventTargetNames::Notification; |
| 373 } | 376 } |
| 374 | 377 |
| 375 void Notification::stop() | 378 void Notification::stop() |
| 376 { | 379 { |
| 377 notificationManager()->notifyDelegateDestroyed(this); | 380 notificationManager()->notifyDelegateDestroyed(this); |
| 378 | 381 |
| 379 m_state = NotificationStateClosed; | 382 m_state = State::Closed; |
| 380 | 383 |
| 381 m_prepareShowMethodRunner->stop(); | 384 if (m_prepareShowMethodRunner) |
| 385 m_prepareShowMethodRunner->stop(); |
| 382 | 386 |
| 383 if (m_loader) | 387 if (m_loader) |
| 384 m_loader->stop(); | 388 m_loader->stop(); |
| 385 } | 389 } |
| 386 | 390 |
| 387 bool Notification::hasPendingActivity() const | 391 bool Notification::hasPendingActivity() const |
| 388 { | 392 { |
| 389 return m_state == NotificationStateShowing || m_prepareShowMethodRunner->isA
ctive() || m_loader; | 393 // Non-persistent notification can receive events until they've been closed. |
| 394 // Persistent notifications should be subject to regular garbage collection. |
| 395 if (m_type == Type::NonPersistent) |
| 396 return m_state != State::Closed; |
| 397 |
| 398 return false; |
| 390 } | 399 } |
| 391 | 400 |
| 392 DEFINE_TRACE(Notification) | 401 DEFINE_TRACE(Notification) |
| 393 { | 402 { |
| 394 visitor->trace(m_prepareShowMethodRunner); | 403 visitor->trace(m_prepareShowMethodRunner); |
| 395 visitor->trace(m_loader); | 404 visitor->trace(m_loader); |
| 396 EventTargetWithInlineData::trace(visitor); | 405 EventTargetWithInlineData::trace(visitor); |
| 397 ActiveDOMObject::trace(visitor); | 406 ActiveDOMObject::trace(visitor); |
| 398 } | 407 } |
| 399 | 408 |
| 400 } // namespace blink | 409 } // namespace blink |
| OLD | NEW |