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 |