OLD | NEW |
1 /* | 1 /* |
2 * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. | 2 * Copyright (C) 2004, 2006, 2008 Apple Inc. All rights reserved. |
3 * Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org> | 3 * Copyright (C) 2005-2007 Alexey Proskuryakov <ap@webkit.org> |
4 * Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix@webkit.org> | 4 * Copyright (C) 2007, 2008 Julien Chaffraix <jchaffraix@webkit.org> |
5 * Copyright (C) 2008, 2011 Google Inc. All rights reserved. | 5 * Copyright (C) 2008, 2011 Google Inc. All rights reserved. |
6 * Copyright (C) 2012 Intel Corporation | 6 * Copyright (C) 2012 Intel Corporation |
7 * | 7 * |
8 * This library is free software; you can redistribute it and/or | 8 * This library is free software; you can redistribute it and/or |
9 * modify it under the terms of the GNU Lesser General Public | 9 * modify it under the terms of the GNU Lesser General Public |
10 * License as published by the Free Software Foundation; either | 10 * License as published by the Free Software Foundation; either |
(...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
208 } | 208 } |
209 | 209 |
210 XMLHttpRequest::State XMLHttpRequest::readyState() const | 210 XMLHttpRequest::State XMLHttpRequest::readyState() const |
211 { | 211 { |
212 return m_state; | 212 return m_state; |
213 } | 213 } |
214 | 214 |
215 ScriptString XMLHttpRequest::responseText(ExceptionState& exceptionState) | 215 ScriptString XMLHttpRequest::responseText(ExceptionState& exceptionState) |
216 { | 216 { |
217 if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != Respo
nseTypeText) { | 217 if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != Respo
nseTypeText) { |
218 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToGet("responseText", "XMLHttpRequest", "the value is only accessible if th
e object's 'responseType' is '' or 'text' (was '" + responseType() + "').")); | 218 exceptionState.throwDOMException(InvalidStateError, "The value is only a
ccessible if the object's 'responseType' is '' or 'text' (was '" + responseType(
) + "')."); |
219 return ScriptString(); | 219 return ScriptString(); |
220 } | 220 } |
221 if (m_error || (m_state != LOADING && m_state != DONE)) | 221 if (m_error || (m_state != LOADING && m_state != DONE)) |
222 return ScriptString(); | 222 return ScriptString(); |
223 return m_responseText; | 223 return m_responseText; |
224 } | 224 } |
225 | 225 |
226 ScriptString XMLHttpRequest::responseJSONSource() | 226 ScriptString XMLHttpRequest::responseJSONSource() |
227 { | 227 { |
228 ASSERT(m_responseTypeCode == ResponseTypeJSON); | 228 ASSERT(m_responseTypeCode == ResponseTypeJSON); |
229 | 229 |
230 if (m_error || m_state != DONE) | 230 if (m_error || m_state != DONE) |
231 return ScriptString(); | 231 return ScriptString(); |
232 return m_responseText; | 232 return m_responseText; |
233 } | 233 } |
234 | 234 |
235 Document* XMLHttpRequest::responseXML(ExceptionState& exceptionState) | 235 Document* XMLHttpRequest::responseXML(ExceptionState& exceptionState) |
236 { | 236 { |
237 if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != Respo
nseTypeDocument) { | 237 if (m_responseTypeCode != ResponseTypeDefault && m_responseTypeCode != Respo
nseTypeDocument) { |
238 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToGet("responseXML", "XMLHttpRequest", "the value is only accessible if the
object's 'responseType' is '' or 'document' (was '" + responseType() + "').")); | 238 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToGet("responseXML", "XMLHttpRequest", "The value is only accessible if the
object's 'responseType' is '' or 'document' (was '" + responseType() + "').")); |
239 return 0; | 239 return 0; |
240 } | 240 } |
241 | 241 |
242 if (m_error || m_state != DONE) | 242 if (m_error || m_state != DONE) |
243 return 0; | 243 return 0; |
244 | 244 |
245 if (!m_createdDocument) { | 245 if (!m_createdDocument) { |
246 bool isHTML = equalIgnoringCase(responseMIMEType(), "text/html"); | 246 bool isHTML = equalIgnoringCase(responseMIMEType(), "text/html"); |
247 | 247 |
248 // The W3C spec requires the final MIME type to be some valid XML type,
or text/html. | 248 // The W3C spec requires the final MIME type to be some valid XML type,
or text/html. |
(...skipping 81 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
330 return 0; | 330 return 0; |
331 | 331 |
332 return m_responseStream.get(); | 332 return m_responseStream.get(); |
333 } | 333 } |
334 | 334 |
335 void XMLHttpRequest::setTimeout(unsigned long timeout, ExceptionState& exception
State) | 335 void XMLHttpRequest::setTimeout(unsigned long timeout, ExceptionState& exception
State) |
336 { | 336 { |
337 // FIXME: Need to trigger or update the timeout Timer here, if needed. http:
//webkit.org/b/98156 | 337 // FIXME: Need to trigger or update the timeout Timer here, if needed. http:
//webkit.org/b/98156 |
338 // XHR2 spec, 4.7.3. "This implies that the timeout attribute can be set whi
le fetching is in progress. If that occurs it will still be measured relative to
the start of fetching." | 338 // XHR2 spec, 4.7.3. "This implies that the timeout attribute can be set whi
le fetching is in progress. If that occurs it will still be measured relative to
the start of fetching." |
339 if (executionContext()->isDocument() && !m_async) { | 339 if (executionContext()->isDocument() && !m_async) { |
340 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::
failedToSet("timeout", "XMLHttpRequest", "timeouts cannot be set for synchronous
requests made from a document.")); | 340 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::
failedToSet("timeout", "XMLHttpRequest", "Timeouts cannot be set for synchronous
requests made from a document.")); |
341 return; | 341 return; |
342 } | 342 } |
343 m_timeoutMilliseconds = timeout; | 343 m_timeoutMilliseconds = timeout; |
344 } | 344 } |
345 | 345 |
346 void XMLHttpRequest::setResponseType(const String& responseType, ExceptionState&
exceptionState) | 346 void XMLHttpRequest::setResponseType(const String& responseType, ExceptionState&
exceptionState) |
347 { | 347 { |
348 if (m_state >= LOADING) { | 348 if (m_state >= LOADING) { |
349 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToSet("responseType", "XMLHttpRequest", "the response type cannot be set if
the object's state is LOADING or DONE.")); | 349 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToSet("responseType", "XMLHttpRequest", "The response type cannot be set if
the object's state is LOADING or DONE.")); |
350 return; | 350 return; |
351 } | 351 } |
352 | 352 |
353 // Newer functionality is not available to synchronous requests in window co
ntexts, as a spec-mandated | 353 // Newer functionality is not available to synchronous requests in window co
ntexts, as a spec-mandated |
354 // attempt to discourage synchronous XHR use. responseType is one such piece
of functionality. | 354 // attempt to discourage synchronous XHR use. responseType is one such piece
of functionality. |
355 // We'll only disable this functionality for HTTP(S) requests since sync req
uests for local protocols | 355 // We'll only disable this functionality for HTTP(S) requests since sync req
uests for local protocols |
356 // such as file: and data: still make sense to allow. | 356 // such as file: and data: still make sense to allow. |
357 if (!m_async && executionContext()->isDocument() && m_url.protocolIsInHTTPFa
mily()) { | 357 if (!m_async && executionContext()->isDocument() && m_url.protocolIsInHTTPFa
mily()) { |
358 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::
failedToSet("responseType", "XMLHttpRequest", "the response type can only be cha
nged for asynchronous HTTP requests made from a document.")); | 358 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessages::
failedToSet("responseType", "XMLHttpRequest", "The response type can only be cha
nged for asynchronous HTTP requests made from a document.")); |
359 return; | 359 return; |
360 } | 360 } |
361 | 361 |
362 if (responseType == "") { | 362 if (responseType == "") { |
363 m_responseTypeCode = ResponseTypeDefault; | 363 m_responseTypeCode = ResponseTypeDefault; |
364 } else if (responseType == "text") { | 364 } else if (responseType == "text") { |
365 m_responseTypeCode = ResponseTypeText; | 365 m_responseTypeCode = ResponseTypeText; |
366 } else if (responseType == "json") { | 366 } else if (responseType == "json") { |
367 m_responseTypeCode = ResponseTypeJSON; | 367 m_responseTypeCode = ResponseTypeJSON; |
368 } else if (responseType == "document") { | 368 } else if (responseType == "document") { |
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
440 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDi
spatchXHRLoadEvent(executionContext(), this); | 440 InspectorInstrumentationCookie cookie = InspectorInstrumentation::willDi
spatchXHRLoadEvent(executionContext(), this); |
441 dispatchThrottledProgressEventSnapshot(EventTypeNames::load); | 441 dispatchThrottledProgressEventSnapshot(EventTypeNames::load); |
442 InspectorInstrumentation::didDispatchXHRLoadEvent(cookie); | 442 InspectorInstrumentation::didDispatchXHRLoadEvent(cookie); |
443 dispatchThrottledProgressEventSnapshot(EventTypeNames::loadend); | 443 dispatchThrottledProgressEventSnapshot(EventTypeNames::loadend); |
444 } | 444 } |
445 } | 445 } |
446 | 446 |
447 void XMLHttpRequest::setWithCredentials(bool value, ExceptionState& exceptionSta
te) | 447 void XMLHttpRequest::setWithCredentials(bool value, ExceptionState& exceptionSta
te) |
448 { | 448 { |
449 if (m_state > OPENED || m_loader) { | 449 if (m_state > OPENED || m_loader) { |
450 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToSet("withCredentials", "XMLHttpRequest", "the value may only be set if th
e object's state is UNSENT or OPENED.")); | 450 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToSet("withCredentials", "XMLHttpRequest", "The value may only be set if th
e object's state is UNSENT or OPENED.")); |
451 return; | 451 return; |
452 } | 452 } |
453 | 453 |
454 m_includeCredentials = value; | 454 m_includeCredentials = value; |
455 } | 455 } |
456 | 456 |
457 bool XMLHttpRequest::isAllowedHTTPMethod(const String& method) | 457 bool XMLHttpRequest::isAllowedHTTPMethod(const String& method) |
458 { | 458 { |
459 return !equalIgnoringCase(method, "TRACE") | 459 return !equalIgnoringCase(method, "TRACE") |
460 && !equalIgnoringCase(method, "TRACK") | 460 && !equalIgnoringCase(method, "TRACK") |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
514 m_error = false; | 514 m_error = false; |
515 m_uploadComplete = false; | 515 m_uploadComplete = false; |
516 | 516 |
517 // clear stuff from possible previous load | 517 // clear stuff from possible previous load |
518 clearResponse(); | 518 clearResponse(); |
519 clearRequest(); | 519 clearRequest(); |
520 | 520 |
521 ASSERT(m_state == UNSENT); | 521 ASSERT(m_state == UNSENT); |
522 | 522 |
523 if (!isValidHTTPToken(method)) { | 523 if (!isValidHTTPToken(method)) { |
524 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedT
oExecute("open", "XMLHttpRequest", "'" + method + "' is not a valid HTTP method.
")); | 524 exceptionState.throwDOMException(SyntaxError, "'" + method + "' is not a
valid HTTP method."); |
525 return; | 525 return; |
526 } | 526 } |
527 | 527 |
528 if (!isAllowedHTTPMethod(method)) { | 528 if (!isAllowedHTTPMethod(method)) { |
529 exceptionState.throwSecurityError(ExceptionMessages::failedToExecute("op
en", "XMLHttpRequest", "'" + method + "' HTTP method is unsupported.")); | 529 exceptionState.throwSecurityError("'" + method + "' HTTP method is unsup
ported."); |
530 return; | 530 return; |
531 } | 531 } |
532 | 532 |
533 if (!ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) && !ex
ecutionContext()->contentSecurityPolicy()->allowConnectToSource(url)) { | 533 if (!ContentSecurityPolicy::shouldBypassMainWorld(executionContext()) && !ex
ecutionContext()->contentSecurityPolicy()->allowConnectToSource(url)) { |
534 // We can safely expose the URL to JavaScript, as these checks happen sy
nchronously before redirection. JavaScript receives no new information. | 534 // We can safely expose the URL to JavaScript, as these checks happen sy
nchronously before redirection. JavaScript receives no new information. |
535 exceptionState.throwSecurityError("Refused to connect to '" + url.elided
String() + "' because it violates the document's Content Security Policy."); | 535 exceptionState.throwSecurityError("Refused to connect to '" + url.elided
String() + "' because it violates the document's Content Security Policy."); |
536 return; | 536 return; |
537 } | 537 } |
538 | 538 |
539 if (!async && executionContext()->isDocument()) { | 539 if (!async && executionContext()->isDocument()) { |
540 if (document()->settings() && !document()->settings()->syncXHRInDocument
sEnabled()) { | 540 if (document()->settings() && !document()->settings()->syncXHRInDocument
sEnabled()) { |
541 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessag
es::failedToExecute("open", "XMLHttpRequest", "synchronous requests are disabled
for this page.")); | 541 exceptionState.throwDOMException(InvalidAccessError, "Synchronous re
quests are disabled for this page."); |
542 return; | 542 return; |
543 } | 543 } |
544 | 544 |
545 // Newer functionality is not available to synchronous requests in windo
w contexts, as a spec-mandated | 545 // Newer functionality is not available to synchronous requests in windo
w contexts, as a spec-mandated |
546 // attempt to discourage synchronous XHR use. responseType is one such p
iece of functionality. | 546 // attempt to discourage synchronous XHR use. responseType is one such p
iece of functionality. |
547 // We'll only disable this functionality for HTTP(S) requests since sync
requests for local protocols | 547 // We'll only disable this functionality for HTTP(S) requests since sync
requests for local protocols |
548 // such as file: and data: still make sense to allow. | 548 // such as file: and data: still make sense to allow. |
549 if (url.protocolIsInHTTPFamily() && m_responseTypeCode != ResponseTypeDe
fault) { | 549 if (url.protocolIsInHTTPFamily() && m_responseTypeCode != ResponseTypeDe
fault) { |
550 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessag
es::failedToExecute("open", "XMLHttpRequest", "synchronous HTTP requests from a
document must not set a response type.")); | 550 exceptionState.throwDOMException(InvalidAccessError, "Synchronous HT
TP requests from a document must not set a response type."); |
551 return; | 551 return; |
552 } | 552 } |
553 | 553 |
554 // Similarly, timeouts are disabled for synchronous requests as well. | 554 // Similarly, timeouts are disabled for synchronous requests as well. |
555 if (m_timeoutMilliseconds > 0) { | 555 if (m_timeoutMilliseconds > 0) { |
556 exceptionState.throwDOMException(InvalidAccessError, ExceptionMessag
es::failedToExecute("open", "XMLHttpRequest", "synchronous requests must not set
a timeout.")); | 556 exceptionState.throwDOMException(InvalidAccessError, "Synchronous re
quests must not set a timeout."); |
557 return; | 557 return; |
558 } | 558 } |
559 } | 559 } |
560 | 560 |
561 m_method = uppercaseKnownHTTPMethod(method); | 561 m_method = uppercaseKnownHTTPMethod(method); |
562 | 562 |
563 m_url = url; | 563 m_url = url; |
564 | 564 |
565 m_async = async; | 565 m_async = async; |
566 | 566 |
(...skipping 23 matching lines...) Expand all Loading... |
590 | 590 |
591 open(method, urlWithCredentials, async, exceptionState); | 591 open(method, urlWithCredentials, async, exceptionState); |
592 } | 592 } |
593 | 593 |
594 bool XMLHttpRequest::initSend(ExceptionState& exceptionState) | 594 bool XMLHttpRequest::initSend(ExceptionState& exceptionState) |
595 { | 595 { |
596 if (!executionContext()) | 596 if (!executionContext()) |
597 return false; | 597 return false; |
598 | 598 |
599 if (m_state != OPENED || m_loader) { | 599 if (m_state != OPENED || m_loader) { |
600 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("send", "XMLHttpRequest", "the object's state must be OPENED.")); | 600 exceptionState.throwDOMException(InvalidStateError, "The object's state
must be OPENED."); |
601 return false; | 601 return false; |
602 } | 602 } |
603 | 603 |
604 m_error = false; | 604 m_error = false; |
605 return true; | 605 return true; |
606 } | 606 } |
607 | 607 |
608 void XMLHttpRequest::send(ExceptionState& exceptionState) | 608 void XMLHttpRequest::send(ExceptionState& exceptionState) |
609 { | 609 { |
610 send(String(), exceptionState); | 610 send(String(), exceptionState); |
(...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
757 { | 757 { |
758 m_requestEntityBody = formData ? formData->deepCopy() : 0; | 758 m_requestEntityBody = formData ? formData->deepCopy() : 0; |
759 createRequest(exceptionState); | 759 createRequest(exceptionState); |
760 m_exceptionCode = exceptionState.code(); | 760 m_exceptionCode = exceptionState.code(); |
761 } | 761 } |
762 | 762 |
763 void XMLHttpRequest::createRequest(ExceptionState& exceptionState) | 763 void XMLHttpRequest::createRequest(ExceptionState& exceptionState) |
764 { | 764 { |
765 // Only GET request is supported for blob URL. | 765 // Only GET request is supported for blob URL. |
766 if (m_url.protocolIs("blob") && m_method != "GET") { | 766 if (m_url.protocolIs("blob") && m_method != "GET") { |
767 exceptionState.throwDOMException(NetworkError, ExceptionMessages::failed
ToExecute("send", "XMLHttpRequest", "'GET' is the only method allowed for 'blob:
' URLs.")); | 767 exceptionState.throwDOMException(NetworkError, "'GET' is the only method
allowed for 'blob:' URLs."); |
768 return; | 768 return; |
769 } | 769 } |
770 | 770 |
771 // The presence of upload event listeners forces us to use preflighting beca
use POSTing to an URL that does not | 771 // The presence of upload event listeners forces us to use preflighting beca
use POSTing to an URL that does not |
772 // permit cross origin requests should look exactly like POSTing to an URL t
hat does not respond at all. | 772 // permit cross origin requests should look exactly like POSTing to an URL t
hat does not respond at all. |
773 // Also, only async requests support upload progress events. | 773 // Also, only async requests support upload progress events. |
774 bool uploadEvents = false; | 774 bool uploadEvents = false; |
775 if (m_async) { | 775 if (m_async) { |
776 m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::creat
e(EventTypeNames::loadstart)); | 776 m_progressEventThrottle.dispatchEvent(XMLHttpRequestProgressEvent::creat
e(EventTypeNames::loadstart)); |
777 if (m_requestEntityBody && m_upload) { | 777 if (m_requestEntityBody && m_upload) { |
(...skipping 271 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1049 } | 1049 } |
1050 | 1050 |
1051 void XMLHttpRequest::overrideMimeType(const String& override) | 1051 void XMLHttpRequest::overrideMimeType(const String& override) |
1052 { | 1052 { |
1053 m_mimeTypeOverride = override; | 1053 m_mimeTypeOverride = override; |
1054 } | 1054 } |
1055 | 1055 |
1056 void XMLHttpRequest::setRequestHeader(const AtomicString& name, const String& va
lue, ExceptionState& exceptionState) | 1056 void XMLHttpRequest::setRequestHeader(const AtomicString& name, const String& va
lue, ExceptionState& exceptionState) |
1057 { | 1057 { |
1058 if (m_state != OPENED || m_loader) { | 1058 if (m_state != OPENED || m_loader) { |
1059 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("setRequestHeader", "XMLHttpRequest", "the object's state must be
OPENED.")); | 1059 exceptionState.throwDOMException(InvalidStateError, ExceptionMessages::f
ailedToExecute("setRequestHeader", "XMLHttpRequest", "The object's state must be
OPENED.")); |
1060 return; | 1060 return; |
1061 } | 1061 } |
1062 | 1062 |
1063 if (!isValidHTTPToken(name)) { | 1063 if (!isValidHTTPToken(name)) { |
1064 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedT
oExecute("setRequestHeader", "XMLHttpRequest", "'" + name + "' is not a valid HT
TP header field name.")); | 1064 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedT
oExecute("setRequestHeader", "XMLHttpRequest", "'" + name + "' is not a valid HT
TP header field name.")); |
1065 return; | 1065 return; |
1066 } | 1066 } |
1067 | 1067 |
1068 if (!isValidHTTPHeaderValue(value)) { | 1068 if (!isValidHTTPHeaderValue(value)) { |
1069 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedT
oExecute("setRequestHeader", "XMLHttpRequest", "'" + value + "' is not a valid H
TTP header field value.")); | 1069 exceptionState.throwDOMException(SyntaxError, ExceptionMessages::failedT
oExecute("setRequestHeader", "XMLHttpRequest", "'" + value + "' is not a valid H
TTP header field value.")); |
(...skipping 324 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1394 { | 1394 { |
1395 return EventTargetNames::XMLHttpRequest; | 1395 return EventTargetNames::XMLHttpRequest; |
1396 } | 1396 } |
1397 | 1397 |
1398 ExecutionContext* XMLHttpRequest::executionContext() const | 1398 ExecutionContext* XMLHttpRequest::executionContext() const |
1399 { | 1399 { |
1400 return ActiveDOMObject::executionContext(); | 1400 return ActiveDOMObject::executionContext(); |
1401 } | 1401 } |
1402 | 1402 |
1403 } // namespace WebCore | 1403 } // namespace WebCore |
OLD | NEW |