Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(105)

Side by Side Diff: Source/core/page/EventSource.cpp

Issue 1264453002: Split the constructor of ThreadableLoader into two methods (ctor and start()) (Closed) Base URL: https://chromium.googlesource.com/chromium/blink.git@master
Patch Set: Addressed #7. Rebased Created 5 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
62 const unsigned long long EventSource::defaultReconnectDelay = 3000; 62 const unsigned long long EventSource::defaultReconnectDelay = 3000;
63 63
64 inline EventSource::EventSource(ExecutionContext* context, const KURL& url, cons t EventSourceInit& eventSourceInit) 64 inline EventSource::EventSource(ExecutionContext* context, const KURL& url, cons t EventSourceInit& eventSourceInit)
65 : ActiveDOMObject(context) 65 : ActiveDOMObject(context)
66 , m_url(url) 66 , m_url(url)
67 , m_withCredentials(eventSourceInit.withCredentials()) 67 , m_withCredentials(eventSourceInit.withCredentials())
68 , m_state(CONNECTING) 68 , m_state(CONNECTING)
69 , m_decoder(TextResourceDecoder::create("text/plain", "UTF-8")) 69 , m_decoder(TextResourceDecoder::create("text/plain", "UTF-8"))
70 , m_connectTimer(this, &EventSource::connectTimerFired) 70 , m_connectTimer(this, &EventSource::connectTimerFired)
71 , m_discardTrailingNewline(false) 71 , m_discardTrailingNewline(false)
72 , m_requestInFlight(false)
73 , m_reconnectDelay(defaultReconnectDelay) 72 , m_reconnectDelay(defaultReconnectDelay)
74 { 73 {
75 } 74 }
76 75
77 EventSource* EventSource::create(ExecutionContext* context, const String& url, c onst EventSourceInit& eventSourceInit, ExceptionState& exceptionState) 76 EventSource* EventSource::create(ExecutionContext* context, const String& url, c onst EventSourceInit& eventSourceInit, ExceptionState& exceptionState)
78 { 77 {
79 if (url.isEmpty()) { 78 if (url.isEmpty()) {
80 exceptionState.throwDOMException(SyntaxError, "Cannot open an EventSourc e to an empty URL."); 79 exceptionState.throwDOMException(SyntaxError, "Cannot open an EventSourc e to an empty URL.");
81 return nullptr; 80 return nullptr;
82 } 81 }
(...skipping 14 matching lines...) Expand all
97 EventSource* source = new EventSource(context, fullURL, eventSourceInit); 96 EventSource* source = new EventSource(context, fullURL, eventSourceInit);
98 97
99 source->scheduleInitialConnect(); 98 source->scheduleInitialConnect();
100 source->suspendIfNeeded(); 99 source->suspendIfNeeded();
101 return source; 100 return source;
102 } 101 }
103 102
104 EventSource::~EventSource() 103 EventSource::~EventSource()
105 { 104 {
106 ASSERT(m_state == CLOSED); 105 ASSERT(m_state == CLOSED);
107 ASSERT(!m_requestInFlight); 106 ASSERT(!m_loader);
108 } 107 }
109 108
110 void EventSource::scheduleInitialConnect() 109 void EventSource::scheduleInitialConnect()
111 { 110 {
112 ASSERT(m_state == CONNECTING); 111 ASSERT(m_state == CONNECTING);
113 ASSERT(!m_requestInFlight); 112 ASSERT(!m_loader);
114 113
115 m_connectTimer.startOneShot(0, FROM_HERE); 114 m_connectTimer.startOneShot(0, FROM_HERE);
116 } 115 }
117 116
118 void EventSource::connect() 117 void EventSource::connect()
119 { 118 {
120 ASSERT(m_state == CONNECTING); 119 ASSERT(m_state == CONNECTING);
121 ASSERT(!m_requestInFlight); 120 ASSERT(!m_loader);
122 ASSERT(executionContext()); 121 ASSERT(executionContext());
123 122
124 ExecutionContext& executionContext = *this->executionContext(); 123 ExecutionContext& executionContext = *this->executionContext();
125 ResourceRequest request(m_url); 124 ResourceRequest request(m_url);
126 request.setHTTPMethod("GET"); 125 request.setHTTPMethod("GET");
127 request.setHTTPHeaderField("Accept", "text/event-stream"); 126 request.setHTTPHeaderField("Accept", "text/event-stream");
128 request.setHTTPHeaderField("Cache-Control", "no-cache"); 127 request.setHTTPHeaderField("Cache-Control", "no-cache");
129 request.setRequestContext(WebURLRequest::RequestContextEventSource); 128 request.setRequestContext(WebURLRequest::RequestContextEventSource);
130 if (!m_lastEventId.isEmpty()) 129 if (!m_lastEventId.isEmpty())
131 request.setHTTPHeaderField("Last-Event-ID", m_lastEventId); 130 request.setHTTPHeaderField("Last-Event-ID", m_lastEventId);
132 131
133 SecurityOrigin* origin = executionContext.securityOrigin(); 132 SecurityOrigin* origin = executionContext.securityOrigin();
134 133
135 ThreadableLoaderOptions options; 134 ThreadableLoaderOptions options;
136 options.preflightPolicy = PreventPreflight; 135 options.preflightPolicy = PreventPreflight;
137 options.crossOriginRequestPolicy = UseAccessControl; 136 options.crossOriginRequestPolicy = UseAccessControl;
138 options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypa ssMainWorld(&executionContext) ? DoNotEnforceContentSecurityPolicy : EnforceConn ectSrcDirective; 137 options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypa ssMainWorld(&executionContext) ? DoNotEnforceContentSecurityPolicy : EnforceConn ectSrcDirective;
139 138
140 ResourceLoaderOptions resourceLoaderOptions; 139 ResourceLoaderOptions resourceLoaderOptions;
141 resourceLoaderOptions.allowCredentials = (origin->canRequest(m_url) || m_wit hCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials; 140 resourceLoaderOptions.allowCredentials = (origin->canRequest(m_url) || m_wit hCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
142 resourceLoaderOptions.credentialsRequested = m_withCredentials ? ClientReque stedCredentials : ClientDidNotRequestCredentials; 141 resourceLoaderOptions.credentialsRequested = m_withCredentials ? ClientReque stedCredentials : ClientDidNotRequestCredentials;
143 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData; 142 resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
144 resourceLoaderOptions.securityOrigin = origin; 143 resourceLoaderOptions.securityOrigin = origin;
145 144
146 InspectorInstrumentation::willSendEventSourceRequest(&executionContext, this ); 145 InspectorInstrumentation::willSendEventSourceRequest(&executionContext, this );
147 // InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient will be called synchronously. 146 // InspectorInstrumentation::documentThreadableLoaderStartedLoadingForClient will be called synchronously.
148 m_loader = ThreadableLoader::create(executionContext, this, request, options , resourceLoaderOptions); 147 m_loader = ThreadableLoader::create(executionContext, this, options, resourc eLoaderOptions);
149 148 m_loader->start(request);
150 if (m_loader)
151 m_requestInFlight = true;
152 } 149 }
153 150
154 void EventSource::networkRequestEnded() 151 void EventSource::networkRequestEnded()
155 { 152 {
156 if (!m_requestInFlight)
157 return;
158
159 InspectorInstrumentation::didFinishEventSourceRequest(executionContext(), th is); 153 InspectorInstrumentation::didFinishEventSourceRequest(executionContext(), th is);
160 154
161 m_requestInFlight = false; 155 m_loader = nullptr;
162 156
163 if (m_state != CLOSED) 157 if (m_state != CLOSED)
164 scheduleReconnect(); 158 scheduleReconnect();
165 } 159 }
166 160
167 void EventSource::scheduleReconnect() 161 void EventSource::scheduleReconnect()
168 { 162 {
169 m_state = CONNECTING; 163 m_state = CONNECTING;
170 m_connectTimer.startOneShot(m_reconnectDelay / 1000.0, FROM_HERE); 164 m_connectTimer.startOneShot(m_reconnectDelay / 1000.0, FROM_HERE);
171 dispatchEvent(Event::create(EventTypeNames::error)); 165 dispatchEvent(Event::create(EventTypeNames::error));
(...skipping 15 matching lines...) Expand all
187 } 181 }
188 182
189 EventSource::State EventSource::readyState() const 183 EventSource::State EventSource::readyState() const
190 { 184 {
191 return m_state; 185 return m_state;
192 } 186 }
193 187
194 void EventSource::close() 188 void EventSource::close()
195 { 189 {
196 if (m_state == CLOSED) { 190 if (m_state == CLOSED) {
197 ASSERT(!m_requestInFlight); 191 ASSERT(!m_loader);
198 return; 192 return;
199 } 193 }
200 194
201 // Stop trying to reconnect if EventSource was explicitly closed or if Activ eDOMObject::stop() was called. 195 // Stop trying to reconnect if EventSource was explicitly closed or if Activ eDOMObject::stop() was called.
202 if (m_connectTimer.isActive()) { 196 if (m_connectTimer.isActive()) {
203 m_connectTimer.stop(); 197 m_connectTimer.stop();
204 } 198 }
205 199
206 if (m_requestInFlight) 200 if (m_loader) {
207 m_loader->cancel(); 201 m_loader->cancel();
202 m_loader = nullptr;
203 }
208 204
209 m_state = CLOSED; 205 m_state = CLOSED;
210 } 206 }
211 207
212 const AtomicString& EventSource::interfaceName() const 208 const AtomicString& EventSource::interfaceName() const
213 { 209 {
214 return EventTargetNames::EventSource; 210 return EventTargetNames::EventSource;
215 } 211 }
216 212
217 ExecutionContext* EventSource::executionContext() const 213 ExecutionContext* EventSource::executionContext() const
218 { 214 {
219 return ActiveDOMObject::executionContext(); 215 return ActiveDOMObject::executionContext();
220 } 216 }
221 217
222 void EventSource::didReceiveResponse(unsigned long, const ResourceResponse& resp onse, PassOwnPtr<WebDataConsumerHandle> handle) 218 void EventSource::didReceiveResponse(unsigned long, const ResourceResponse& resp onse, PassOwnPtr<WebDataConsumerHandle> handle)
223 { 219 {
224 ASSERT_UNUSED(handle, !handle); 220 ASSERT_UNUSED(handle, !handle);
225 ASSERT(m_state == CONNECTING); 221 ASSERT(m_state == CONNECTING);
226 ASSERT(m_requestInFlight); 222 ASSERT(m_loader);
227 223
228 m_eventStreamOrigin = SecurityOrigin::create(response.url())->toString(); 224 m_eventStreamOrigin = SecurityOrigin::create(response.url())->toString();
229 int statusCode = response.httpStatusCode(); 225 int statusCode = response.httpStatusCode();
230 bool mimeTypeIsValid = response.mimeType() == "text/event-stream"; 226 bool mimeTypeIsValid = response.mimeType() == "text/event-stream";
231 bool responseIsValid = statusCode == 200 && mimeTypeIsValid; 227 bool responseIsValid = statusCode == 200 && mimeTypeIsValid;
232 if (responseIsValid) { 228 if (responseIsValid) {
233 const String& charset = response.textEncodingName(); 229 const String& charset = response.textEncodingName();
234 // If we have a charset, the only allowed value is UTF-8 (case-insensiti ve). 230 // If we have a charset, the only allowed value is UTF-8 (case-insensiti ve).
235 responseIsValid = charset.isEmpty() || equalIgnoringCase(charset, "UTF-8 "); 231 responseIsValid = charset.isEmpty() || equalIgnoringCase(charset, "UTF-8 ");
236 if (!responseIsValid) { 232 if (!responseIsValid) {
(...skipping 21 matching lines...) Expand all
258 dispatchEvent(Event::create(EventTypeNames::open)); 254 dispatchEvent(Event::create(EventTypeNames::open));
259 } else { 255 } else {
260 m_loader->cancel(); 256 m_loader->cancel();
261 dispatchEvent(Event::create(EventTypeNames::error)); 257 dispatchEvent(Event::create(EventTypeNames::error));
262 } 258 }
263 } 259 }
264 260
265 void EventSource::didReceiveData(const char* data, unsigned length) 261 void EventSource::didReceiveData(const char* data, unsigned length)
266 { 262 {
267 ASSERT(m_state == OPEN); 263 ASSERT(m_state == OPEN);
268 ASSERT(m_requestInFlight); 264 ASSERT(m_loader);
269 265
270 append(m_receiveBuf, m_decoder->decode(data, length)); 266 append(m_receiveBuf, m_decoder->decode(data, length));
271 parseEventStream(); 267 parseEventStream();
272 } 268 }
273 269
274 void EventSource::didFinishLoading(unsigned long, double) 270 void EventSource::didFinishLoading(unsigned long, double)
275 { 271 {
276 ASSERT(m_state == OPEN); 272 ASSERT(m_state == OPEN);
277 ASSERT(m_requestInFlight); 273 ASSERT(m_loader);
278 274
279 if (m_receiveBuf.size() > 0 || m_data.size() > 0) { 275 if (m_receiveBuf.size() > 0 || m_data.size() > 0) {
280 parseEventStream(); 276 parseEventStream();
281 277
282 // Discard everything that has not been dispatched by now. 278 // Discard everything that has not been dispatched by now.
283 m_receiveBuf.clear(); 279 m_receiveBuf.clear();
284 m_data.clear(); 280 m_data.clear();
285 m_eventName = emptyAtom; 281 m_eventName = emptyAtom;
286 m_currentlyParsedEventId = nullAtom; 282 m_currentlyParsedEventId = nullAtom;
287 } 283 }
288 networkRequestEnded(); 284 networkRequestEnded();
289 } 285 }
290 286
291 void EventSource::didFail(const ResourceError& error) 287 void EventSource::didFail(const ResourceError& error)
292 { 288 {
293 ASSERT(m_state != CLOSED); 289 ASSERT(m_state != CLOSED);
294 ASSERT(m_requestInFlight); 290 ASSERT(m_loader);
295 291
296 if (error.isCancellation()) 292 if (error.isCancellation())
297 m_state = CLOSED; 293 m_state = CLOSED;
298 networkRequestEnded(); 294 networkRequestEnded();
299 } 295 }
300 296
301 void EventSource::didFailAccessControlCheck(const ResourceError& error) 297 void EventSource::didFailAccessControlCheck(const ResourceError& error)
302 { 298 {
303 String message = "EventSource cannot load " + error.failingURL() + ". " + er ror.localizedDescription(); 299 String message = "EventSource cannot load " + error.failingURL() + ". " + er ror.localizedDescription();
304 executionContext()->addConsoleMessage(ConsoleMessage::create(JSMessageSource , ErrorMessageLevel, message)); 300 executionContext()->addConsoleMessage(ConsoleMessage::create(JSMessageSource , ErrorMessageLevel, message));
305 301
306 abortConnectionAttempt(); 302 abortConnectionAttempt();
307 } 303 }
308 304
309 void EventSource::didFailRedirectCheck() 305 void EventSource::didFailRedirectCheck()
310 { 306 {
311 abortConnectionAttempt(); 307 abortConnectionAttempt();
312 } 308 }
313 309
314 void EventSource::abortConnectionAttempt() 310 void EventSource::abortConnectionAttempt()
315 { 311 {
316 ASSERT(m_state == CONNECTING); 312 ASSERT(m_state == CONNECTING);
317 313
318 if (m_requestInFlight) { 314 m_loader = nullptr;
319 m_loader->cancel(); 315 m_state = CLOSED;
320 } else { 316 networkRequestEnded();
321 m_state = CLOSED;
322 }
323
324 ASSERT(m_state == CLOSED);
325 dispatchEvent(Event::create(EventTypeNames::error)); 317 dispatchEvent(Event::create(EventTypeNames::error));
326 } 318 }
327 319
328 void EventSource::parseEventStream() 320 void EventSource::parseEventStream()
329 { 321 {
330 unsigned bufPos = 0; 322 unsigned bufPos = 0;
331 unsigned bufSize = m_receiveBuf.size(); 323 unsigned bufSize = m_receiveBuf.size();
332 while (bufPos < bufSize) { 324 while (bufPos < bufSize) {
333 if (m_discardTrailingNewline) { 325 if (m_discardTrailingNewline) {
334 if (m_receiveBuf[bufPos] == '\n') 326 if (m_receiveBuf[bufPos] == '\n')
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after
416 if (ok) 408 if (ok)
417 m_reconnectDelay = retry; 409 m_reconnectDelay = retry;
418 } 410 }
419 } 411 }
420 } 412 }
421 } 413 }
422 414
423 void EventSource::stop() 415 void EventSource::stop()
424 { 416 {
425 close(); 417 close();
426
427 // (Non)Oilpan: In order to make Worker shutdowns clean,
428 // deref the loader. This will in turn deref its
429 // RefPtr<WorkerGlobalScope>.
430 //
431 // Worth doing regardless, it is no longer of use.
432 m_loader = nullptr;
433 } 418 }
434 419
435 bool EventSource::hasPendingActivity() const 420 bool EventSource::hasPendingActivity() const
436 { 421 {
437 return m_state != CLOSED; 422 return m_state != CLOSED;
438 } 423 }
439 424
440 PassRefPtrWillBeRawPtr<MessageEvent> EventSource::createMessageEvent() 425 PassRefPtrWillBeRawPtr<MessageEvent> EventSource::createMessageEvent()
441 { 426 {
442 RefPtrWillBeRawPtr<MessageEvent> event = MessageEvent::create(); 427 RefPtrWillBeRawPtr<MessageEvent> event = MessageEvent::create();
443 event->initMessageEvent(m_eventName.isEmpty() ? EventTypeNames::message : m_ eventName, false, false, SerializedScriptValueFactory::instance().create(String( m_data)), m_eventStreamOrigin, m_lastEventId, 0, nullptr); 428 event->initMessageEvent(m_eventName.isEmpty() ? EventTypeNames::message : m_ eventName, false, false, SerializedScriptValueFactory::instance().create(String( m_data)), m_eventStreamOrigin, m_lastEventId, 0, nullptr);
444 m_data.clear(); 429 m_data.clear();
445 return event.release(); 430 return event.release();
446 } 431 }
447 432
448 DEFINE_TRACE(EventSource) 433 DEFINE_TRACE(EventSource)
449 { 434 {
450 RefCountedGarbageCollectedEventTargetWithInlineData::trace(visitor); 435 RefCountedGarbageCollectedEventTargetWithInlineData::trace(visitor);
451 ActiveDOMObject::trace(visitor); 436 ActiveDOMObject::trace(visitor);
452 } 437 }
453 438
454 } // namespace blink 439 } // namespace blink
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698