| 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 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 61 namespace blink { | 61 namespace blink { |
| 62 | 62 |
| 63 const unsigned long long EventSource::defaultReconnectDelay = 3000; | 63 const unsigned long long EventSource::defaultReconnectDelay = 3000; |
| 64 | 64 |
| 65 inline EventSource::EventSource(ExecutionContext* context, const KURL& url, cons
t EventSourceInit& eventSourceInit) | 65 inline EventSource::EventSource(ExecutionContext* context, const KURL& url, cons
t EventSourceInit& eventSourceInit) |
| 66 : ActiveScriptWrappable(this) | 66 : ActiveScriptWrappable(this) |
| 67 , ActiveDOMObject(context) | 67 , ActiveDOMObject(context) |
| 68 , m_url(url) | 68 , m_url(url) |
| 69 , m_currentURL(url) | 69 , m_currentURL(url) |
| 70 , m_withCredentials(eventSourceInit.withCredentials()) | 70 , m_withCredentials(eventSourceInit.withCredentials()) |
| 71 , m_state(CONNECTING) | 71 , m_state(kConnecting) |
| 72 , m_connectTimer(this, &EventSource::connectTimerFired) | 72 , m_connectTimer(this, &EventSource::connectTimerFired) |
| 73 , m_reconnectDelay(defaultReconnectDelay) | 73 , m_reconnectDelay(defaultReconnectDelay) |
| 74 { | 74 { |
| 75 } | 75 } |
| 76 | 76 |
| 77 EventSource* EventSource::create(ExecutionContext* context, const String& url, c
onst EventSourceInit& eventSourceInit, ExceptionState& exceptionState) | 77 EventSource* EventSource::create(ExecutionContext* context, const String& url, c
onst EventSourceInit& eventSourceInit, ExceptionState& exceptionState) |
| 78 { | 78 { |
| 79 if (context->isDocument()) | 79 if (context->isDocument()) |
| 80 UseCounter::count(toDocument(context), UseCounter::EventSourceDocument); | 80 UseCounter::count(toDocument(context), UseCounter::EventSourceDocument); |
| 81 else | 81 else |
| (...skipping 19 matching lines...) Expand all Loading... |
| 101 | 101 |
| 102 EventSource* source = new EventSource(context, fullURL, eventSourceInit); | 102 EventSource* source = new EventSource(context, fullURL, eventSourceInit); |
| 103 | 103 |
| 104 source->scheduleInitialConnect(); | 104 source->scheduleInitialConnect(); |
| 105 source->suspendIfNeeded(); | 105 source->suspendIfNeeded(); |
| 106 return source; | 106 return source; |
| 107 } | 107 } |
| 108 | 108 |
| 109 EventSource::~EventSource() | 109 EventSource::~EventSource() |
| 110 { | 110 { |
| 111 ASSERT(m_state == CLOSED); | 111 DCHECK_EQ(kClosed, m_state); |
| 112 ASSERT(!m_loader); | 112 DCHECK(!m_loader); |
| 113 } | 113 } |
| 114 | 114 |
| 115 void EventSource::scheduleInitialConnect() | 115 void EventSource::scheduleInitialConnect() |
| 116 { | 116 { |
| 117 ASSERT(m_state == CONNECTING); | 117 DCHECK_EQ(kConnecting, m_state); |
| 118 ASSERT(!m_loader); | 118 DCHECK(!m_loader); |
| 119 | 119 |
| 120 m_connectTimer.startOneShot(0, BLINK_FROM_HERE); | 120 m_connectTimer.startOneShot(0, BLINK_FROM_HERE); |
| 121 } | 121 } |
| 122 | 122 |
| 123 void EventSource::connect() | 123 void EventSource::connect() |
| 124 { | 124 { |
| 125 ASSERT(m_state == CONNECTING); | 125 DCHECK_EQ(kConnecting, m_state); |
| 126 ASSERT(!m_loader); | 126 DCHECK(!m_loader); |
| 127 ASSERT(getExecutionContext()); | 127 DCHECK(getExecutionContext()); |
| 128 | 128 |
| 129 ExecutionContext& executionContext = *this->getExecutionContext(); | 129 ExecutionContext& executionContext = *this->getExecutionContext(); |
| 130 ResourceRequest request(m_currentURL); | 130 ResourceRequest request(m_currentURL); |
| 131 request.setHTTPMethod(HTTPNames::GET); | 131 request.setHTTPMethod(HTTPNames::GET); |
| 132 request.setHTTPHeaderField(HTTPNames::Accept, "text/event-stream"); | 132 request.setHTTPHeaderField(HTTPNames::Accept, "text/event-stream"); |
| 133 request.setHTTPHeaderField(HTTPNames::Cache_Control, "no-cache"); | 133 request.setHTTPHeaderField(HTTPNames::Cache_Control, "no-cache"); |
| 134 request.setRequestContext(WebURLRequest::RequestContextEventSource); | 134 request.setRequestContext(WebURLRequest::RequestContextEventSource); |
| 135 request.setExternalRequestStateFromRequestorAddressSpace(executionContext.se
curityContext().addressSpace()); | 135 request.setExternalRequestStateFromRequestorAddressSpace(executionContext.se
curityContext().addressSpace()); |
| 136 if (m_parser && !m_parser->lastEventId().isEmpty()) { | 136 if (m_parser && !m_parser->lastEventId().isEmpty()) { |
| 137 // HTTP headers are Latin-1 byte strings, but the Last-Event-ID header i
s encoded as UTF-8. | 137 // HTTP headers are Latin-1 byte strings, but the Last-Event-ID header i
s encoded as UTF-8. |
| (...skipping 20 matching lines...) Expand all Loading... |
| 158 m_loader = ThreadableLoader::create(executionContext, this, options, resourc
eLoaderOptions); | 158 m_loader = ThreadableLoader::create(executionContext, this, options, resourc
eLoaderOptions); |
| 159 m_loader->start(request); | 159 m_loader->start(request); |
| 160 } | 160 } |
| 161 | 161 |
| 162 void EventSource::networkRequestEnded() | 162 void EventSource::networkRequestEnded() |
| 163 { | 163 { |
| 164 InspectorInstrumentation::didFinishEventSourceRequest(getExecutionContext(),
this); | 164 InspectorInstrumentation::didFinishEventSourceRequest(getExecutionContext(),
this); |
| 165 | 165 |
| 166 m_loader = nullptr; | 166 m_loader = nullptr; |
| 167 | 167 |
| 168 if (m_state != CLOSED) | 168 if (m_state != kClosed) |
| 169 scheduleReconnect(); | 169 scheduleReconnect(); |
| 170 } | 170 } |
| 171 | 171 |
| 172 void EventSource::scheduleReconnect() | 172 void EventSource::scheduleReconnect() |
| 173 { | 173 { |
| 174 m_state = CONNECTING; | 174 m_state = kConnecting; |
| 175 m_connectTimer.startOneShot(m_reconnectDelay / 1000.0, BLINK_FROM_HERE); | 175 m_connectTimer.startOneShot(m_reconnectDelay / 1000.0, BLINK_FROM_HERE); |
| 176 dispatchEvent(Event::create(EventTypeNames::error)); | 176 dispatchEvent(Event::create(EventTypeNames::error)); |
| 177 } | 177 } |
| 178 | 178 |
| 179 void EventSource::connectTimerFired(TimerBase*) | 179 void EventSource::connectTimerFired(TimerBase*) |
| 180 { | 180 { |
| 181 connect(); | 181 connect(); |
| 182 } | 182 } |
| 183 | 183 |
| 184 String EventSource::url() const | 184 String EventSource::url() const |
| 185 { | 185 { |
| 186 return m_url.getString(); | 186 return m_url.getString(); |
| 187 } | 187 } |
| 188 | 188 |
| 189 bool EventSource::withCredentials() const | 189 bool EventSource::withCredentials() const |
| 190 { | 190 { |
| 191 return m_withCredentials; | 191 return m_withCredentials; |
| 192 } | 192 } |
| 193 | 193 |
| 194 EventSource::State EventSource::readyState() const | 194 EventSource::State EventSource::readyState() const |
| 195 { | 195 { |
| 196 return m_state; | 196 return m_state; |
| 197 } | 197 } |
| 198 | 198 |
| 199 void EventSource::close() | 199 void EventSource::close() |
| 200 { | 200 { |
| 201 if (m_state == CLOSED) { | 201 if (m_state == kClosed) { |
| 202 ASSERT(!m_loader); | 202 DCHECK(!m_loader); |
| 203 return; | 203 return; |
| 204 } | 204 } |
| 205 if (m_parser) | 205 if (m_parser) |
| 206 m_parser->stop(); | 206 m_parser->stop(); |
| 207 | 207 |
| 208 // Stop trying to reconnect if EventSource was explicitly closed or if Activ
eDOMObject::stop() was called. | 208 // Stop trying to reconnect if EventSource was explicitly closed or if Activ
eDOMObject::stop() was called. |
| 209 if (m_connectTimer.isActive()) { | 209 if (m_connectTimer.isActive()) { |
| 210 m_connectTimer.stop(); | 210 m_connectTimer.stop(); |
| 211 } | 211 } |
| 212 | 212 |
| 213 if (m_loader) { | 213 if (m_loader) { |
| 214 m_loader->cancel(); | 214 m_loader->cancel(); |
| 215 m_loader = nullptr; | 215 m_loader = nullptr; |
| 216 } | 216 } |
| 217 | 217 |
| 218 m_state = CLOSED; | 218 m_state = kClosed; |
| 219 } | 219 } |
| 220 | 220 |
| 221 const AtomicString& EventSource::interfaceName() const | 221 const AtomicString& EventSource::interfaceName() const |
| 222 { | 222 { |
| 223 return EventTargetNames::EventSource; | 223 return EventTargetNames::EventSource; |
| 224 } | 224 } |
| 225 | 225 |
| 226 ExecutionContext* EventSource::getExecutionContext() const | 226 ExecutionContext* EventSource::getExecutionContext() const |
| 227 { | 227 { |
| 228 return ActiveDOMObject::getExecutionContext(); | 228 return ActiveDOMObject::getExecutionContext(); |
| 229 } | 229 } |
| 230 | 230 |
| 231 void EventSource::didReceiveResponse(unsigned long, const ResourceResponse& resp
onse, std::unique_ptr<WebDataConsumerHandle> handle) | 231 void EventSource::didReceiveResponse(unsigned long, const ResourceResponse& resp
onse, std::unique_ptr<WebDataConsumerHandle> handle) |
| 232 { | 232 { |
| 233 ASSERT_UNUSED(handle, !handle); | 233 ASSERT_UNUSED(handle, !handle); |
| 234 ASSERT(m_state == CONNECTING); | 234 DCHECK_EQ(kConnecting, m_state); |
| 235 ASSERT(m_loader); | 235 DCHECK(m_loader); |
| 236 | 236 |
| 237 m_currentURL = response.url(); | 237 m_currentURL = response.url(); |
| 238 m_eventStreamOrigin = SecurityOrigin::create(response.url())->toString(); | 238 m_eventStreamOrigin = SecurityOrigin::create(response.url())->toString(); |
| 239 int statusCode = response.httpStatusCode(); | 239 int statusCode = response.httpStatusCode(); |
| 240 bool mimeTypeIsValid = response.mimeType() == "text/event-stream"; | 240 bool mimeTypeIsValid = response.mimeType() == "text/event-stream"; |
| 241 bool responseIsValid = statusCode == 200 && mimeTypeIsValid; | 241 bool responseIsValid = statusCode == 200 && mimeTypeIsValid; |
| 242 if (responseIsValid) { | 242 if (responseIsValid) { |
| 243 const String& charset = response.textEncodingName(); | 243 const String& charset = response.textEncodingName(); |
| 244 // If we have a charset, the only allowed value is UTF-8 (case-insensiti
ve). | 244 // If we have a charset, the only allowed value is UTF-8 (case-insensiti
ve). |
| 245 responseIsValid = charset.isEmpty() || equalIgnoringCase(charset, "UTF-8
"); | 245 responseIsValid = charset.isEmpty() || equalIgnoringCase(charset, "UTF-8
"); |
| (...skipping 11 matching lines...) Expand all Loading... |
| 257 StringBuilder message; | 257 StringBuilder message; |
| 258 message.append("EventSource's response has a MIME type (\""); | 258 message.append("EventSource's response has a MIME type (\""); |
| 259 message.append(response.mimeType()); | 259 message.append(response.mimeType()); |
| 260 message.append("\") that is not \"text/event-stream\". Aborting the
connection."); | 260 message.append("\") that is not \"text/event-stream\". Aborting the
connection."); |
| 261 // FIXME: We are missing the source line. | 261 // FIXME: We are missing the source line. |
| 262 getExecutionContext()->addConsoleMessage(ConsoleMessage::create(JSMe
ssageSource, ErrorMessageLevel, message.toString())); | 262 getExecutionContext()->addConsoleMessage(ConsoleMessage::create(JSMe
ssageSource, ErrorMessageLevel, message.toString())); |
| 263 } | 263 } |
| 264 } | 264 } |
| 265 | 265 |
| 266 if (responseIsValid) { | 266 if (responseIsValid) { |
| 267 m_state = OPEN; | 267 m_state = kOpen; |
| 268 AtomicString lastEventId; | 268 AtomicString lastEventId; |
| 269 if (m_parser) { | 269 if (m_parser) { |
| 270 // The new parser takes over the event ID. | 270 // The new parser takes over the event ID. |
| 271 lastEventId = m_parser->lastEventId(); | 271 lastEventId = m_parser->lastEventId(); |
| 272 } | 272 } |
| 273 m_parser = new EventSourceParser(lastEventId, this); | 273 m_parser = new EventSourceParser(lastEventId, this); |
| 274 dispatchEvent(Event::create(EventTypeNames::open)); | 274 dispatchEvent(Event::create(EventTypeNames::open)); |
| 275 } else { | 275 } else { |
| 276 m_loader->cancel(); | 276 m_loader->cancel(); |
| 277 dispatchEvent(Event::create(EventTypeNames::error)); | 277 dispatchEvent(Event::create(EventTypeNames::error)); |
| 278 } | 278 } |
| 279 } | 279 } |
| 280 | 280 |
| 281 void EventSource::didReceiveData(const char* data, unsigned length) | 281 void EventSource::didReceiveData(const char* data, unsigned length) |
| 282 { | 282 { |
| 283 ASSERT(m_state == OPEN); | 283 DCHECK_EQ(kOpen, m_state); |
| 284 ASSERT(m_loader); | 284 DCHECK(m_loader); |
| 285 ASSERT(m_parser); | 285 DCHECK(m_parser); |
| 286 | 286 |
| 287 m_parser->addBytes(data, length); | 287 m_parser->addBytes(data, length); |
| 288 } | 288 } |
| 289 | 289 |
| 290 void EventSource::didFinishLoading(unsigned long, double) | 290 void EventSource::didFinishLoading(unsigned long, double) |
| 291 { | 291 { |
| 292 ASSERT(m_state == OPEN); | 292 DCHECK_EQ(kOpen, m_state); |
| 293 ASSERT(m_loader); | 293 DCHECK(m_loader); |
| 294 | 294 |
| 295 networkRequestEnded(); | 295 networkRequestEnded(); |
| 296 } | 296 } |
| 297 | 297 |
| 298 void EventSource::didFail(const ResourceError& error) | 298 void EventSource::didFail(const ResourceError& error) |
| 299 { | 299 { |
| 300 ASSERT(m_state != CLOSED); | 300 DCHECK_NE(kClosed, m_state); |
| 301 ASSERT(m_loader); | 301 DCHECK(m_loader); |
| 302 | 302 |
| 303 if (error.isCancellation()) | 303 if (error.isCancellation()) |
| 304 m_state = CLOSED; | 304 m_state = kClosed; |
| 305 networkRequestEnded(); | 305 networkRequestEnded(); |
| 306 } | 306 } |
| 307 | 307 |
| 308 void EventSource::didFailAccessControlCheck(const ResourceError& error) | 308 void EventSource::didFailAccessControlCheck(const ResourceError& error) |
| 309 { | 309 { |
| 310 ASSERT(m_loader); | 310 DCHECK(m_loader); |
| 311 | 311 |
| 312 String message = "EventSource cannot load " + error.failingURL() + ". " + er
ror.localizedDescription(); | 312 String message = "EventSource cannot load " + error.failingURL() + ". " + er
ror.localizedDescription(); |
| 313 getExecutionContext()->addConsoleMessage(ConsoleMessage::create(JSMessageSou
rce, ErrorMessageLevel, message)); | 313 getExecutionContext()->addConsoleMessage(ConsoleMessage::create(JSMessageSou
rce, ErrorMessageLevel, message)); |
| 314 | 314 |
| 315 abortConnectionAttempt(); | 315 abortConnectionAttempt(); |
| 316 } | 316 } |
| 317 | 317 |
| 318 void EventSource::didFailRedirectCheck() | 318 void EventSource::didFailRedirectCheck() |
| 319 { | 319 { |
| 320 ASSERT(m_loader); | 320 DCHECK(m_loader); |
| 321 | 321 |
| 322 abortConnectionAttempt(); | 322 abortConnectionAttempt(); |
| 323 } | 323 } |
| 324 | 324 |
| 325 void EventSource::onMessageEvent(const AtomicString& eventType, const String& da
ta, const AtomicString& lastEventId) | 325 void EventSource::onMessageEvent(const AtomicString& eventType, const String& da
ta, const AtomicString& lastEventId) |
| 326 { | 326 { |
| 327 MessageEvent* e = MessageEvent::create(); | 327 MessageEvent* e = MessageEvent::create(); |
| 328 e->initMessageEvent(eventType, false, false, SerializedScriptValue::serializ
e(data), m_eventStreamOrigin, lastEventId, 0, nullptr); | 328 e->initMessageEvent(eventType, false, false, SerializedScriptValue::serializ
e(data), m_eventStreamOrigin, lastEventId, 0, nullptr); |
| 329 | 329 |
| 330 InspectorInstrumentation::willDispatchEventSourceEvent(getExecutionContext()
, this, eventType, lastEventId, data); | 330 InspectorInstrumentation::willDispatchEventSourceEvent(getExecutionContext()
, this, eventType, lastEventId, data); |
| 331 dispatchEvent(e); | 331 dispatchEvent(e); |
| 332 } | 332 } |
| 333 | 333 |
| 334 void EventSource::onReconnectionTimeSet(unsigned long long reconnectionTime) | 334 void EventSource::onReconnectionTimeSet(unsigned long long reconnectionTime) |
| 335 { | 335 { |
| 336 m_reconnectDelay = reconnectionTime; | 336 m_reconnectDelay = reconnectionTime; |
| 337 } | 337 } |
| 338 | 338 |
| 339 void EventSource::abortConnectionAttempt() | 339 void EventSource::abortConnectionAttempt() |
| 340 { | 340 { |
| 341 ASSERT(m_state == CONNECTING); | 341 DCHECK_EQ(kConnecting, m_state); |
| 342 | 342 |
| 343 m_loader = nullptr; | 343 m_loader = nullptr; |
| 344 m_state = CLOSED; | 344 m_state = kClosed; |
| 345 networkRequestEnded(); | 345 networkRequestEnded(); |
| 346 | 346 |
| 347 dispatchEvent(Event::create(EventTypeNames::error)); | 347 dispatchEvent(Event::create(EventTypeNames::error)); |
| 348 } | 348 } |
| 349 | 349 |
| 350 void EventSource::stop() | 350 void EventSource::stop() |
| 351 { | 351 { |
| 352 close(); | 352 close(); |
| 353 } | 353 } |
| 354 | 354 |
| 355 bool EventSource::hasPendingActivity() const | 355 bool EventSource::hasPendingActivity() const |
| 356 { | 356 { |
| 357 return m_state != CLOSED; | 357 return m_state != kClosed; |
| 358 } | 358 } |
| 359 | 359 |
| 360 DEFINE_TRACE(EventSource) | 360 DEFINE_TRACE(EventSource) |
| 361 { | 361 { |
| 362 visitor->trace(m_parser); | 362 visitor->trace(m_parser); |
| 363 EventTargetWithInlineData::trace(visitor); | 363 EventTargetWithInlineData::trace(visitor); |
| 364 ActiveDOMObject::trace(visitor); | 364 ActiveDOMObject::trace(visitor); |
| 365 EventSourceParser::Client::trace(visitor); | 365 EventSourceParser::Client::trace(visitor); |
| 366 } | 366 } |
| 367 | 367 |
| 368 } // namespace blink | 368 } // namespace blink |
| OLD | NEW |