OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2009, 2012 Ericsson AB. All rights reserved. | 2 * Copyright (C) 2009, 2012 Ericsson AB. All rights reserved. |
3 * Copyright (C) 2010 Apple Inc. All rights reserved. | 3 * Copyright (C) 2010 Apple Inc. All rights reserved. |
4 * Copyright (C) 2011, Code Aurora Forum. All rights reserved. | 4 * Copyright (C) 2011, Code Aurora Forum. All rights reserved. |
5 * | 5 * |
6 * Redistribution and use in source and binary forms, with or without | 6 * Redistribution and use in source and binary forms, with or without |
7 * modification, are permitted provided that the following conditions | 7 * modification, are permitted provided that the following conditions |
8 * are met: | 8 * are met: |
9 * | 9 * |
10 * 1. Redistributions of source code must retain the above copyright | 10 * 1. Redistributions of source code must retain the above copyright |
(...skipping 45 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
56 namespace WebCore { | 56 namespace WebCore { |
57 | 57 |
58 const unsigned long long EventSource::defaultReconnectDelay = 3000; | 58 const unsigned long long EventSource::defaultReconnectDelay = 3000; |
59 | 59 |
60 inline EventSource::EventSource(ExecutionContext* context, const KURL& url, cons
t Dictionary& eventSourceInit) | 60 inline EventSource::EventSource(ExecutionContext* context, const KURL& url, cons
t Dictionary& eventSourceInit) |
61 : ActiveDOMObject(context) | 61 : ActiveDOMObject(context) |
62 , m_url(url) | 62 , m_url(url) |
63 , m_withCredentials(false) | 63 , m_withCredentials(false) |
64 , m_state(CONNECTING) | 64 , m_state(CONNECTING) |
65 , m_decoder(TextResourceDecoder::create("text/plain", "UTF-8")) | 65 , m_decoder(TextResourceDecoder::create("text/plain", "UTF-8")) |
66 , m_reconnectTimer(this, &EventSource::reconnectTimerFired) | 66 , m_connectTimer(this, &EventSource::connectTimerFired) |
67 , m_discardTrailingNewline(false) | 67 , m_discardTrailingNewline(false) |
68 , m_requestInFlight(false) | 68 , m_requestInFlight(false) |
69 , m_reconnectDelay(defaultReconnectDelay) | 69 , m_reconnectDelay(defaultReconnectDelay) |
70 { | 70 { |
71 ScriptWrappable::init(this); | 71 ScriptWrappable::init(this); |
72 eventSourceInit.get("withCredentials", m_withCredentials); | 72 eventSourceInit.get("withCredentials", m_withCredentials); |
73 } | 73 } |
74 | 74 |
75 PassRefPtr<EventSource> EventSource::create(ExecutionContext* context, const Str
ing& url, const Dictionary& eventSourceInit, ExceptionState& es) | 75 PassRefPtr<EventSource> EventSource::create(ExecutionContext* context, const Str
ing& url, const Dictionary& eventSourceInit, ExceptionState& es) |
76 { | 76 { |
(...skipping 16 matching lines...) Expand all Loading... |
93 } | 93 } |
94 if (!shouldBypassMainWorldContentSecurityPolicy && !context->contentSecurity
Policy()->allowConnectToSource(fullURL)) { | 94 if (!shouldBypassMainWorldContentSecurityPolicy && !context->contentSecurity
Policy()->allowConnectToSource(fullURL)) { |
95 // We can safely expose the URL to JavaScript, as this exception is gene
rate synchronously before any redirects take place. | 95 // We can safely expose the URL to JavaScript, as this exception is gene
rate synchronously before any redirects take place. |
96 es.throwSecurityError("Refused to connect to '" + fullURL.elidedString()
+ "' because it violates the document's Content Security Policy."); | 96 es.throwSecurityError("Refused to connect to '" + fullURL.elidedString()
+ "' because it violates the document's Content Security Policy."); |
97 return 0; | 97 return 0; |
98 } | 98 } |
99 | 99 |
100 RefPtr<EventSource> source = adoptRef(new EventSource(context, fullURL, even
tSourceInit)); | 100 RefPtr<EventSource> source = adoptRef(new EventSource(context, fullURL, even
tSourceInit)); |
101 | 101 |
102 source->setPendingActivity(source.get()); | 102 source->setPendingActivity(source.get()); |
103 source->connect(); | 103 source->scheduleInitialConnect(); |
104 source->suspendIfNeeded(); | 104 source->suspendIfNeeded(); |
105 | 105 |
106 return source.release(); | 106 return source.release(); |
107 } | 107 } |
108 | 108 |
109 EventSource::~EventSource() | 109 EventSource::~EventSource() |
110 { | 110 { |
111 ASSERT(m_state == CLOSED); | 111 ASSERT(m_state == CLOSED); |
112 ASSERT(!m_requestInFlight); | 112 ASSERT(!m_requestInFlight); |
113 } | 113 } |
114 | 114 |
| 115 void EventSource::scheduleInitialConnect() |
| 116 { |
| 117 ASSERT(m_state == CONNECTING); |
| 118 ASSERT(!m_requestInFlight); |
| 119 |
| 120 m_connectTimer.startOneShot(0); |
| 121 } |
| 122 |
115 void EventSource::connect() | 123 void EventSource::connect() |
116 { | 124 { |
117 ASSERT(m_state == CONNECTING); | 125 ASSERT(m_state == CONNECTING); |
118 ASSERT(!m_requestInFlight); | 126 ASSERT(!m_requestInFlight); |
119 | 127 |
120 ResourceRequest request(m_url); | 128 ResourceRequest request(m_url); |
121 request.setHTTPMethod("GET"); | 129 request.setHTTPMethod("GET"); |
122 request.setHTTPHeaderField("Accept", "text/event-stream"); | 130 request.setHTTPHeaderField("Accept", "text/event-stream"); |
123 request.setHTTPHeaderField("Cache-Control", "no-cache"); | 131 request.setHTTPHeaderField("Cache-Control", "no-cache"); |
124 if (!m_lastEventId.isEmpty()) | 132 if (!m_lastEventId.isEmpty()) |
(...skipping 27 matching lines...) Expand all Loading... |
152 | 160 |
153 if (m_state != CLOSED) | 161 if (m_state != CLOSED) |
154 scheduleReconnect(); | 162 scheduleReconnect(); |
155 else | 163 else |
156 unsetPendingActivity(this); | 164 unsetPendingActivity(this); |
157 } | 165 } |
158 | 166 |
159 void EventSource::scheduleReconnect() | 167 void EventSource::scheduleReconnect() |
160 { | 168 { |
161 m_state = CONNECTING; | 169 m_state = CONNECTING; |
162 m_reconnectTimer.startOneShot(m_reconnectDelay / 1000.0); | 170 m_connectTimer.startOneShot(m_reconnectDelay / 1000.0); |
163 dispatchEvent(Event::create(EventTypeNames::error)); | 171 dispatchEvent(Event::create(EventTypeNames::error)); |
164 } | 172 } |
165 | 173 |
166 void EventSource::reconnectTimerFired(Timer<EventSource>*) | 174 void EventSource::connectTimerFired(Timer<EventSource>*) |
167 { | 175 { |
168 connect(); | 176 connect(); |
169 } | 177 } |
170 | 178 |
171 String EventSource::url() const | 179 String EventSource::url() const |
172 { | 180 { |
173 return m_url.string(); | 181 return m_url.string(); |
174 } | 182 } |
175 | 183 |
176 bool EventSource::withCredentials() const | 184 bool EventSource::withCredentials() const |
177 { | 185 { |
178 return m_withCredentials; | 186 return m_withCredentials; |
179 } | 187 } |
180 | 188 |
181 EventSource::State EventSource::readyState() const | 189 EventSource::State EventSource::readyState() const |
182 { | 190 { |
183 return m_state; | 191 return m_state; |
184 } | 192 } |
185 | 193 |
186 void EventSource::close() | 194 void EventSource::close() |
187 { | 195 { |
188 if (m_state == CLOSED) { | 196 if (m_state == CLOSED) { |
189 ASSERT(!m_requestInFlight); | 197 ASSERT(!m_requestInFlight); |
190 return; | 198 return; |
191 } | 199 } |
192 | 200 |
193 // Stop trying to reconnect if EventSource was explicitly closed or if Activ
eDOMObject::stop() was called. | 201 // Stop trying to reconnect if EventSource was explicitly closed or if Activ
eDOMObject::stop() was called. |
194 if (m_reconnectTimer.isActive()) { | 202 if (m_connectTimer.isActive()) { |
195 m_reconnectTimer.stop(); | 203 m_connectTimer.stop(); |
196 unsetPendingActivity(this); | 204 unsetPendingActivity(this); |
197 } | 205 } |
198 | 206 |
199 if (m_requestInFlight) | 207 if (m_requestInFlight) |
200 m_loader->cancel(); | 208 m_loader->cancel(); |
201 | 209 |
202 m_state = CLOSED; | 210 m_state = CLOSED; |
203 } | 211 } |
204 | 212 |
205 const AtomicString& EventSource::interfaceName() const | 213 const AtomicString& EventSource::interfaceName() const |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
299 } | 307 } |
300 | 308 |
301 void EventSource::didFailRedirectCheck() | 309 void EventSource::didFailRedirectCheck() |
302 { | 310 { |
303 abortConnectionAttempt(); | 311 abortConnectionAttempt(); |
304 } | 312 } |
305 | 313 |
306 void EventSource::abortConnectionAttempt() | 314 void EventSource::abortConnectionAttempt() |
307 { | 315 { |
308 ASSERT(m_state == CONNECTING); | 316 ASSERT(m_state == CONNECTING); |
309 ASSERT(m_requestInFlight); | |
310 | 317 |
311 m_loader->cancel(); | 318 if (m_requestInFlight) { |
| 319 m_loader->cancel(); |
| 320 } else { |
| 321 m_state = CLOSED; |
| 322 unsetPendingActivity(this); |
| 323 } |
312 | 324 |
313 ASSERT(m_state == CLOSED); | 325 ASSERT(m_state == CLOSED); |
314 dispatchEvent(Event::create(EventTypeNames::error)); | 326 dispatchEvent(Event::create(EventTypeNames::error)); |
315 } | 327 } |
316 | 328 |
317 void EventSource::parseEventStream() | 329 void EventSource::parseEventStream() |
318 { | 330 { |
319 unsigned int bufPos = 0; | 331 unsigned int bufPos = 0; |
320 unsigned int bufSize = m_receiveBuf.size(); | 332 unsigned int bufSize = m_receiveBuf.size(); |
321 while (bufPos < bufSize) { | 333 while (bufPos < bufSize) { |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
415 | 427 |
416 PassRefPtr<MessageEvent> EventSource::createMessageEvent() | 428 PassRefPtr<MessageEvent> EventSource::createMessageEvent() |
417 { | 429 { |
418 RefPtr<MessageEvent> event = MessageEvent::create(); | 430 RefPtr<MessageEvent> event = MessageEvent::create(); |
419 event->initMessageEvent(m_eventName.isEmpty() ? EventTypeNames::message : At
omicString(m_eventName), false, false, SerializedScriptValue::create(String(m_da
ta)), m_eventStreamOrigin, m_lastEventId, 0, nullptr); | 431 event->initMessageEvent(m_eventName.isEmpty() ? EventTypeNames::message : At
omicString(m_eventName), false, false, SerializedScriptValue::create(String(m_da
ta)), m_eventStreamOrigin, m_lastEventId, 0, nullptr); |
420 m_data.clear(); | 432 m_data.clear(); |
421 return event.release(); | 433 return event.release(); |
422 } | 434 } |
423 | 435 |
424 } // namespace WebCore | 436 } // namespace WebCore |
OLD | NEW |