Upstream version 11.39.266.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / core / xml / XMLHttpRequest.cpp
1 /*
2  *  Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved.
3  *  Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org>
4  *  Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix@webkit.org>
5  *  Copyright (C) 2008, 2011 Google Inc. All rights reserved.
6  *  Copyright (C) 2012 Intel Corporation
7  *
8  *  This library is free software; you can redistribute it and/or
9  *  modify it under the terms of the GNU Lesser General Public
10  *  License as published by the Free Software Foundation; either
11  *  version 2 of the License, or (at your option) any later version.
12  *
13  *  This library is distributed in the hope that it will be useful,
14  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  *  Lesser General Public License for more details.
17  *
18  *  You should have received a copy of the GNU Lesser General Public
19  *  License along with this library; if not, write to the Free Software
20  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
21  */
22
23 #include "config.h"
24 #include "core/xml/XMLHttpRequest.h"
25
26 #include "bindings/core/v8/ExceptionState.h"
27 #include "core/FetchInitiatorTypeNames.h"
28 #include "core/dom/ContextFeatures.h"
29 #include "core/dom/DOMException.h"
30 #include "core/dom/DOMImplementation.h"
31 #include "core/dom/DocumentParser.h"
32 #include "core/dom/ExceptionCode.h"
33 #include "core/dom/XMLDocument.h"
34 #include "core/editing/markup.h"
35 #include "core/events/Event.h"
36 #include "core/fetch/FetchUtils.h"
37 #include "core/fileapi/Blob.h"
38 #include "core/fileapi/File.h"
39 #include "core/frame/Settings.h"
40 #include "core/frame/UseCounter.h"
41 #include "core/frame/csp/ContentSecurityPolicy.h"
42 #include "core/html/DOMFormData.h"
43 #include "core/html/HTMLDocument.h"
44 #include "core/html/parser/TextResourceDecoder.h"
45 #include "core/inspector/ConsoleMessage.h"
46 #include "core/inspector/InspectorInstrumentation.h"
47 #include "core/inspector/InspectorTraceEvents.h"
48 #include "core/loader/ThreadableLoader.h"
49 #include "core/streams/ReadableStream.h"
50 #include "core/streams/ReadableStreamImpl.h"
51 #include "core/streams/Stream.h"
52 #include "core/streams/UnderlyingSource.h"
53 #include "core/xml/XMLHttpRequestProgressEvent.h"
54 #include "core/xml/XMLHttpRequestUpload.h"
55 #include "platform/Logging.h"
56 #include "platform/RuntimeEnabledFeatures.h"
57 #include "platform/SharedBuffer.h"
58 #include "platform/blob/BlobData.h"
59 #include "platform/network/HTTPParsers.h"
60 #include "platform/network/ParsedContentType.h"
61 #include "platform/network/ResourceError.h"
62 #include "platform/network/ResourceRequest.h"
63 #include "public/platform/WebURLRequest.h"
64 #include "wtf/ArrayBuffer.h"
65 #include "wtf/ArrayBufferView.h"
66 #include "wtf/Assertions.h"
67 #include "wtf/RefCountedLeakCounter.h"
68 #include "wtf/StdLibExtras.h"
69 #include "wtf/text/CString.h"
70
71 namespace blink {
72
73 DEFINE_DEBUG_ONLY_GLOBAL(WTF::RefCountedLeakCounter, xmlHttpRequestCounter, ("XMLHttpRequest"));
74
75 static bool isSetCookieHeader(const AtomicString& name)
76 {
77     return equalIgnoringCase(name, "set-cookie") || equalIgnoringCase(name, "set-cookie2");
78 }
79
80 static void replaceCharsetInMediaType(String& mediaType, const String& charsetValue)
81 {
82     unsigned pos = 0, len = 0;
83
84     findCharsetInMediaType(mediaType, pos, len);
85
86     if (!len) {
87         // When no charset found, do nothing.
88         return;
89     }
90
91     // Found at least one existing charset, replace all occurrences with new charset.
92     while (len) {
93         mediaType.replace(pos, len, charsetValue);
94         unsigned start = pos + charsetValue.length();
95         findCharsetInMediaType(mediaType, pos, len, start);
96     }
97 }
98
99 static void logConsoleError(ExecutionContext* context, const String& message)
100 {
101     if (!context)
102         return;
103     // FIXME: It's not good to report the bad usage without indicating what source line it came from.
104     // We should pass additional parameters so we can tell the console where the mistake occurred.
105     context->addConsoleMessage(ConsoleMessage::create(JSMessageSource, ErrorMessageLevel, message));
106 }
107
108 namespace {
109
110 class ReadableStreamSource : public GarbageCollectedFinalized<ReadableStreamSource>, public UnderlyingSource {
111     USING_GARBAGE_COLLECTED_MIXIN(ReadableStreamSource);
112 public:
113     ReadableStreamSource(XMLHttpRequest* owner) : m_owner(owner) { }
114     virtual ~ReadableStreamSource() { }
115     virtual void pullSource() OVERRIDE { }
116     virtual ScriptPromise cancelSource(ScriptState* scriptState, ScriptValue reason) OVERRIDE
117     {
118         m_owner->abort();
119         return ScriptPromise::cast(scriptState, v8::Undefined(scriptState->isolate()));
120     }
121     virtual void trace(Visitor* visitor) OVERRIDE
122     {
123         visitor->trace(m_owner);
124         UnderlyingSource::trace(visitor);
125     }
126
127 private:
128     // This is RawPtr in non-oilpan build to avoid the reference cycle. To
129     // avoid use-after free, the associated ReadableStream must be closed
130     // or errored when m_owner is gone.
131     RawPtrWillBeMember<XMLHttpRequest> m_owner;
132 };
133
134 } // namespace
135
136 PassRefPtrWillBeRawPtr<XMLHttpRequest> XMLHttpRequest::create(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin)
137 {
138     RefPtrWillBeRawPtr<XMLHttpRequest> xmlHttpRequest = adoptRefWillBeNoop(new XMLHttpRequest(context, securityOrigin));
139     xmlHttpRequest->suspendIfNeeded();
140
141     return xmlHttpRequest.release();
142 }
143
144 XMLHttpRequest::XMLHttpRequest(ExecutionContext* context, PassRefPtr<SecurityOrigin> securityOrigin)
145     : ActiveDOMObject(context)
146     , m_timeoutMilliseconds(0)
147     , m_loaderIdentifier(0)
148     , m_state(UNSENT)
149     , m_lengthDownloadedToFile(0)
150     , m_receivedLength(0)
151     , m_lastSendLineNumber(0)
152     , m_exceptionCode(0)
153     , m_progressEventThrottle(this)
154     , m_responseTypeCode(ResponseTypeDefault)
155     , m_securityOrigin(securityOrigin)
156     , m_async(true)
157     , m_includeCredentials(false)
158     , m_parsedResponse(false)
159     , m_error(false)
160     , m_uploadEventsAllowed(true)
161     , m_uploadComplete(false)
162     , m_sameOriginRequest(true)
163     , m_downloadingToFile(false)
164 {
165 #ifndef NDEBUG
166     xmlHttpRequestCounter.increment();
167 #endif
168 }
169
170 XMLHttpRequest::~XMLHttpRequest()
171 {
172 #ifndef NDEBUG
173     xmlHttpRequestCounter.decrement();
174 #endif
175 }
176
177 Document* XMLHttpRequest::document() const
178 {
179     ASSERT(executionContext()->isDocument());
180     return toDocument(executionContext());
181 }
182
183 SecurityOrigin* XMLHttpRequest::securityOrigin() const
184 {
185     return m_securityOrigin ? m_securityOrigin.get() : executionContext()->securityOrigin();
186 }
187
188 XMLHttpRequest::State XMLHttpRequest::readyState() const
189 {
190     return m_state;
191 }
192
193 ScriptString XMLHttpRequest::responseText(ExceptionState& exceptionState)
194 {
195     if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeText) {
196         exceptionState.throwDOMException(InvalidStateError, "The value is only accessible if the object's 'responseType' is '' or 'text' (was '" + responseType() + "').");
197         return ScriptString();
198     }
199     if (m_error || (m_state != LOADING && m_state != DONE))
200         return ScriptString();
201     return m_responseText;
202 }
203
204 ScriptString XMLHttpRequest::responseJSONSource()
205 {
206     ASSERT(m_responseTypeCode == ResponseTypeJSON);
207
208     if (m_error || m_state != DONE)
209         return ScriptString();
210     return m_responseText;
211 }
212
213 void XMLHttpRequest::initResponseDocument()
214 {
215     // The W3C spec requires the final MIME type to be some valid XML type, or text/html.
216     // If it is text/html, then the responseType of "document" must have been supplied explicitly.
217     bool isHTML = responseIsHTML();
218     if ((m_response.isHTTP() && !responseIsXML() && !isHTML)
219         || (isHTML && m_responseTypeCode == ResponseTypeDefault)
220         || executionContext()->isWorkerGlobalScope()) {
221         m_responseDocument = nullptr;
222         return;
223     }
224
225     DocumentInit init = DocumentInit::fromContext(document()->contextDocument(), m_url);
226     if (isHTML)
227         m_responseDocument = HTMLDocument::create(init);
228     else
229         m_responseDocument = XMLDocument::create(init);
230
231     // FIXME: Set Last-Modified.
232     m_responseDocument->setSecurityOrigin(securityOrigin());
233     m_responseDocument->setContextFeatures(document()->contextFeatures());
234     m_responseDocument->setMimeType(finalResponseMIMETypeWithFallback());
235 }
236
237 Document* XMLHttpRequest::responseXML(ExceptionState& exceptionState)
238 {
239     if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != ResponseTypeDocument) {
240         exceptionState.throwDOMException(InvalidStateError, "The value is only accessible if the object's 'responseType' is '' or 'document' (was '" + responseType() + "').");
241         return 0;
242     }
243
244     if (m_error || m_state != DONE)
245         return 0;
246
247     if (!m_parsedResponse) {
248         initResponseDocument();
249         if (!m_responseDocument)
250             return nullptr;
251
252         m_responseDocument->setContent(m_responseText.flattenToString());
253         if (!m_responseDocument->wellFormed())
254             m_responseDocument = nullptr;
255
256         m_parsedResponse = true;
257     }
258
259     return m_responseDocument.get();
260 }
261
262 Blob* XMLHttpRequest::responseBlob()
263 {
264     ASSERT(m_responseTypeCode == ResponseTypeBlob);
265
266     // We always return null before DONE.
267     if (m_error || m_state != DONE)
268         return 0;
269
270     if (!m_responseBlob) {
271         OwnPtr<BlobData> blobData = BlobData::create();
272         if (m_downloadingToFile) {
273             ASSERT(!m_binaryResponseBuilder.get());
274
275             // When responseType is set to "blob", we redirect the downloaded
276             // data to a file-handle directly in the browser process. We get
277             // the file-path from the ResourceResponse directly instead of
278             // copying the bytes between the browser and the renderer.
279             String filePath = m_response.downloadedFilePath();
280             // If we errored out or got no data, we still return a blob, just
281             // an empty one.
282             if (!filePath.isEmpty() && m_lengthDownloadedToFile) {
283                 blobData->appendFile(filePath);
284                 // FIXME: finalResponseMIMETypeWithFallback() defaults to
285                 // text/xml which may be incorrect. Replace it with
286                 // finalResponseMIMEType() after compatibility investigation.
287                 blobData->setContentType(finalResponseMIMETypeWithFallback());
288             }
289             m_responseBlob = Blob::create(BlobDataHandle::create(blobData.release(), m_lengthDownloadedToFile));
290         } else {
291             size_t size = 0;
292             if (m_binaryResponseBuilder.get() && m_binaryResponseBuilder->size()) {
293                 size = m_binaryResponseBuilder->size();
294                 blobData->appendBytes(m_binaryResponseBuilder->data(), size);
295                 blobData->setContentType(finalResponseMIMETypeWithFallback());
296                 m_binaryResponseBuilder.clear();
297             }
298             m_responseBlob = Blob::create(BlobDataHandle::create(blobData.release(), size));
299         }
300     }
301
302     return m_responseBlob.get();
303 }
304
305 ArrayBuffer* XMLHttpRequest::responseArrayBuffer()
306 {
307     ASSERT(m_responseTypeCode == ResponseTypeArrayBuffer);
308
309     if (m_error || m_state != DONE)
310         return 0;
311
312     if (!m_responseArrayBuffer.get()) {
313         if (m_binaryResponseBuilder.get() && m_binaryResponseBuilder->size() > 0) {
314             m_responseArrayBuffer = m_binaryResponseBuilder->getAsArrayBuffer();
315             if (!m_responseArrayBuffer) {
316                 // m_binaryResponseBuilder failed to allocate an ArrayBuffer.
317                 // We need to crash the renderer since there's no way defined in
318                 // the spec to tell this to the user.
319                 CRASH();
320             }
321             m_binaryResponseBuilder.clear();
322         } else {
323             m_responseArrayBuffer = ArrayBuffer::create(static_cast<void*>(0), 0);
324         }
325     }
326
327     return m_responseArrayBuffer.get();
328 }
329
330 Stream* XMLHttpRequest::responseLegacyStream()
331 {
332     ASSERT(m_responseTypeCode == ResponseTypeLegacyStream);
333
334     if (m_error || (m_state != LOADING && m_state != DONE))
335         return 0;
336
337     return m_responseLegacyStream.get();
338 }
339
340 ReadableStream* XMLHttpRequest::responseStream()
341 {
342     ASSERT(m_responseTypeCode == ResponseTypeStream);
343     if (m_error || (m_state != LOADING && m_state != DONE))
344         return 0;
345
346     return m_responseStream;
347 }
348
349 void XMLHttpRequest::setTimeout(unsigned long timeout, ExceptionState& exceptionState)
350 {
351     // FIXME: Need to trigger or update the timeout Timer here, if needed. http://webkit.org/b/98156
352     // XHR2 spec, 4.7.3. "This implies that the timeout attribute can be set while fetching is in progress. If that occurs it will still be measured relative to the start of fetching."
353     if (executionContext()->isDocument() && !m_async) {
354         exceptionState.throwDOMException(InvalidAccessError, "Timeouts cannot be set for synchronous requests made from a document.");
355         return;
356     }
357
358     m_timeoutMilliseconds = timeout;
359
360     // From http://www.w3.org/TR/XMLHttpRequest/#the-timeout-attribute:
361     // Note: This implies that the timeout attribute can be set while fetching is in progress. If
362     // that occurs it will still be measured relative to the start of fetching.
363     //
364     // The timeout may be overridden after send.
365     if (m_loader)
366         m_loader->overrideTimeout(timeout);
367 }
368
369 void XMLHttpRequest::setResponseType(const String& responseType, ExceptionState& exceptionState)
370 {
371     if (m_state >= LOADING) {
372         exceptionState.throwDOMException(InvalidStateError, "The response type cannot be set if the object's state is LOADING or DONE.");
373         return;
374     }
375
376     // Newer functionality is not available to synchronous requests in window contexts, as a spec-mandated
377     // attempt to discourage synchronous XHR use. responseType is one such piece of functionality.
378     if (!m_async && executionContext()->isDocument()) {
379         exceptionState.throwDOMException(InvalidAccessError, "The response type cannot be changed for synchronous requests made from a document.");
380         return;
381     }
382
383     if (responseType == "") {
384         m_responseTypeCode = ResponseTypeDefault;
385     } else if (responseType == "text") {
386         m_responseTypeCode = ResponseTypeText;
387     } else if (responseType == "json") {
388         m_responseTypeCode = ResponseTypeJSON;
389     } else if (responseType == "document") {
390         m_responseTypeCode = ResponseTypeDocument;
391     } else if (responseType == "blob") {
392         m_responseTypeCode = ResponseTypeBlob;
393     } else if (responseType == "arraybuffer") {
394         m_responseTypeCode = ResponseTypeArrayBuffer;
395     } else if (responseType == "legacystream") {
396         if (RuntimeEnabledFeatures::streamEnabled())
397             m_responseTypeCode = ResponseTypeLegacyStream;
398         else
399             return;
400     } else if (responseType == "stream") {
401         if (RuntimeEnabledFeatures::streamEnabled())
402             m_responseTypeCode = ResponseTypeStream;
403         else
404             return;
405     } else {
406         ASSERT_NOT_REACHED();
407     }
408 }
409
410 String XMLHttpRequest::responseType()
411 {
412     switch (m_responseTypeCode) {
413     case ResponseTypeDefault:
414         return "";
415     case ResponseTypeText:
416         return "text";
417     case ResponseTypeJSON:
418         return "json";
419     case ResponseTypeDocument:
420         return "document";
421     case ResponseTypeBlob:
422         return "blob";
423     case ResponseTypeArrayBuffer:
424         return "arraybuffer";
425     case ResponseTypeLegacyStream:
426         return "legacystream";
427     case ResponseTypeStream:
428         return "stream";
429     }
430     return "";
431 }
432
433 String XMLHttpRequest::responseURL()
434 {
435     return m_response.url().string();
436 }
437
438 XMLHttpRequestUpload* XMLHttpRequest::upload()
439 {
440     if (!m_upload)
441         m_upload = XMLHttpRequestUpload::create(this);
442     return m_upload.get();
443 }
444
445 void XMLHttpRequest::trackProgress(int length)
446 {
447     m_receivedLength += length;
448
449     if (m_state != LOADING) {
450         changeState(LOADING);
451     } else {
452         // Dispatch a readystatechange event because many applications use
453         // it to track progress although this is not specified.
454         //
455         // FIXME: Stop dispatching this event for progress tracking.
456         dispatchReadyStateChangeEvent();
457     }
458     if (m_async)
459         dispatchProgressEventFromSnapshot(EventTypeNames::progress);
460 }
461
462 void XMLHttpRequest::changeState(State newState)
463 {
464     if (m_state != newState) {
465         m_state = newState;
466         dispatchReadyStateChangeEvent();
467     }
468 }
469
470 void XMLHttpRequest::dispatchReadyStateChangeEvent()
471 {
472     if (!executionContext())
473         return;
474
475     InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRReadyStateChangeEvent(executionContext(), this);
476
477     if (m_async || (m_state <= OPENED || m_state == DONE)) {
478         TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "XHRReadyStateChange", "data", InspectorXhrReadyStateChangeEvent::data(executionContext(), this));
479         TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
480         XMLHttpRequestProgressEventThrottle::DeferredEventAction action = XMLHttpRequestProgressEventThrottle::Ignore;
481         if (m_state == DONE) {
482             if (m_error)
483                 action = XMLHttpRequestProgressEventThrottle::Clear;
484             else
485                 action = XMLHttpRequestProgressEventThrottle::Flush;
486         }
487         m_progressEventThrottle.dispatchReadyStateChangeEvent(Event::create(EventTypeNames::readystatechange), action);
488         TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());
489     }
490
491     InspectorInstrumentation::didDispatchXHRReadyStateChangeEvent(cookie);
492     if (m_state == DONE && !m_error) {
493         {
494             TRACE_EVENT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "XHRLoad", "data", InspectorXhrLoadEvent::data(executionContext(), this));
495             TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline.stack"), "CallStack", "stack", InspectorCallStackEvent::currentCallStack());
496             InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDispatchXHRLoadEvent(executionContext(), this);
497             dispatchProgressEventFromSnapshot(EventTypeNames::load);
498             InspectorInstrumentation::didDispatchXHRLoadEvent(cookie);
499         }
500         dispatchProgressEventFromSnapshot(EventTypeNames::loadend);
501         TRACE_EVENT_INSTANT1(TRACE_DISABLED_BY_DEFAULT("devtools.timeline"), "UpdateCounters", "data", InspectorUpdateCountersEvent::data());
502     }
503 }
504
505 void XMLHttpRequest::setWithCredentials(bool value, ExceptionState& exceptionState)
506 {
507     if (m_state > OPENED || m_loader) {
508         exceptionState.throwDOMException(InvalidStateError,  "The value may only be set if the object's state is UNSENT or OPENED.");
509         return;
510     }
511
512     // FIXME: According to XMLHttpRequest Level 2 we should throw InvalidAccessError exception here.
513     // However for time being only print warning message to warn web developers.
514     if (!m_async)
515         UseCounter::countDeprecation(executionContext(), UseCounter::SyncXHRWithCredentials);
516
517     m_includeCredentials = value;
518 }
519
520 AtomicString XMLHttpRequest::uppercaseKnownHTTPMethod(const AtomicString& method)
521 {
522     // Valid methods per step-5 of http://xhr.spec.whatwg.org/#the-open()-method.
523     const char* const methods[] = {
524         "DELETE",
525         "GET",
526         "HEAD",
527         "OPTIONS",
528         "POST",
529         "PUT" };
530
531     for (unsigned i = 0; i < WTF_ARRAY_LENGTH(methods); ++i) {
532         if (equalIgnoringCase(method, methods[i])) {
533             // Don't bother allocating a new string if it's already all uppercase.
534             if (method == methods[i])
535                 return method;
536             return methods[i];
537         }
538     }
539     return method;
540 }
541
542 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, ExceptionState& exceptionState)
543 {
544     open(method, url, true, exceptionState);
545 }
546
547 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool async, ExceptionState& exceptionState)
548 {
549     WTF_LOG(Network, "XMLHttpRequest %p open('%s', '%s', %d)", this, method.utf8().data(), url.elidedString().utf8().data(), async);
550
551     if (!internalAbort())
552         return;
553
554     State previousState = m_state;
555     m_state = UNSENT;
556     m_error = false;
557     m_uploadComplete = false;
558
559     if (!isValidHTTPToken(method)) {
560         exceptionState.throwDOMException(SyntaxError, "'" + method + "' is not a valid HTTP method.");
561         return;
562     }
563
564     if (FetchUtils::isForbiddenMethod(method)) {
565         exceptionState.throwSecurityError("'" + method + "' HTTP method is unsupported.");
566         return;
567     }
568
569     if (!ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) && !executionContext()->contentSecurityPolicy()->allowConnectToSource(url)) {
570         // We can safely expose the URL to JavaScript, as these checks happen synchronously before redirection. JavaScript receives no new information.
571         exceptionState.throwSecurityError("Refused to connect to '" + url.elidedString() + "' because it violates the document's Content Security Policy.");
572         return;
573     }
574
575     if (!async && executionContext()->isDocument()) {
576         if (document()->settings() && !document()->settings()->syncXHRInDocumentsEnabled()) {
577             exceptionState.throwDOMException(InvalidAccessError, "Synchronous requests are disabled for this page.");
578             return;
579         }
580
581         // Newer functionality is not available to synchronous requests in window contexts, as a spec-mandated
582         // attempt to discourage synchronous XHR use. responseType is one such piece of functionality.
583         if (m_responseTypeCode != ResponseTypeDefault) {
584             exceptionState.throwDOMException(InvalidAccessError, "Synchronous requests from a document must not set a response type.");
585             return;
586         }
587
588         // Similarly, timeouts are disabled for synchronous requests as well.
589         if (m_timeoutMilliseconds > 0) {
590             exceptionState.throwDOMException(InvalidAccessError, "Synchronous requests must not set a timeout.");
591             return;
592         }
593     }
594
595     m_method = uppercaseKnownHTTPMethod(method);
596
597     m_url = url;
598
599     m_async = async;
600
601     ASSERT(!m_loader);
602
603     // Check previous state to avoid dispatching readyState event
604     // when calling open several times in a row.
605     if (previousState != OPENED)
606         changeState(OPENED);
607     else
608         m_state = OPENED;
609 }
610
611 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool async, const String& user, ExceptionState& exceptionState)
612 {
613     KURL urlWithCredentials(url);
614     urlWithCredentials.setUser(user);
615
616     open(method, urlWithCredentials, async, exceptionState);
617 }
618
619 void XMLHttpRequest::open(const AtomicString& method, const KURL& url, bool async, const String& user, const String& password, ExceptionState& exceptionState)
620 {
621     KURL urlWithCredentials(url);
622     urlWithCredentials.setUser(user);
623     urlWithCredentials.setPass(password);
624
625     open(method, urlWithCredentials, async, exceptionState);
626 }
627
628 bool XMLHttpRequest::initSend(ExceptionState& exceptionState)
629 {
630     if (!executionContext())
631         return false;
632
633     if (m_state != OPENED || m_loader) {
634         exceptionState.throwDOMException(InvalidStateError, "The object's state must be OPENED.");
635         return false;
636     }
637
638     m_error = false;
639     return true;
640 }
641
642 void XMLHttpRequest::send(ExceptionState& exceptionState)
643 {
644     send(String(), exceptionState);
645 }
646
647 bool XMLHttpRequest::areMethodAndURLValidForSend()
648 {
649     return m_method != "GET" && m_method != "HEAD" && m_url.protocolIsInHTTPFamily();
650 }
651
652 void XMLHttpRequest::send(Document* document, ExceptionState& exceptionState)
653 {
654     WTF_LOG(Network, "XMLHttpRequest %p send() Document %p", this, document);
655
656     ASSERT(document);
657
658     if (!initSend(exceptionState))
659         return;
660
661     RefPtr<FormData> httpBody;
662
663     if (areMethodAndURLValidForSend()) {
664         if (getRequestHeader("Content-Type").isEmpty()) {
665             // FIXME: this should include the charset used for encoding.
666             setRequestHeaderInternal("Content-Type", "application/xml");
667         }
668
669         // FIXME: According to XMLHttpRequest Level 2, this should use the Document.innerHTML algorithm
670         // from the HTML5 specification to serialize the document.
671         String body = createMarkup(document);
672
673         // FIXME: This should use value of document.inputEncoding to determine the encoding to use.
674         httpBody = FormData::create(UTF8Encoding().encode(body, WTF::EntitiesForUnencodables));
675         if (m_upload)
676             httpBody->setAlwaysStream(true);
677     }
678
679     createRequest(httpBody.release(), exceptionState);
680 }
681
682 void XMLHttpRequest::send(const String& body, ExceptionState& exceptionState)
683 {
684     WTF_LOG(Network, "XMLHttpRequest %p send() String '%s'", this, body.utf8().data());
685
686     if (!initSend(exceptionState))
687         return;
688
689     RefPtr<FormData> httpBody;
690
691     if (!body.isNull() && areMethodAndURLValidForSend()) {
692         String contentType = getRequestHeader("Content-Type");
693         if (contentType.isEmpty()) {
694             setRequestHeaderInternal("Content-Type", "text/plain;charset=UTF-8");
695         } else {
696             replaceCharsetInMediaType(contentType, "UTF-8");
697             m_requestHeaders.set("Content-Type", AtomicString(contentType));
698         }
699
700         httpBody = FormData::create(UTF8Encoding().encode(body, WTF::EntitiesForUnencodables));
701         if (m_upload)
702             httpBody->setAlwaysStream(true);
703     }
704
705     createRequest(httpBody.release(), exceptionState);
706 }
707
708 void XMLHttpRequest::send(Blob* body, ExceptionState& exceptionState)
709 {
710     WTF_LOG(Network, "XMLHttpRequest %p send() Blob '%s'", this, body->uuid().utf8().data());
711
712     if (!initSend(exceptionState))
713         return;
714
715     RefPtr<FormData> httpBody;
716
717     if (areMethodAndURLValidForSend()) {
718         if (getRequestHeader("Content-Type").isEmpty()) {
719             const String& blobType = body->type();
720             if (!blobType.isEmpty() && isValidContentType(blobType)) {
721                 setRequestHeaderInternal("Content-Type", AtomicString(blobType));
722             } else {
723                 // From FileAPI spec, whenever media type cannot be determined,
724                 // empty string must be returned.
725                 setRequestHeaderInternal("Content-Type", "");
726             }
727         }
728
729         // FIXME: add support for uploading bundles.
730         httpBody = FormData::create();
731         if (body->hasBackingFile()) {
732             File* file = toFile(body);
733             if (!file->path().isEmpty())
734                 httpBody->appendFile(file->path());
735             else if (!file->fileSystemURL().isEmpty())
736                 httpBody->appendFileSystemURL(file->fileSystemURL());
737             else
738                 ASSERT_NOT_REACHED();
739         } else {
740             httpBody->appendBlob(body->uuid(), body->blobDataHandle());
741         }
742     }
743
744     createRequest(httpBody.release(), exceptionState);
745 }
746
747 void XMLHttpRequest::send(DOMFormData* body, ExceptionState& exceptionState)
748 {
749     WTF_LOG(Network, "XMLHttpRequest %p send() DOMFormData %p", this, body);
750
751     if (!initSend(exceptionState))
752         return;
753
754     RefPtr<FormData> httpBody;
755
756     if (areMethodAndURLValidForSend()) {
757         httpBody = body->createMultiPartFormData();
758
759         if (getRequestHeader("Content-Type").isEmpty()) {
760             AtomicString contentType = AtomicString("multipart/form-data; boundary=", AtomicString::ConstructFromLiteral) + httpBody->boundary().data();
761             setRequestHeaderInternal("Content-Type", contentType);
762         }
763     }
764
765     createRequest(httpBody.release(), exceptionState);
766 }
767
768 void XMLHttpRequest::send(ArrayBuffer* body, ExceptionState& exceptionState)
769 {
770     WTF_LOG(Network, "XMLHttpRequest %p send() ArrayBuffer %p", this, body);
771
772     sendBytesData(body->data(), body->byteLength(), exceptionState);
773 }
774
775 void XMLHttpRequest::send(ArrayBufferView* body, ExceptionState& exceptionState)
776 {
777     WTF_LOG(Network, "XMLHttpRequest %p send() ArrayBufferView %p", this, body);
778
779     sendBytesData(body->baseAddress(), body->byteLength(), exceptionState);
780 }
781
782 void XMLHttpRequest::sendBytesData(const void* data, size_t length, ExceptionState& exceptionState)
783 {
784     if (!initSend(exceptionState))
785         return;
786
787     RefPtr<FormData> httpBody;
788
789     if (areMethodAndURLValidForSend()) {
790         httpBody = FormData::create(data, length);
791         if (m_upload)
792             httpBody->setAlwaysStream(true);
793     }
794
795     createRequest(httpBody.release(), exceptionState);
796 }
797
798 void XMLHttpRequest::sendForInspectorXHRReplay(PassRefPtr<FormData> formData, ExceptionState& exceptionState)
799 {
800     createRequest(formData ? formData->deepCopy() : nullptr, exceptionState);
801     m_exceptionCode = exceptionState.code();
802 }
803
804 void XMLHttpRequest::createRequest(PassRefPtr<FormData> httpBody, ExceptionState& exceptionState)
805 {
806     // Only GET request is supported for blob URL.
807     if (m_url.protocolIs("blob") && m_method != "GET") {
808         exceptionState.throwDOMException(NetworkError, "'GET' is the only method allowed for 'blob:' URLs.");
809         return;
810     }
811
812     // The presence of upload event listeners forces us to use preflighting because POSTing to an URL that does not
813     // permit cross origin requests should look exactly like POSTing to an URL that does not respond at all.
814     // Also, only async requests support upload progress events.
815     bool uploadEvents = false;
816     if (m_async) {
817         dispatchProgressEvent(EventTypeNames::loadstart, 0, 0);
818         if (httpBody && m_upload) {
819             uploadEvents = m_upload->hasEventListeners();
820             m_upload->dispatchEvent(XMLHttpRequestProgressEvent::create(EventTypeNames::loadstart));
821         }
822     }
823
824     m_sameOriginRequest = securityOrigin()->canRequest(m_url);
825
826     // We also remember whether upload events should be allowed for this request in case the upload listeners are
827     // added after the request is started.
828     m_uploadEventsAllowed = m_sameOriginRequest || uploadEvents || !FetchUtils::isSimpleRequest(m_method, m_requestHeaders);
829
830     ASSERT(executionContext());
831     ExecutionContext& executionContext = *this->executionContext();
832
833     ResourceRequest request(m_url);
834     request.setHTTPMethod(m_method);
835     request.setRequestContext(blink::WebURLRequest::RequestContextXMLHttpRequest);
836
837     InspectorInstrumentation::willLoadXHR(&executionContext, this, this, m_method, m_url, m_async, httpBody ? httpBody->deepCopy() : nullptr, m_requestHeaders, m_includeCredentials);
838
839     if (httpBody) {
840         ASSERT(m_method != "GET");
841         ASSERT(m_method != "HEAD");
842         request.setHTTPBody(httpBody);
843     }
844
845     if (m_requestHeaders.size() > 0)
846         request.addHTTPHeaderFields(m_requestHeaders);
847
848     ThreadableLoaderOptions options;
849     options.preflightPolicy = uploadEvents ? ForcePreflight : ConsiderPreflight;
850     options.crossOriginRequestPolicy = UseAccessControl;
851     options.initiator = FetchInitiatorTypeNames::xmlhttprequest;
852     options.contentSecurityPolicyEnforcement = ContentSecurityPolicy::shouldBypassMainWorld(&executionContext) ? DoNotEnforceContentSecurityPolicy : EnforceConnectSrcDirective;
853     options.timeoutMilliseconds = m_timeoutMilliseconds;
854
855     ResourceLoaderOptions resourceLoaderOptions;
856     resourceLoaderOptions.allowCredentials = (m_sameOriginRequest || m_includeCredentials) ? AllowStoredCredentials : DoNotAllowStoredCredentials;
857     resourceLoaderOptions.credentialsRequested = m_includeCredentials ? ClientRequestedCredentials : ClientDidNotRequestCredentials;
858     resourceLoaderOptions.securityOrigin = securityOrigin();
859     resourceLoaderOptions.mixedContentBlockingTreatment = RuntimeEnabledFeatures::laxMixedContentCheckingEnabled() ? TreatAsPassiveContent : TreatAsActiveContent;
860
861     // When responseType is set to "blob", we redirect the downloaded data to a
862     // file-handle directly.
863     m_downloadingToFile = responseTypeCode() == ResponseTypeBlob;
864     if (m_downloadingToFile) {
865         request.setDownloadToFile(true);
866         resourceLoaderOptions.dataBufferingPolicy = DoNotBufferData;
867     }
868
869     m_exceptionCode = 0;
870     m_error = false;
871
872     if (m_async) {
873         if (m_upload)
874             request.setReportUploadProgress(true);
875
876         // ThreadableLoader::create can return null here, for example if we're no longer attached to a page.
877         // This is true while running onunload handlers.
878         // FIXME: Maybe we need to be able to send XMLHttpRequests from onunload, <http://bugs.webkit.org/show_bug.cgi?id=10904>.
879         // FIXME: Maybe create() can return null for other reasons too?
880         ASSERT(!m_loader);
881         m_loader = ThreadableLoader::create(executionContext, this, request, options, resourceLoaderOptions);
882     } else {
883         // Use count for XHR synchronous requests.
884         UseCounter::count(&executionContext, UseCounter::XMLHttpRequestSynchronous);
885         ThreadableLoader::loadResourceSynchronously(executionContext, request, *this, options, resourceLoaderOptions);
886     }
887
888     if (!m_exceptionCode && m_error)
889         m_exceptionCode = NetworkError;
890     if (m_exceptionCode)
891         exceptionState.throwDOMException(m_exceptionCode, "Failed to load '" + m_url.elidedString() + "'.");
892 }
893
894 void XMLHttpRequest::abort()
895 {
896     WTF_LOG(Network, "XMLHttpRequest %p abort()", this);
897
898     // internalAbort() clears |m_loader|. Compute |sendFlag| now.
899     //
900     // |sendFlag| corresponds to "the send() flag" defined in the XHR spec.
901     //
902     // |sendFlag| is only set when we have an active, asynchronous loader.
903     // Don't use it as "the send() flag" when the XHR is in sync mode.
904     bool sendFlag = m_loader;
905
906     // internalAbort() clears the response. Save the data needed for
907     // dispatching ProgressEvents.
908     long long expectedLength = m_response.expectedContentLength();
909     long long receivedLength = m_receivedLength;
910
911     if (!internalAbort())
912         return;
913
914     // The script never gets any chance to call abort() on a sync XHR between
915     // send() call and transition to the DONE state. It's because a sync XHR
916     // doesn't dispatch any event between them. So, if |m_async| is false, we
917     // can skip the "request error steps" (defined in the XHR spec) without any
918     // state check.
919     //
920     // FIXME: It's possible open() is invoked in internalAbort() and |m_async|
921     // becomes true by that. We should implement more reliable treatment for
922     // nested method invocations at some point.
923     if (m_async) {
924         if ((m_state == OPENED && sendFlag) || m_state == HEADERS_RECEIVED || m_state == LOADING) {
925             ASSERT(!m_loader);
926             handleRequestError(0, EventTypeNames::abort, receivedLength, expectedLength);
927         }
928     }
929     m_state = UNSENT;
930 }
931
932 void XMLHttpRequest::clearVariablesForLoading()
933 {
934     m_decoder.clear();
935
936     if (m_responseDocumentParser) {
937         m_responseDocumentParser->removeClient(this);
938 #if !ENABLE(OILPAN)
939         m_responseDocumentParser->detach();
940 #endif
941         m_responseDocumentParser = nullptr;
942     }
943
944     m_finalResponseCharset = String();
945 }
946
947 bool XMLHttpRequest::internalAbort()
948 {
949     m_error = true;
950
951     if (m_responseDocumentParser && !m_responseDocumentParser->isStopped())
952         m_responseDocumentParser->stopParsing();
953
954     clearVariablesForLoading();
955
956     InspectorInstrumentation::didFailXHRLoading(executionContext(), this, this);
957
958     if (m_responseLegacyStream && m_state != DONE)
959         m_responseLegacyStream->abort();
960
961     if (m_responseStream) {
962         // When the stream is already closed (including canceled from the
963         // user), |error| does nothing.
964         // FIXME: Create a more specific error.
965         m_responseStream->error(DOMException::create(!m_async && m_exceptionCode ? m_exceptionCode : AbortError, "XMLHttpRequest::abort"));
966     }
967
968     clearResponse();
969     clearRequest();
970
971     if (!m_loader)
972         return true;
973
974     // Cancelling the ThreadableLoader m_loader may result in calling
975     // window.onload synchronously. If such an onload handler contains open()
976     // call on the same XMLHttpRequest object, reentry happens.
977     //
978     // If, window.onload contains open() and send(), m_loader will be set to
979     // non 0 value. So, we cannot continue the outer open(). In such case,
980     // just abort the outer open() by returning false.
981     RefPtr<ThreadableLoader> loader = m_loader.release();
982     loader->cancel();
983
984     // If abort() called internalAbort() and a nested open() ended up
985     // clearing the error flag, but didn't send(), make sure the error
986     // flag is still set.
987     bool newLoadStarted = hasPendingActivity();
988     if (!newLoadStarted)
989         m_error = true;
990
991     return !newLoadStarted;
992 }
993
994 void XMLHttpRequest::clearResponse()
995 {
996     // FIXME: when we add the support for multi-part XHR, we will have to
997     // be careful with this initialization.
998     m_receivedLength = 0;
999
1000     m_response = ResourceResponse();
1001
1002     m_responseText.clear();
1003
1004     m_parsedResponse = false;
1005     m_responseDocument = nullptr;
1006
1007     m_responseBlob = nullptr;
1008
1009     m_downloadingToFile = false;
1010     m_lengthDownloadedToFile = 0;
1011
1012     m_responseLegacyStream = nullptr;
1013     m_responseStream = nullptr;
1014
1015     // These variables may referred by the response accessors. So, we can clear
1016     // this only when we clear the response holder variables above.
1017     m_binaryResponseBuilder.clear();
1018     m_responseArrayBuffer.clear();
1019 }
1020
1021 void XMLHttpRequest::clearRequest()
1022 {
1023     m_requestHeaders.clear();
1024 }
1025
1026 void XMLHttpRequest::dispatchProgressEvent(const AtomicString& type, long long receivedLength, long long expectedLength)
1027 {
1028     bool lengthComputable = expectedLength > 0 && receivedLength <= expectedLength;
1029     unsigned long long loaded = receivedLength >= 0 ? static_cast<unsigned long long>(receivedLength) : 0;
1030     unsigned long long total = lengthComputable ? static_cast<unsigned long long>(expectedLength) : 0;
1031
1032     m_progressEventThrottle.dispatchProgressEvent(type, lengthComputable, loaded, total);
1033
1034     if (type == EventTypeNames::loadend)
1035         InspectorInstrumentation::didDispatchXHRLoadendEvent(executionContext(), this);
1036 }
1037
1038 void XMLHttpRequest::dispatchProgressEventFromSnapshot(const AtomicString& type)
1039 {
1040     dispatchProgressEvent(type, m_receivedLength, m_response.expectedContentLength());
1041 }
1042
1043 void XMLHttpRequest::handleNetworkError()
1044 {
1045     WTF_LOG(Network, "XMLHttpRequest %p handleNetworkError()", this);
1046
1047     // Response is cleared next, save needed progress event data.
1048     long long expectedLength = m_response.expectedContentLength();
1049     long long receivedLength = m_receivedLength;
1050
1051     // Prevent the XMLHttpRequest instance from being destoryed during
1052     // |internalAbort()|.
1053     RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
1054
1055     if (!internalAbort())
1056         return;
1057
1058     handleRequestError(NetworkError, EventTypeNames::error, receivedLength, expectedLength);
1059 }
1060
1061 void XMLHttpRequest::handleDidCancel()
1062 {
1063     WTF_LOG(Network, "XMLHttpRequest %p handleDidCancel()", this);
1064
1065     // Response is cleared next, save needed progress event data.
1066     long long expectedLength = m_response.expectedContentLength();
1067     long long receivedLength = m_receivedLength;
1068
1069     // Prevent the XMLHttpRequest instance from being destoryed during
1070     // |internalAbort()|.
1071     RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
1072
1073     if (!internalAbort())
1074         return;
1075
1076     handleRequestError(AbortError, EventTypeNames::abort, receivedLength, expectedLength);
1077 }
1078
1079 void XMLHttpRequest::handleRequestError(ExceptionCode exceptionCode, const AtomicString& type, long long receivedLength, long long expectedLength)
1080 {
1081     WTF_LOG(Network, "XMLHttpRequest %p handleRequestError()", this);
1082
1083     // The request error steps for event 'type' and exception 'exceptionCode'.
1084
1085     if (!m_async && exceptionCode) {
1086         m_state = DONE;
1087         m_exceptionCode = exceptionCode;
1088         return;
1089     }
1090     // With m_error set, the state change steps are minimal: any pending
1091     // progress event is flushed + a readystatechange is dispatched.
1092     // No new progress events dispatched; as required, that happens at
1093     // the end here.
1094     ASSERT(m_error);
1095     changeState(DONE);
1096
1097     if (!m_uploadComplete) {
1098         m_uploadComplete = true;
1099         if (m_upload && m_uploadEventsAllowed)
1100             m_upload->handleRequestError(type);
1101     }
1102
1103     // Note: The below event dispatch may be called while |hasPendingActivity() == false|,
1104     // when |handleRequestError| is called after |internalAbort()|.
1105     // This is safe, however, as |this| will be kept alive from a strong ref |Event::m_target|.
1106     dispatchProgressEvent(EventTypeNames::progress, receivedLength, expectedLength);
1107     dispatchProgressEvent(type, receivedLength, expectedLength);
1108     dispatchProgressEvent(EventTypeNames::loadend, receivedLength, expectedLength);
1109 }
1110
1111 void XMLHttpRequest::overrideMimeType(const AtomicString& mimeType, ExceptionState& exceptionState)
1112 {
1113     if (m_state == LOADING || m_state == DONE) {
1114         exceptionState.throwDOMException(InvalidStateError, "MimeType cannot be overridden when the state is LOADING or DONE.");
1115         return;
1116     }
1117
1118     m_mimeTypeOverride = mimeType;
1119 }
1120
1121 void XMLHttpRequest::setRequestHeader(const AtomicString& name, const AtomicString& value, ExceptionState& exceptionState)
1122 {
1123     if (m_state != OPENED || m_loader) {
1124         exceptionState.throwDOMException(InvalidStateError, "The object's state must be OPENED.");
1125         return;
1126     }
1127
1128     if (!isValidHTTPToken(name)) {
1129         exceptionState.throwDOMException(SyntaxError, "'" + name + "' is not a valid HTTP header field name.");
1130         return;
1131     }
1132
1133     if (!isValidHTTPHeaderValue(value)) {
1134         exceptionState.throwDOMException(SyntaxError, "'" + value + "' is not a valid HTTP header field value.");
1135         return;
1136     }
1137
1138     // No script (privileged or not) can set unsafe headers.
1139     if (FetchUtils::isForbiddenHeaderName(name)) {
1140         logConsoleError(executionContext(), "Refused to set unsafe header \"" + name + "\"");
1141         return;
1142     }
1143
1144     setRequestHeaderInternal(name, value);
1145 }
1146
1147 void XMLHttpRequest::setRequestHeaderInternal(const AtomicString& name, const AtomicString& value)
1148 {
1149     HTTPHeaderMap::AddResult result = m_requestHeaders.add(name, value);
1150     if (!result.isNewEntry)
1151         result.storedValue->value = result.storedValue->value + ", " + value;
1152 }
1153
1154 const AtomicString& XMLHttpRequest::getRequestHeader(const AtomicString& name) const
1155 {
1156     return m_requestHeaders.get(name);
1157 }
1158
1159 String XMLHttpRequest::getAllResponseHeaders() const
1160 {
1161     if (m_state < HEADERS_RECEIVED || m_error)
1162         return "";
1163
1164     StringBuilder stringBuilder;
1165
1166     HTTPHeaderSet accessControlExposeHeaderSet;
1167     parseAccessControlExposeHeadersAllowList(m_response.httpHeaderField("Access-Control-Expose-Headers"), accessControlExposeHeaderSet);
1168     HTTPHeaderMap::const_iterator end = m_response.httpHeaderFields().end();
1169     for (HTTPHeaderMap::const_iterator it = m_response.httpHeaderFields().begin(); it!= end; ++it) {
1170         // Hide Set-Cookie header fields from the XMLHttpRequest client for these reasons:
1171         //     1) If the client did have access to the fields, then it could read HTTP-only
1172         //        cookies; those cookies are supposed to be hidden from scripts.
1173         //     2) There's no known harm in hiding Set-Cookie header fields entirely; we don't
1174         //        know any widely used technique that requires access to them.
1175         //     3) Firefox has implemented this policy.
1176         if (isSetCookieHeader(it->key) && !securityOrigin()->canLoadLocalResources())
1177             continue;
1178
1179         if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(it->key) && !accessControlExposeHeaderSet.contains(it->key))
1180             continue;
1181
1182         stringBuilder.append(it->key);
1183         stringBuilder.append(':');
1184         stringBuilder.append(' ');
1185         stringBuilder.append(it->value);
1186         stringBuilder.append('\r');
1187         stringBuilder.append('\n');
1188     }
1189
1190     return stringBuilder.toString();
1191 }
1192
1193 const AtomicString& XMLHttpRequest::getResponseHeader(const AtomicString& name) const
1194 {
1195     if (m_state < HEADERS_RECEIVED || m_error)
1196         return nullAtom;
1197
1198     // See comment in getAllResponseHeaders above.
1199     if (isSetCookieHeader(name) && !securityOrigin()->canLoadLocalResources()) {
1200         logConsoleError(executionContext(), "Refused to get unsafe header \"" + name + "\"");
1201         return nullAtom;
1202     }
1203
1204     HTTPHeaderSet accessControlExposeHeaderSet;
1205     parseAccessControlExposeHeadersAllowList(m_response.httpHeaderField("Access-Control-Expose-Headers"), accessControlExposeHeaderSet);
1206
1207     if (!m_sameOriginRequest && !isOnAccessControlResponseHeaderWhitelist(name) && !accessControlExposeHeaderSet.contains(name)) {
1208         logConsoleError(executionContext(), "Refused to get unsafe header \"" + name + "\"");
1209         return nullAtom;
1210     }
1211     return m_response.httpHeaderField(name);
1212 }
1213
1214 AtomicString XMLHttpRequest::finalResponseMIMEType() const
1215 {
1216     AtomicString overriddenType = extractMIMETypeFromMediaType(m_mimeTypeOverride);
1217     if (!overriddenType.isEmpty())
1218         return overriddenType;
1219
1220     if (m_response.isHTTP())
1221         return extractMIMETypeFromMediaType(m_response.httpHeaderField("Content-Type"));
1222
1223     return m_response.mimeType();
1224 }
1225
1226 AtomicString XMLHttpRequest::finalResponseMIMETypeWithFallback() const
1227 {
1228     AtomicString finalType = finalResponseMIMEType();
1229     if (!finalType.isEmpty())
1230         return finalType;
1231
1232     // FIXME: This fallback is not specified in the final MIME type algorithm
1233     // of the XHR spec. Move this to more appropriate place.
1234     return AtomicString("text/xml", AtomicString::ConstructFromLiteral);
1235 }
1236
1237 bool XMLHttpRequest::responseIsXML() const
1238 {
1239     return DOMImplementation::isXMLMIMEType(finalResponseMIMETypeWithFallback());
1240 }
1241
1242 bool XMLHttpRequest::responseIsHTML() const
1243 {
1244     return equalIgnoringCase(finalResponseMIMEType(), "text/html");
1245 }
1246
1247 int XMLHttpRequest::status() const
1248 {
1249     if (m_state == UNSENT || m_state == OPENED || m_error)
1250         return 0;
1251
1252     if (m_response.httpStatusCode())
1253         return m_response.httpStatusCode();
1254
1255     return 0;
1256 }
1257
1258 String XMLHttpRequest::statusText() const
1259 {
1260     if (m_state == UNSENT || m_state == OPENED || m_error)
1261         return String();
1262
1263     if (!m_response.httpStatusText().isNull())
1264         return m_response.httpStatusText();
1265
1266     return String();
1267 }
1268
1269 void XMLHttpRequest::didFail(const ResourceError& error)
1270 {
1271     WTF_LOG(Network, "XMLHttpRequest %p didFail()", this);
1272
1273     // If we are already in an error state, for instance we called abort(), bail out early.
1274     if (m_error)
1275         return;
1276
1277     if (error.isCancellation()) {
1278         handleDidCancel();
1279         // Now the XMLHttpRequest instance may be dead.
1280         return;
1281     }
1282
1283     if (error.isTimeout()) {
1284         handleDidTimeout();
1285         // Now the XMLHttpRequest instance may be dead.
1286         return;
1287     }
1288
1289     // Network failures are already reported to Web Inspector by ResourceLoader.
1290     if (error.domain() == errorDomainBlinkInternal)
1291         logConsoleError(executionContext(), "XMLHttpRequest cannot load " + error.failingURL() + ". " + error.localizedDescription());
1292
1293     handleNetworkError();
1294     // Now the XMLHttpRequest instance may be dead.
1295 }
1296
1297 void XMLHttpRequest::didFailRedirectCheck()
1298 {
1299     WTF_LOG(Network, "XMLHttpRequest %p didFailRedirectCheck()", this);
1300
1301     handleNetworkError();
1302     // Now the XMLHttpRequest instance may be dead.
1303 }
1304
1305 void XMLHttpRequest::didFinishLoading(unsigned long identifier, double)
1306 {
1307     WTF_LOG(Network, "XMLHttpRequest %p didFinishLoading(%lu)", this, identifier);
1308
1309     if (m_error)
1310         return;
1311
1312     if (m_state < HEADERS_RECEIVED)
1313         changeState(HEADERS_RECEIVED);
1314
1315     m_loaderIdentifier = identifier;
1316
1317     if (m_responseDocumentParser) {
1318         // |DocumentParser::finish()| tells the parser that we have reached end of the data.
1319         // When using |HTMLDocumentParser|, which works asynchronously, we do not have the
1320         // complete document just after the |DocumentParser::finish()| call.
1321         // Wait for the parser to call us back in |notifyParserStopped| to progress state.
1322         m_responseDocumentParser->finish();
1323         ASSERT(m_responseDocument);
1324         return;
1325     }
1326
1327     if (m_decoder)
1328         m_responseText = m_responseText.concatenateWith(m_decoder->flush());
1329
1330     if (m_responseLegacyStream)
1331         m_responseLegacyStream->finalize();
1332
1333     if (m_responseStream)
1334         m_responseStream->close();
1335
1336     clearVariablesForLoading();
1337     endLoading();
1338 }
1339
1340 void XMLHttpRequest::notifyParserStopped()
1341 {
1342     // This should only be called when response document is parsed asynchronously.
1343     ASSERT(m_responseDocumentParser);
1344     ASSERT(!m_responseDocumentParser->isParsing());
1345     ASSERT(!m_responseLegacyStream);
1346     ASSERT(!m_responseStream);
1347
1348     // Do nothing if we are called from |internalAbort()|.
1349     if (m_error)
1350         return;
1351
1352     clearVariablesForLoading();
1353
1354     m_responseDocument->implicitClose();
1355
1356     if (!m_responseDocument->wellFormed())
1357         m_responseDocument = nullptr;
1358
1359     m_parsedResponse = true;
1360
1361     endLoading();
1362 }
1363
1364 void XMLHttpRequest::endLoading()
1365 {
1366     InspectorInstrumentation::didFinishXHRLoading(executionContext(), this, this, m_loaderIdentifier, m_responseText, m_method, m_url, m_lastSendURL, m_lastSendLineNumber);
1367
1368     if (m_loader)
1369         m_loader = nullptr;
1370     m_loaderIdentifier = 0;
1371
1372     changeState(DONE);
1373 }
1374
1375 void XMLHttpRequest::didSendData(unsigned long long bytesSent, unsigned long long totalBytesToBeSent)
1376 {
1377     WTF_LOG(Network, "XMLHttpRequest %p didSendData(%llu, %llu)", this, bytesSent, totalBytesToBeSent);
1378
1379     if (!m_upload)
1380         return;
1381
1382     if (m_uploadEventsAllowed)
1383         m_upload->dispatchProgressEvent(bytesSent, totalBytesToBeSent);
1384
1385     if (bytesSent == totalBytesToBeSent && !m_uploadComplete) {
1386         m_uploadComplete = true;
1387         if (m_uploadEventsAllowed)
1388             m_upload->dispatchEventAndLoadEnd(EventTypeNames::load, true, bytesSent, totalBytesToBeSent);
1389     }
1390 }
1391
1392 void XMLHttpRequest::didReceiveResponse(unsigned long identifier, const ResourceResponse& response)
1393 {
1394     WTF_LOG(Network, "XMLHttpRequest %p didReceiveResponse(%lu)", this, identifier);
1395
1396     m_response = response;
1397     if (!m_mimeTypeOverride.isEmpty()) {
1398         m_response.setHTTPHeaderField("Content-Type", m_mimeTypeOverride);
1399         m_finalResponseCharset = extractCharsetFromMediaType(m_mimeTypeOverride);
1400     }
1401
1402     if (m_finalResponseCharset.isEmpty())
1403         m_finalResponseCharset = response.textEncodingName();
1404 }
1405
1406 void XMLHttpRequest::parseDocumentChunk(const char* data, int len)
1407 {
1408     if (!m_responseDocumentParser) {
1409         ASSERT(!m_responseDocument);
1410         initResponseDocument();
1411         if (!m_responseDocument)
1412             return;
1413
1414         m_responseDocumentParser = m_responseDocument->implicitOpen();
1415         m_responseDocumentParser->addClient(this);
1416     }
1417     ASSERT(m_responseDocumentParser);
1418
1419     if (m_responseDocumentParser->needsDecoder())
1420         m_responseDocumentParser->setDecoder(createDecoder());
1421
1422     m_responseDocumentParser->appendBytes(data, len);
1423 }
1424
1425 PassOwnPtr<TextResourceDecoder> XMLHttpRequest::createDecoder() const
1426 {
1427     if (m_responseTypeCode == ResponseTypeJSON)
1428         return TextResourceDecoder::create("application/json", "UTF-8");
1429
1430     if (!m_finalResponseCharset.isEmpty())
1431         return TextResourceDecoder::create("text/plain", m_finalResponseCharset);
1432
1433     // allow TextResourceDecoder to look inside the m_response if it's XML or HTML
1434     if (responseIsXML()) {
1435         OwnPtr<TextResourceDecoder> decoder = TextResourceDecoder::create("application/xml");
1436         // Don't stop on encoding errors, unlike it is done for other kinds
1437         // of XML resources. This matches the behavior of previous WebKit
1438         // versions, Firefox and Opera.
1439         decoder->useLenientXMLDecoding();
1440
1441         return decoder.release();
1442     }
1443
1444     if (responseIsHTML())
1445         return TextResourceDecoder::create("text/html", "UTF-8");
1446
1447     return TextResourceDecoder::create("text/plain", "UTF-8");
1448 }
1449
1450 void XMLHttpRequest::didReceiveData(const char* data, int len)
1451 {
1452     ASSERT(!m_downloadingToFile);
1453
1454     if (m_error)
1455         return;
1456
1457     if (m_state < HEADERS_RECEIVED)
1458         changeState(HEADERS_RECEIVED);
1459
1460     // We need to check for |m_error| again, because |changeState| may trigger
1461     // readystatechange, and user javascript can cause |abort()|.
1462     if (m_error)
1463         return;
1464
1465     if (!len)
1466         return;
1467
1468     if (len == -1)
1469         len = strlen(data);
1470
1471     if (m_responseTypeCode == ResponseTypeDocument && responseIsHTML()) {
1472         parseDocumentChunk(data, len);
1473     } else if (m_responseTypeCode == ResponseTypeDefault || m_responseTypeCode == ResponseTypeText || m_responseTypeCode == ResponseTypeJSON || m_responseTypeCode == ResponseTypeDocument) {
1474         if (!m_decoder)
1475             m_decoder = createDecoder();
1476
1477         m_responseText = m_responseText.concatenateWith(m_decoder->decode(data, len));
1478     } else if (m_responseTypeCode == ResponseTypeArrayBuffer || m_responseTypeCode == ResponseTypeBlob) {
1479         // Buffer binary data.
1480         if (!m_binaryResponseBuilder)
1481             m_binaryResponseBuilder = SharedBuffer::create();
1482         m_binaryResponseBuilder->append(data, len);
1483     } else if (m_responseTypeCode == ResponseTypeLegacyStream) {
1484         if (!m_responseLegacyStream)
1485             m_responseLegacyStream = Stream::create(executionContext(), responseType());
1486         m_responseLegacyStream->addData(data, len);
1487     } else if (m_responseTypeCode == ResponseTypeStream) {
1488         if (!m_responseStream) {
1489             m_responseStream = new ReadableStreamImpl<ReadableStreamChunkTypeTraits<ArrayBuffer> >(executionContext(), new ReadableStreamSource(this));
1490             m_responseStream->didSourceStart();
1491         }
1492         m_responseStream->enqueue(ArrayBuffer::create(data, len));
1493     }
1494
1495     trackProgress(len);
1496 }
1497
1498 void XMLHttpRequest::didDownloadData(int dataLength)
1499 {
1500     if (m_error)
1501         return;
1502
1503     ASSERT(m_downloadingToFile);
1504
1505     if (m_state < HEADERS_RECEIVED)
1506         changeState(HEADERS_RECEIVED);
1507
1508     if (!dataLength)
1509         return;
1510
1511     // readystatechange event handler may do something to put this XHR in error
1512     // state. We need to check m_error again here.
1513     if (m_error)
1514         return;
1515
1516     m_lengthDownloadedToFile += dataLength;
1517
1518     trackProgress(dataLength);
1519 }
1520
1521 void XMLHttpRequest::handleDidTimeout()
1522 {
1523     WTF_LOG(Network, "XMLHttpRequest %p handleDidTimeout()", this);
1524
1525     // Response is cleared next, save needed progress event data.
1526     long long expectedLength = m_response.expectedContentLength();
1527     long long receivedLength = m_receivedLength;
1528
1529     // Prevent the XMLHttpRequest instance from being destoryed during
1530     // |internalAbort()|.
1531     RefPtrWillBeRawPtr<XMLHttpRequest> protect(this);
1532
1533     if (!internalAbort())
1534         return;
1535
1536     handleRequestError(TimeoutError, EventTypeNames::timeout, receivedLength, expectedLength);
1537 }
1538
1539 void XMLHttpRequest::suspend()
1540 {
1541     m_progressEventThrottle.suspend();
1542 }
1543
1544 void XMLHttpRequest::resume()
1545 {
1546     m_progressEventThrottle.resume();
1547 }
1548
1549 void XMLHttpRequest::stop()
1550 {
1551     internalAbort();
1552 }
1553
1554 bool XMLHttpRequest::hasPendingActivity() const
1555 {
1556     // Neither this object nor the JavaScript wrapper should be deleted while
1557     // a request is in progress because we need to keep the listeners alive,
1558     // and they are referenced by the JavaScript wrapper.
1559     // |m_loader| is non-null while request is active and ThreadableLoaderClient
1560     // callbacks may be called, and |m_responseDocumentParser| is non-null while
1561     // DocumentParserClient callbacks may be called.
1562     return m_loader || m_responseDocumentParser;
1563 }
1564
1565 void XMLHttpRequest::contextDestroyed()
1566 {
1567     ASSERT(!m_loader);
1568     ActiveDOMObject::contextDestroyed();
1569 }
1570
1571 const AtomicString& XMLHttpRequest::interfaceName() const
1572 {
1573     return EventTargetNames::XMLHttpRequest;
1574 }
1575
1576 ExecutionContext* XMLHttpRequest::executionContext() const
1577 {
1578     return ActiveDOMObject::executionContext();
1579 }
1580
1581 void XMLHttpRequest::trace(Visitor* visitor)
1582 {
1583     visitor->trace(m_responseBlob);
1584     visitor->trace(m_responseLegacyStream);
1585     visitor->trace(m_responseStream);
1586     visitor->trace(m_streamSource);
1587     visitor->trace(m_responseDocument);
1588     visitor->trace(m_responseDocumentParser);
1589     visitor->trace(m_progressEventThrottle);
1590     visitor->trace(m_upload);
1591     XMLHttpRequestEventTarget::trace(visitor);
1592 }
1593
1594 } // namespace blink